Android framework服务命令行工具框架 - Android13
- 1、framework服务命令行工具简介
- 2、cmd 执行程序
- 2.1 目录和Android.bp
- 2.2 cmdMain 执行入口
- 2.3 cmd命令
- 3、am命令工具,实质脚本执行cmd activity
- 3.1 sh脚本
- 3.2 activity服务注册
- 3.3 onShellCommand执行
- 4、简易时序图
1、framework服务命令行工具简介
这里强调 “framework服务” ,主要就是bin命令模拟 framework服务 相关的查询和功能,如am\pm\input等;其实质就是
Android 提供了大多数常见的 Unix 命令行工具,说白了就是bin执行程序
。而 framework服务 命令行工具现在一般就是cmd
bin执行程序Binder获取对应服务,通过IBinder::shellCommand
调用对应服务的onShellCommand
。
2、cmd 执行程序
2.1 目录和Android.bp
frameworks/native/cmds/cmd/Android.bp
frameworks/native/cmds/cmd/cmd.cpp
2.2 cmdMain 执行入口
DEBUG
:默认关闭#define DEBUG 0
serviceName
:SM中注册的binder服务对应的名称,如ACTIVITY_SERVICE = "activity"
(ActivityManagerService)IBinder::shellCommand(service, in, out, err, args, cb, result)
:执行到对应服务onShellCommand
frameworks/native/cmds/cmd/cmd.cpp
int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog,int in, int out, int err, RunMode runMode) {sp<ProcessState> proc = ProcessState::self();proc->startThreadPool();#if DEBUGALOGD("cmd: starting");
#endifsp<IServiceManager> sm = defaultServiceManager();if (runMode == RunMode::kStandalone) {fflush(stdout);}if (sm == nullptr) {ALOGW("Unable to get default service manager!");errorLog << "cmd: Unable to get default service manager!" << endl;return 20;}int argc = argv.size();if (argc == 0) {errorLog << "cmd: No service specified; use -l to list all running services. Use -w to start and wait for a service." << endl;return 20;}if ((argc == 1) && (argv[0] == "-l")) {Vector<String16> services = sm->listServices();services.sort(sort_func);outputLog << "Currently running services:" << endl;for (size_t i=0; i<services.size(); i++) {sp<IBinder> service = sm->checkService(services[i]);if (service != nullptr) {outputLog << " " << services[i] << endl;}}return 0;}bool waitForService = ((argc > 1) && (argv[0] == "-w"));int serviceIdx = (waitForService) ? 1 : 0;const auto cmd = argv[serviceIdx];Vector<String16> args;String16 serviceName = String16(cmd.data(), cmd.size());for (int i = serviceIdx + 1; i < argc; i++) {args.add(String16(argv[i].data(), argv[i].size()));}sp<IBinder> service;if(waitForService) {service = sm->waitForService(serviceName);} else {service = sm->checkService(serviceName);}if (service == nullptr) {if (runMode == RunMode::kStandalone) {ALOGW("Can't find service %.*s", static_cast<int>(cmd.size()), cmd.data());}errorLog << "cmd: Can't find service: " << cmd << endl;return 20;}sp<MyShellCallback> cb = new MyShellCallback(errorLog);sp<MyResultReceiver> result = new MyResultReceiver();#if DEBUGALOGD("cmd: Invoking %.*s in=%d, out=%d, err=%d",static_cast<int>(cmd.size()), cmd.data(), in, out, err);
#endif// TODO: block until a result is returned to MyResultReceiver.status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);if (error < 0) {const char* errstr;switch (error) {case BAD_TYPE: errstr = "Bad type"; break;case FAILED_TRANSACTION: errstr = "Failed transaction"; break;case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;case UNEXPECTED_NULL: errstr = "Unexpected null"; break;default: errstr = strerror(-error); break;}if (runMode == RunMode::kStandalone) {ALOGW("Failure calling service %.*s: %s (%d)", static_cast<int>(cmd.size()), cmd.data(),errstr, -error);}outputLog << "cmd: Failure calling service " << cmd << ": " << errstr << " (" << (-error)<< ")" << endl;return error;}cb->mActive = false;status_t res = result->waitForResult();
#if DEBUGALOGD("result=%d", (int)res);
#endifreturn res;
}
2.3 cmd命令
-
cmd
-
cmd -l
列出SM中注册的服务
-
cmd activity
3、am命令工具,实质脚本执行cmd activity
3.1 sh脚本
这里am工具为例。Android 提供了大多数常见的 Unix 命令行工具,查看可用工具的列表:
adb shell ls /system/bin
frameworks/base/cmds/am/am
#!/system/bin/shif [ "$1" != "instrument" ] ; thencmd activity "$@"
elsebase=/systemexport CLASSPATH=$base/framework/am.jarexec app_process $base/bin com.android.commands.am.Am "$@"
fi
3.2 activity服务注册
activity
服务就是ActivityManagerService
注册的Context.ACTIVITY_SERVICE
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setSystemProcess() {try {ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_HIGH);ServiceManager.addService("gfxinfo", new GraphicsBinder(this));ServiceManager.addService("dbinfo", new DbBinder(this));mAppProfiler.setCpuInfoService();ServiceManager.addService("permission", new PermissionController(this));ServiceManager.addService("processinfo", new ProcessInfoService(this));ServiceManager.addService("cacheinfo", new CacheBinder(this));//... ... ... ...
}
3.3 onShellCommand执行
ActivityManagerShellCommand
专门处理am
相关命令,这里具体功能不展开细说。
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);
}
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) {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 "compact":return runCompact(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 "clear-exit-info":return runClearExitInfo(pw);case "bug-report":return runBugReport(pw);case "force-stop":return runForceStop(pw);case "stop-app":return runStopApp(pw);case "fgs-notification-rate-limit":return runFgsNotificationRateLimit(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);case "refresh-settings-cache":return runRefreshSettingsCache();case "memory-factor":return runMemoryFactor(pw);case "service-restart-backoff":return runServiceRestartBackoff(pw);case "get-isolated-pids":return runGetIsolatedProcesses(pw);case "set-stop-user-on-switch":return runSetStopUserOnSwitch(pw);case "set-bg-abusive-uids":return runSetBgAbusiveUids(pw);case "list-bg-exemptions-config":return runListBgExemptionsConfig(pw);default:return handleDefaultCommands(cmd);}} catch (RemoteException e) {pw.println("Remote exception: " + e);}return -1;
}