-
public static synchronized void runShell() {
-
ProcessBuilder pb = new ProcessBuilder("/system/bin/sh");
-
// java.lang.ProcessBuilder: Creates operating system processes.
-
pb.directory(new File("/system/bin"));// 設置shell的當前目錄。
-
try {
-
Process proc = pb.start();
-
// 獲取輸入流,能夠經過它獲取SHELL的輸出。
-
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
-
BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
-
// 獲取輸出流,能夠經過它向SHELL發送命令。
-
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
-
out.println("pwd");
-
out.println("su root");// 執行這一句時會彈出對話框(如下程序要求授予最高權限...),要求用戶確認。
-
// out.println("cat /proc/version");
-
// out.println("monkey -v 500");
-
// out.println("cd /data/data");//這個目錄在系統中要求有root權限才能夠訪問的。
-
// out.println("ls -l");//這個命令若是能列出當前安裝的APK的數據文件存放目錄,就說明咱們有了ROOT權限。
-
out.println("exit");
-
// proc.waitFor();
-
String line;
-
while ((line = in.readLine()) != null) {
-
System.out.println(line); // 打印輸出結果
-
}
-
while ((line = err.readLine()) != null) {
-
System.out.println(line); // 打印錯誤輸出結果
-
}
-
in.close();
-
out.close();
-
proc.destroy();
-
} catch (Exception e) {
-
System.out.println("exception:" + e);
-
}
-
}
-
/**
-
* 執行shell
-
*
-
* @return 0:成功,其它爲失敗。
-
*/
-
public static synchronized int runShellCmd() {
-
BufferedReader input = null;
-
PrintWriter output = null;
-
Process pro = null;
-
try {
-
pro = Runtime.getRuntime().exec("adb shell ");
-
input = new BufferedReader(new InputStreamReader(pro.getInputStream()));
-
pro.getOutputStream().write("pidof mediaserver\r\n".getBytes());
-
pro.getOutputStream().flush();
-
String line = input.readLine();
-
int pid = 0;
-
/**
-
* 按道理說直接執行命令打印是這樣的:
-
* root@android:/ # adb shell
-
* root@android:/ # pidof mediaserver
-
* 7114
-
* 也就是說第三行就應該是我取到的pid值,可是實際上倒是5行?
-
*/
-
for (int i = 0; i < 6; i++) {
-
Log.e(TAG , i + " line is " + line);
-
pid = toInt(line, 0);
-
if (pid > 0)
-
break;
-
line = input.readLine();
-
}
-
Log.e(TAG, "pid:" + pid);
-
/**
-
* 實際打印以下:
-
* E/MainActivity( 7036): 0 line is pidof mediaserver
-
* E/MainActivity( 7036): 1 line is
-
* E/MainActivity( 7036): 2 line is root@android:/ # pidof mediaserver
-
* E/MainActivity( 7036): 3 line is
-
* E/MainActivity( 7036): 4 line is 6946
-
* E/MainActivity( 7036): pid:6946
-
* 爲何會多出2個空行??
-
*/
-
if (pid == 0) {
-
throw new IOException("not find mediaserver process!");
-
}
-
String killCmd = String.format("kill -9 %d\r\n", pid);
-
/**
-
* 直接這麼使用不行的,不知道什麼緣由,執行結果死活不對。
-
*/
-
pro.getOutputStream().write(killCmd.getBytes());
-
pro.getOutputStream().flush();
-
-
/**
-
* 再一次這麼重開就ok了,誰能告訴我緣由?
-
*/
-
pro.destroy();
-
pro = null;
-
pro = Runtime.getRuntime().exec("adb shell ");
-
pro.getOutputStream().write(killCmd.getBytes());
-
pro.getOutputStream().flush();
-
-
-
} catch (IOException ex) {
-
ex.printStackTrace();
-
return -1;
-
} finally {
-
try {
-
if (input != null) {
-
input.close();
-
}
-
if (output != null) {
-
output.close();
-
}
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
if (pro != null) {
-
pro.destroy();
-
pro = null;
-
}
-
}
-
return 0;
-
}
-
/**
-
* Executes the specified command and its arguments in a separate native
-
* process. The new process uses the environment provided in {@code envp}
-
* and the working directory specified by {@code directory}.
-
*
-
* @param progArray
-
* the array containing the program to execute as well as any
-
* arguments to the program.
-
* @param envp
-
* the array containing the environment to start the new process
-
* in.
-
* @param directory
-
* the directory in which to execute the program. If {@code null},
-
* execute if in the same directory as the parent process.
-
* @return the new {@code Process} object that represents the native
-
* process.
-
* @throws IOException
-
* if the requested program can not be executed.
-
* @throws SecurityException
-
* if the current {@code SecurityManager} disallows program
-
* execution.
-
* @see SecurityManager#checkExec
-
* @since Android 1.0
-
*/
-
public Process exec(String[] progArray, String[] envp, File directory) throws IOException {
-
// BEGIN android-changed: push responsibility for argument checking into ProcessManager
-
return ProcessManager.getInstance().exec(progArray, envp, directory, false);
-
// END android-changed
-
}
-
/**
-
* Map from pid to Process. We keep weak references to the Process objects
-
* and clean up the entries when no more external references are left. The
-
* process objects themselves don't require much memory, but file
-
* descriptors (associated with stdin/out/err in this case) can be
-
* a scarce resource.
-
*/
-
private final Map<Integer, ProcessReference> processReferences
-
= new HashMap<Integer, ProcessReference>();
-
/**
-
* Executes a process and returns an object representing it.
-
*/
-
Process exec(String[] taintedCommand, String[] taintedEnvironment, File workingDirectory,
-
boolean redirectErrorStream) throws IOException {
-
// Make sure we throw the same exceptions as the RI.
-
if (taintedCommand == null) {
-
throw new NullPointerException();
-
}
-
if (taintedCommand.length == 0) {
-
throw new IndexOutOfBoundsException();
-
}
-
-
// Handle security and safety by copying mutable inputs and checking them.
-
String[] command = taintedCommand.clone();
-
String[] environment = taintedEnvironment != null ? taintedEnvironment.clone() : null;
-
SecurityManager securityManager = System.getSecurityManager();
-
if (securityManager != null) {
-
securityManager.checkExec(command[0]);//權限檢查
-
}
-
// Check we're not passing null Strings to the native exec.
-
for (String arg : command) {
-
if (arg == null) {
-
throw new NullPointerException();
-
}
-
}
-
// The environment is allowed to be null or empty, but no element may be null.
-
if (environment != null) {
-
for (String env : environment) {
-
if (env == null) {
-
throw new NullPointerException();
-
}
-
}
-
}
-
-
FileDescriptor in = new FileDescriptor();
-
FileDescriptor out = new FileDescriptor();
-
FileDescriptor err = new FileDescriptor();
-
-
String workingPath = (workingDirectory == null)
-
? null
-
: workingDirectory.getPath();
-
-
// Ensure onExit() doesn't access the process map before we add our
-
// entry.
-
synchronized (processReferences) {
-
int pid;
-
try {
-
/**
-
* 調用exec函數
-
*/
-
pid = exec(command, environment, workingPath, in, out, err, redirectErrorStream);
-
} catch (IOException e) {
-
IOException wrapper = new IOException("Error running exec()."
-
+ " Command: " + Arrays.toString(command)
-
+ " Working Directory: " + workingDirectory
-
+ " Environment: " + Arrays.toString(environment));
-
wrapper.initCause(e);
-
throw wrapper;
-
}
-
/**
-
* 新建一個進程實現。
-
*/
-
ProcessImpl process = new ProcessImpl(pid, in, out, err);
-
/**
-
* 建立一個進程引用。
-
*/
-
ProcessReference processReference
-
= new ProcessReference(process, referenceQueue);
-
-
/**
-
* 加入到全局進程引用map中。
-
*/
-
processReferences.put(pid, processReference);
-
-
/*
-
* This will wake up the child monitor thread in case there
-
* weren't previously any children to wait on.
-
*/
-
processReferences.notifyAll();
-
-
return process;
-
}
-
}
-
//Android 4.0.3在
-
./libcore/luni/src/main/native/java_lang_ProcessManager.cpp
-
//Android 2.2在
-
./dalvik/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.cpp
-
//源碼爲:
-
/**
-
* Converts Java String[] to char** and delegates to executeProcess().
-
*/
-
static pid_t java_lang_ProcessManager_exec(
-
JNIEnv* env, jclass clazz, jobjectArray javaCommands,
-
jobjectArray javaEnvironment, jstring javaWorkingDirectory,
-
jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
-
jboolean redirectErrorStream) {
-
-
// Copy commands into char*[].
-
char** commands = convertStrings(env, javaCommands);
-
-
// Extract working directory string.
-
const char* workingDirectory = NULL;
-
if (javaWorkingDirectory != NULL) {
-
workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
-
}
-
-
// Convert environment array.
-
char** environment = convertStrings(env, javaEnvironment);
-
-
//關鍵就這一行.
-
pid_t result = executeProcess(
-
env, commands, environment, workingDirectory,
-
inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);
-
-
// Temporarily clear exception so we can clean up.
-
jthrowable exception = env->ExceptionOccurred();
-
env->ExceptionClear();
-
-
freeStrings(env, javaEnvironment, environment);
-
-
// Clean up working directory string.
-
if (javaWorkingDirectory != NULL) {
-
env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
-
}
-
-
freeStrings(env, javaCommands, commands);
-
-
// Re-throw exception if present.
-
if (exception != NULL) {
-
if (env->Throw(exception) < 0) {
-
LOGE("Error rethrowing exception!");
-
}
-
}
-
-
return result;
-
}
-
/** Executes a command in a child process. */
-
static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
-
const char* workingDirectory, jobject inDescriptor,
-
jobject outDescriptor, jobject errDescriptor,
-
jboolean redirectErrorStream) {
-
int i, result, error;
-
-
// Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
-
int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-
for (i = 0; i < PIPE_COUNT; i++) {
-
if (pipe(pipes + i * 2) == -1) {
-
jniThrowIOException(env, errno);
-
closePipes(pipes, -1);
-
return -1;
-
}
-
}
-
int stdinIn = pipes[0];
-
int stdinOut = pipes[1];
-
int stdoutIn = pipes[2];
-
int stdoutOut = pipes[3];
-
int stderrIn = pipes[4];
-
int stderrOut = pipes[5];
-
int statusIn = pipes[6];
-
int statusOut = pipes[7];
-
-
pid_t childPid = fork();
-
-
// If fork() failed...
-
if (childPid == -1) {
-
jniThrowIOException(env, errno);
-
closePipes(pipes, -1);
-
return -1;
-
}
-
-
// If this is the child process...
-
if (childPid == 0) {
-
/*
-
* Note: We cannot malloc() or free() after this point!
-
* A no-longer-running thread may be holding on to the heap lock, and
-
* an attempt to malloc() or free() would result in deadlock.
-
*/
-
-
// Replace stdin, out, and err with pipes.
-
dup2(stdinIn, 0);
-
dup2(stdoutOut, 1);
-
if (redirectErrorStream) {
-
dup2(stdoutOut, 2);
-
} else {
-
dup2(stderrOut, 2);
-
}
-
-
// Close all but statusOut. This saves some work in the next step.
-
closePipes(pipes, statusOut);
-
-
// Make statusOut automatically close if execvp() succeeds.
-
fcntl(statusOut, F_SETFD, FD_CLOEXEC);
-
-
// Close remaining open fds with the exception of statusOut.
-
closeNonStandardFds(statusOut);
-
-
// Switch to working directory.
-
if (workingDirectory != NULL) {
-
if (chdir(workingDirectory) == -1) {
-
goto execFailed;
-
}
-
}
-
-
// Set up environment.
-
if (environment != NULL) {
-
environ = environment;
-
}
-
-
// Execute process. By convention, the first argument in the arg array
-
// should be the command itself. In fact, I get segfaults when this
-
// isn't the case.
-
execvp(commands[0], commands);
-
-
// If we got here, execvp() failed or the working dir was invalid.
-
execFailed:
-
error = errno;
-
write(statusOut, &error, sizeof(int));
-
close(statusOut);
-
exit(error);
-
}
-
-
// This is the parent process.
-
-
// Close child's pipe ends.
-
close(stdinIn);
-
close(stdoutOut);
-
close(stderrOut);
-
close(statusOut);
-
-
// Check status pipe for an error code. If execvp() succeeds, the other
-
// end of the pipe should automatically close, in which case, we'll read
-
// nothing.
-
int count = read(statusIn, &result, sizeof(int));
-
close(statusIn);
-
if (count > 0) {
-
jniThrowIOException(env, result);
-
-
close(stdoutIn);
-
close(stdinOut);
-
close(stderrIn);
-
-
return -1;
-
}
-
-
// Fill in file descriptor wrappers.
-
jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
-
jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
-
jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);
-
-
return childPid;
-
}
-
/**
-
* Starts a new process based on the current state of this process builder.
-
*
-
* @return the new {@code Process} instance.
-
* @throws NullPointerException
-
* if any of the elements of {@link #command()} is {@code null}.
-
* @throws IndexOutOfBoundsException
-
* if {@link #command()} is empty.
-
* @throws SecurityException
-
* if {@link SecurityManager#checkExec(String)} doesn't allow
-
* process creation.
-
* @throws IOException
-
* if an I/O error happens.
-
*/
-
public Process start() throws IOException {
-
// BEGIN android-changed: push responsibility for argument checking into ProcessManager
-
String[] cmdArray = command.toArray(new String[command.size()]);
-
String[] envArray = new String[environment.size()];
-
int i = 0;
-
for (Map.Entry<String, String> entry : environment.entrySet()) {
-
envArray[i++] = entry.getKey() + "=" + entry.getValue(); //$NON-NLS-1$
-
}
-
//和Runtime.exec的同樣。
-
return ProcessManager.getInstance().exec(cmdArray, envArray, directory, redirectErrorStream);
-
// END android-changed
-
}