赞
踩
大家都知道 adb shell 后可以执行很多命令,这里我们主要是介绍 adb shell 进入后是如何执行那些代码命令的,这里我们就以 “am start ” 命令来说。绝大多的命令代码都是在 frameworks/base/cmds 这个目录下的,am 命令也不例外。
am 的开始是由一段脚步执行的。同时am 底下的 Android.bp 会将相关代码编译成一个 am.jar Java可执行库。
# frameworks/base/cmds/am/am
#!/system/bin/sh
if [ "$1" != "instrument" ] ; then
cmd activity "$@"
else
base=/system
export CLASSPATH=$base/framework/am.jar
exec app_process $base/bin com.android.commands.am.Am "$@"
fi
// frameworks/base/cmds/am/src/com/android/commands/am/Am.java
public static void main(String[] args) {
(new Am()).run(args);
}
// frameworks/base/core/java/com/android/internal/os/BaseCommand.java /** * Call to run the command. */ public void run(String[] args) { if (args.length < 1) { onShowUsage(System.out); return; } mRawArgs = args; mArgs.init(null, null, null, null, args, null, 0); try { onRun(); // 下一步入口 } catch (IllegalArgumentException e) { onShowUsage(System.err); System.err.println(); System.err.println("Error: " + e.getMessage()); } catch (Exception e) { e.printStackTrace(System.err); System.exit(1); } }
// frameworks/base/cmds/am/src/com/android/commands/am/Am.java @Override public void onRun() throws Exception { mAm = ActivityManager.getService();// 记着这里 if (mAm == null) { System.err.println(NO_SYSTEM_ERROR_CODE); throw new AndroidException("Can't connect to activity manager; is the system running?"); } mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); if (mPm == null) { System.err.println(NO_SYSTEM_ERROR_CODE); throw new AndroidException("Can't connect to package manager; is the system running?"); } String op = nextArgRequired(); if (op.equals("instrument")) { runInstrument(); //这里是通过 Instrument启动 读者自行分析。 } else { runAmCmd(getRawArgs());// 这里是通过正常startactivity 启动。 } } // 细品一些这个runAmCmd, 你好好品品。 void runAmCmd(String[] args) throws AndroidException { final MyShellCallback cb = new MyShellCallback(); try { mAm.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err, args, cb, new ResultReceiver(null) { }); //终于走到了常规套路。 } catch (RemoteException e) { System.err.println(NO_SYSTEM_ERROR_CODE); throw new AndroidException("Can't call activity manager; is the system running?"); } finally { cb.mActive = false; } }
//frameworks/base/core/java/android/os/Binder.java
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
// 看 AMS
onShellCommand(in, out, err, args, callback, resultReceiver);
}
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new ActivityManagerShellCommand(this, false)).exec(
this, in, out, err, args, callback, resultReceiver);
}
ActivityManagerShellCommand 是继承自 ShellCommand类,这个 exec 是在 ShellCommand 里的,主要用来初始化一些参数和环境
// frameworks/base/core/java/android/os/ShellCommand.java public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { String cmd; int start; if (args != null && args.length > 0) { cmd = args[0]; start = 1; } else { cmd = null; start = 0; } init(target, in, out, err, args, callback, start); mCmd = cmd; mResultReceiver = resultReceiver; if (DEBUG) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget, here); Slog.d(TAG, "Calling uid=" + Binder.getCallingUid() + " pid=" + Binder.getCallingPid() + " ShellCallback=" + getShellCallback()); } int res = -1; try { res = onCommand(mCmd); // 回掉主要接口函数 if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget); } catch (SecurityException e) { PrintWriter eout = getErrPrintWriter(); eout.println("Security exception: " + e.getMessage()); eout.println(); e.printStackTrace(eout); } catch (Throwable e) { // Unlike usual calls, in this case if an exception gets thrown // back to us we want to print it back in to the dump data, since // that is where the caller expects all interesting information to // go. PrintWriter eout = getErrPrintWriter(); eout.println(); eout.println("Exception occurred while executing:"); e.printStackTrace(eout); } finally { if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget); if (mOutPrintWriter != null) { mOutPrintWriter.flush(); } if (mErrPrintWriter != null) { mErrPrintWriter.flush(); } if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget); if (mResultReceiver != null) { mResultReceiver.send(res, null); } } if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget); return res; }
所有 am 的命令接在此了。
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @Override public int onCommand(String cmd) { if (cmd == null) { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); try { switch (cmd) { // 这就是使用‘am start’ 和 ‘am start-activity’ 是相同结果了。 case "start": case "start-activity": return runStartActivity(pw); case "startservice": case "start-service": return runStartService(pw, false); case "startforegroundservice": case "startfgservice": case "start-foreground-service": case "start-fg-service": return runStartService(pw, true); case "stopservice": case "stop-service": return runStopService(pw); case "broadcast": return runSendBroadcast(pw); case "instrument": getOutPrintWriter().println("Error: must be invoked through 'am instrument'."); return -1; case "trace-ipc": return runTraceIpc(pw); case "profile": return runProfile(pw); case "dumpheap": return runDumpHeap(pw); case "set-debug-app": return runSetDebugApp(pw); case "set-agent-app": return runSetAgentApp(pw); case "clear-debug-app": return runClearDebugApp(pw); case "set-watch-heap": return runSetWatchHeap(pw); case "clear-watch-heap": return runClearWatchHeap(pw); case "bug-report": return runBugReport(pw); case "force-stop": return runForceStop(pw); case "crash": return runCrash(pw); case "kill": return runKill(pw); case "kill-all": return runKillAll(pw); case "make-uid-idle": return runMakeIdle(pw); case "monitor": return runMonitor(pw); case "watch-uids": return runWatchUids(pw); case "hang": return runHang(pw); case "restart": return runRestart(pw); case "idle-maintenance": return runIdleMaintenance(pw); case "screen-compat": return runScreenCompat(pw); case "package-importance": return runPackageImportance(pw); case "to-uri": return runToUri(pw, 0); case "to-intent-uri": return runToUri(pw, Intent.URI_INTENT_SCHEME); case "to-app-uri": return runToUri(pw, Intent.URI_ANDROID_APP_SCHEME); case "switch-user": return runSwitchUser(pw); case "get-current-user": return runGetCurrentUser(pw); case "start-user": return runStartUser(pw); case "unlock-user": return runUnlockUser(pw); case "stop-user": return runStopUser(pw); case "is-user-stopped": return runIsUserStopped(pw); case "get-started-user-state": return runGetStartedUserState(pw); case "track-associations": return runTrackAssociations(pw); case "untrack-associations": return runUntrackAssociations(pw); case "get-uid-state": return getUidState(pw); case "get-config": return runGetConfig(pw); case "suppress-resize-config-changes": return runSuppressResizeConfigChanges(pw); case "set-inactive": return runSetInactive(pw); case "get-inactive": return runGetInactive(pw); case "set-standby-bucket": return runSetStandbyBucket(pw); case "get-standby-bucket": return runGetStandbyBucket(pw); case "send-trim-memory": return runSendTrimMemory(pw); case "display": return runDisplay(pw); case "stack": return runStack(pw); case "task": return runTask(pw); case "write": return runWrite(pw); case "attach-agent": return runAttachAgent(pw); case "supports-multiwindow": return runSupportsMultiwindow(pw); case "supports-split-screen-multi-window": return runSupportsSplitScreenMultiwindow(pw); case "update-appinfo": return runUpdateApplicationInfo(pw); case "no-home-screen": return runNoHomeScreen(pw); case "wait-for-broadcast-idle": return runWaitForBroadcastIdle(pw); case "compat": return runCompat(pw); default: return handleDefaultCommands(cmd); } } catch (RemoteException e) { pw.println("Remote exception: " + e); } return -1; } 其实分析到这里就可以结束了,耐不住好奇继续看吧 比较长的方法 int runStartActivity(PrintWriter pw) throws RemoteException { Intent intent; try { // 构建 Intent 这里面有玄机 intent = makeIntent(UserHandle.USER_CURRENT); } catch (URISyntaxException e) { throw new RuntimeException(e.getMessage(), e); } if (mUserId == UserHandle.USER_ALL) { getErrPrintWriter().println("Error: Can't start service with user 'all'"); return 1; } String mimeType = intent.getType(); if (mimeType == null && intent.getData() != null && "content".equals(intent.getData().getScheme())) { mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId); } do { if (mStopOption) { String packageName; if (intent.getComponent() != null) { packageName = intent.getComponent().getPackageName(); } else { // queryIntentActivities does not convert user id, so we convert it here first int userIdForQuery = mInternal.mUserController.handleIncomingUser( Binder.getCallingPid(), Binder.getCallingUid(), mUserId, false, ALLOW_NON_FULL, "ActivityManagerShellCommand", null); List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0, userIdForQuery).getList(); if (activities == null || activities.size() <= 0) { getErrPrintWriter().println("Error: Intent does not match any activities: " + intent); return 1; } else if (activities.size() > 1) { getErrPrintWriter().println( "Error: Intent matches multiple activities; can't stop: " + intent); return 1; } packageName = activities.get(0).activityInfo.packageName; } pw.println("Stopping: " + packageName); pw.flush(); mInterface.forceStopPackage(packageName, mUserId); try { Thread.sleep(250); } catch (InterruptedException e) { } } ProfilerInfo profilerInfo = null; if (mProfileFile != null || mAgent != null) { ParcelFileDescriptor fd = null; if (mProfileFile != null) { fd = openFileForSystem(mProfileFile, "w"); if (fd == null) { return 1; } } profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop, mStreaming, mAgent, mAttachAgentDuringBind); } pw.println("Starting: " + intent); pw.flush(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); WaitResult result = null; int res; final long startTime = SystemClock.uptimeMillis(); // 构建启动项,不会启动activity 可以在这里学习,细品 ActivityOptions options = null; if (mDisplayId != INVALID_DISPLAY) { options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(mDisplayId); } if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLaunchWindowingMode(mWindowingMode); } if (mActivityType != ACTIVITY_TYPE_UNDEFINED) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLaunchActivityType(mActivityType); } if (mTaskId != INVALID_TASK_ID) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLaunchTaskId(mTaskId); if (mIsTaskOverlay) { options.setTaskOverlay(true, true /* canResume */); } } if (mIsLockTask) { if (options == null) { options = ActivityOptions.makeBasic(); } options.setLockTaskEnabled(true); } // 开始启动了,3 、2、1 点火。 if (mWaitOption) { result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); res = result.result; } else { res = mInternal.startActivityAsUser(null, SHELL_PACKAGE_NAME, intent, mimeType, null, null, 0, mStartFlags, profilerInfo, options != null ? options.toBundle() : null, mUserId); } final long endTime = SystemClock.uptimeMillis(); PrintWriter out = mWaitOption ? pw : getErrPrintWriter(); boolean launched = false; // 检查结果,汇到情况。 switch (res) { case ActivityManager.START_SUCCESS: launched = true; break; case ActivityManager.START_SWITCHES_CANCELED: launched = true; out.println( "Warning: Activity not started because the " + " current activity is being kept for the user."); break; case ActivityManager.START_DELIVERED_TO_TOP: launched = true; out.println( "Warning: Activity not started, intent has " + "been delivered to currently running " + "top-most instance."); break; case ActivityManager.START_RETURN_INTENT_TO_CALLER: launched = true; out.println( "Warning: Activity not started because intent " + "should be handled by the caller"); break; case ActivityManager.START_TASK_TO_FRONT: launched = true; out.println( "Warning: Activity not started, its current " + "task has been brought to the front"); break; case ActivityManager.START_INTENT_NOT_RESOLVED: out.println( "Error: Activity not started, unable to " + "resolve " + intent.toString()); break; case ActivityManager.START_CLASS_NOT_FOUND: out.println(NO_CLASS_ERROR_CODE); out.println("Error: Activity class " + intent.getComponent().toShortString() + " does not exist."); break; case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: out.println( "Error: Activity not started, you requested to " + "both forward and receive its result"); break; case ActivityManager.START_PERMISSION_DENIED: out.println( "Error: Activity not started, you do not " + "have permission to access it."); break; case ActivityManager.START_NOT_VOICE_COMPATIBLE: out.println( "Error: Activity not started, voice control not allowed for: " + intent); break; case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY: out.println( "Error: Not allowed to start background user activity" + " that shouldn't be displayed for all users."); break; default: out.println( "Error: Activity not started, unknown error code " + res); break; } out.flush(); if (mWaitOption && launched) { if (result == null) { result = new WaitResult(); result.who = intent.getComponent(); } pw.println("Status: " + (result.timeout ? "timeout" : "ok")); pw.println("LaunchState: " + launchStateToString(result.launchState)); if (result.who != null) { pw.println("Activity: " + result.who.flattenToShortString()); } if (result.totalTime >= 0) { pw.println("TotalTime: " + result.totalTime); } pw.println("WaitTime: " + (endTime-startTime)); pw.println("Complete"); pw.flush(); } mRepeat--; if (mRepeat > 0) { mTaskInterface.unhandledBack(); } } while (mRepeat > 0); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。