主要分析下列 2 个流程:
// dump activity 的一些信息
adb shell dumpsys activity > D:\dumpsys\activity2.txt
// a11 打开 ActivityManagerDebugConfig 的开关
adb shell cmd activity log_switch enable DEBUG_ALL
还可以使用下列命令dump 具体的组件
adb shell dumpsys activity -a a // -a 是dump全部,a 是 activities
/frameworks/native/cmds/dumpsys/main.cpp
int main(int argc, char* const argv[]) {
signal(SIGPIPE, SIG_IGN);
sp sm = defaultServiceManager();
fflush(stdout);
if (sm == nullptr) {
ALOGE("Unable to get default service manager!");
std::cerr << "dumpsys: Unable to get default service manager!" << std::endl;
return 20;
}
Dumpsys dumpsys(sm.get());
// 执行 dumpsys 的 main 方法
return dumpsys.main(argc, argv);
}
// 执行 dumpsys 的 main 方法
/frameworks/native/cmds/dumpsys/dumpsys.cpp
int Dumpsys::main(int argc, char* const argv[]) {
Vector services;
Vector args;
String16 priorityType;
Vector skippedServices;
Vector protoServices;
Type type = Type::DUMP;
。。。
optind = 1;
。。。
for (int i = optind; i < argc; i++) {
if (skipServices) {
skippedServices.add(String16(argv[i]));
} else {
// 将输入的servicename 保存到 services 中,如adb shell dumpsys activity -a a
// 则将 activity 保存到 services 中
if (i == optind) {
services.add(String16(argv[i]));
} else {
const String16 arg(argv[i]);
// args 保存其他参数 -a a
args.add(arg);
const size_t N = services.size();
。。。。
for (size_t i = 0; i < N; i++) {
const String16& serviceName = services[i];
if (IsSkipped(skippedServices, serviceName)) continue;
// 调用startDumpThread 方法 type 类型为 DUMP
if (startDumpThread(type, serviceName, args) == OK) {
bool addSeparator = (N > 1);
if (addSeparator) {
writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
}
std::chrono::duration elapsedDuration;
size_t bytesWritten = 0;
// 输出结果
status_t status =
writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(timeoutArgMs),
asProto, elapsedDuration, bytesWritten);
==========
// 调用startDumpThread 方法 type 类型为 DUMP
status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
const Vector& args) {
// 找到对应服务的客户端
sp service = sm_->checkService(serviceName);
if (service == nullptr) {
std::cerr << "Can't find service: " << serviceName << std::endl;
return NAME_NOT_FOUND;
}
int sfd[2];
// 管道通信
if (pipe(sfd) != 0) {
std::cerr << "Failed to create pipe to dump service info for " << serviceName << ": "
<< strerror(errno) << std::endl;
return -errno;
}
redirectFd_ = unique_fd(sfd[0]);
unique_fd remote_end(sfd[1]);
sfd[0] = sfd[1] = -1;
// dump blocks until completion, so spawn a thread..
activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
status_t err = 0;
switch (type) {
case Type::DUMP:
// binder 通信调用dump 方法
err = service->dump(remote_end.get(), args);
break;
// binder 通信调用dump 方法
/frameworks/native/libs/binder/BpBinder.cpp
status_t BpBinder::dump(int fd, const Vector& args)
{
Parcel send;
Parcel reply;
// send 封装了文件描述符
send.writeFileDescriptor(fd);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
for (size_t i = 0; i < numArgs; i++) {
// 保存了 args 参数
send.writeString16(args[i]);
}
status_t err = transact(DUMP_TRANSACTION, send, &reply);
return err;
}
=========
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
// don't send userspace flags to the kernel
flags = flags & ~FLAG_PRIVATE_VENDOR;
// user transactions require a given stability level
if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
using android::internal::Stability;
auto stability = Stability::get(this);
auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
if (CC_UNLIKELY(!Stability::check(stability, required))) {
ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
Stability::stabilityString(stability).c_str(),
Stability::stabilityString(required).c_str());
return BAD_TYPE;
}
}
/// 通过binder 驱动去找到对端服务器端
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
===========服务端执行流程===========
走到服务器端的 BBinder
/frameworks/base/core/jni/android_util_Binder.cpp
// javabinder 继承了 BBinder
class JavaBBinder : public BBinder
{
public:
JavaBBinder(JNIEnv* env, jobject /* Java Binder */ object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
。。。
status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override
{
JNIEnv* env = javavm_to_jnienv(mVM);
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
//printf("Transact from %p to Java code sending: ", this);
//data.print();
//printf("\n");
// 调用java 层的execTransact 方法
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast(&data), reinterpret_cast(reply), flags);
// mExecTransact 为java 层的 execTransact 方法
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
// 调用java 层的execTransact 方法
/frameworks/base/core/java/android/os/Binder.java
@UnsupportedAppUsage
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
// At that point, the parcel request headers haven't been parsed so we do not know what
// WorkSource the caller has set. Use calling uid as the default.
final int callingUid = Binder.getCallingUid();
final long origWorkSource = ThreadLocalWorkSource.setUid(callingUid);
try {
return execTransactInternal(code, dataObj, replyObj, flags, callingUid);
===========
private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags,
int callingUid) {
final BinderInternal.Observer observer = sObserver;
final CallSession callSession =
observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null;
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
// If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
final boolean tracingEnabled = Binder.isTracingEnabled();
try {
if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0) {
AppOpsManager.startNotedAppOpsCollection(callingUid);
try {
res = onTransact(code, data, reply, flags);
} finally {
AppOpsManager.finishNotedAppOpsCollection();
}
} else {
// 调用 onTransact 方法
res = onTransact(code, data, reply, flags);
}
=============
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
// 如果是dump 命令,则执行 dump 方法
} else if (code == DUMP_TRANSACTION) {
ParcelFileDescriptor fd = data.readFileDescriptor();
String[] args = data.readStringArray();
if (fd != null) {
try {
dump(fd.getFileDescriptor(), args);
// 如果是 adb shell cmd,则调用 shellCommand 方法
} else if (code == SHELL_COMMAND_TRANSACTION) {
ParcelFileDescriptor in = data.readFileDescriptor();
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
args, shellCallback, resultReceiver);
}
=========
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
doDump(fd, pw, args);
=========
void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
final String disabled = sDumpDisabled;
if (disabled == null) {
try {
dump(fd, pw, args);
由 aidl 自动生成的 IActivityManager.Stub 是继承于Binder 对象的
public IActivityManager IRemoteService extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements xxx
而 ActivityManagerService 是继承了 IActivityManager.Stub,所以走到其 dump(fd, pw, args) 方法
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
10510 @Override
10511 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
// 传入参数是 mPriorityDumper
10512 PriorityDump.dump(mPriorityDumper, fd, pw, args);
10513 }
=============
调用 PriorityDump 工具类的dump 方法
/frameworks/base/services/core/java/com/android/server/utils/PriorityDump.java
public static void dump(PriorityDumper dumper, FileDescriptor fd, PrintWriter pw,
String[] args) {
boolean asProto = false;
@PriorityType int priority = PRIORITY_TYPE_INVALID;
...
String[] strippedArgs = new String[args.length];
int strippedCount = 0;
for (int argIndex = 0; argIndex < args.length; argIndex++) {
if (args[argIndex].equals(PROTO_ARG)) {
asProto = true;
} else if (args[argIndex].equals(PRIORITY_ARG)) {
if (argIndex + 1 < args.length) {
argIndex++;
priority = getPriorityType(args[argIndex]);
}
} else {
// 分离出命令args 来
strippedArgs[strippedCount++] = args[argIndex];
}
}
if (strippedCount < args.length) {
strippedArgs = Arrays.copyOf(strippedArgs, strippedCount);
}
switch (priority) {
...
default: {
// 调用 PriorityDumper 去dump
dumper.dump(fd, pw, strippedArgs, asProto);
return;
}
}
// 调用 PriorityDumper 去dump
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
674 private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
675 @Override
676 public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
677 boolean asProto) {
678 if (asProto) return;
679 doDump(fd, pw, new String[]{"activities"}, asProto);
680 doDump(fd, pw, new String[]{"service", "all-platform-critical"}, asProto);
681 }
。。。。。
687
688 @Override
689 public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
// dump 方法
690 doDump(fd, pw, args, asProto);
691 }
692 };
========
// dump 方法
10666 private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) {
10667 if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
10668
10669 boolean dumpAll = false;
10670 boolean dumpClient = false;
10671 boolean dumpCheckin = false;
10672 boolean dumpCheckinFormat = false;
10673 boolean dumpNormalPriority = false;
10674 boolean dumpVisibleStacksOnly = false;
10675 boolean dumpFocusedStackOnly = false;
10676 String dumpPackage = null;
10677
10678 int opti = 0;
10679 while (opti < args.length) {
10680 String opt = args[opti];
10681 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10682 break;
10683 }
10684 opti++;
// 先判断输入命令是否有 -a ,如果有则dump全部信息
10685 if ("-a".equals(opt)) {
10686 dumpAll = true;
。。。
// useProto 为false
10718 if (useProto) {
10719 final ProtoOutputStream proto = new ProtoOutputStream(fd);
10720 String cmd = opti < args.length ? args[opti] : "";
10721 opti++;
。。。
10786 int dumpAppId = getAppId(dumpPackage);
10787 boolean more = false;
10788 // Is the caller requesting to dump a particular piece of data?
10789 if (opti < args.length) {
10790 String cmd = args[opti];
10791 opti++;
// DUMP_ACTIVITIES_CMD 为 activities,DUMP_ACTIVITIES_SHORT_CMD 为a
10792 if (DUMP_ACTIVITIES_CMD.equals(cmd) || DUMP_ACTIVITIES_SHORT_CMD.equals(cmd)
10793 || DUMP_LASTANR_CMD.equals(cmd) || DUMP_LASTANR_TRACES_CMD.equals(cmd)
10794 || DUMP_STARTER_CMD.equals(cmd) || DUMP_CONTAINERS_CMD.equals(cmd)
10795 || DUMP_RECENTS_CMD.equals(cmd) || DUMP_RECENTS_SHORT_CMD.equals(cmd)) {
10796 mAtmInternal.dump(
10797 cmd, fd, pw, args, opti, true /* dumpAll */, dumpClient, dumpPackage);
调用 ActivityTaskManagerService 的方法
6979 @Override
6980 public void dump(String cmd, FileDescriptor fd, PrintWriter pw, String[] args, int opti,
6981 boolean dumpAll, boolean dumpClient, String dumpPackage) {
6982 synchronized (mGlobalLock) {
6983 if (DUMP_ACTIVITIES_CMD.equals(cmd) || DUMP_ACTIVITIES_SHORT_CMD.equals(cmd)) {
6984 dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
adb shell cmd activity -h
/frameworks/native/cmds/cmd/main.cpp
int main(int argc, char* const argv[]) {
signal(SIGPIPE, SIG_IGN);
std::vector arguments;
arguments.reserve(argc - 1);
// 0th argument is a program name, skipping.
for (int i = 1; i < argc; ++i) {
arguments.emplace_back(argv[i]);
}
// 调用 cmdMain 方法
return cmdMain(arguments, android::aout, android::aerr, STDIN_FILENO, STDOUT_FILENO,
STDERR_FILENO, RunMode::kStandalone);
// 调用 cmdMain 方法
/frameworks/native/cmds/cmd/cmd.cpp
int cmdMain(const std::vector& argv, TextOutput& outputLog, TextOutput& errorLog,
int in, int out, int err, RunMode runMode) {
sp proc = ProcessState::self();
proc->startThreadPool();
#if DEBUG
ALOGD("cmd: starting");
#endif
sp sm = defaultServiceManager();
int argc = argv.size();
// 如果命令是:adb shell cmd -l 则列出所有的service 的名字
if ((argc == 1) && (argv[0] == "-l")) {
Vector services = sm->listServices();
services.sort(sort_func);
// 会打印出下列string 值
outputLog << "Currently running services:" << endl;
for (size_t i=0; i service = sm->checkService(services[i]);
if (service != nullptr) {
outputLog << " " << services[i] << endl;
}
}
return 0;
}
// 这里是 false 的
bool waitForService = ((argc > 1) && (argv[0] == "-w"));
// index 的值为 0
int serviceIdx = (waitForService) ? 1 : 0;
// cmd 为第一个参数为 servicename
const auto cmd = argv[serviceIdx];
Vector args;
// 通过cmd 获取到 servicename
String16 serviceName = String16(cmd.data(), cmd.size());
// 遍历service 后面的参数,保存到 args 中
for (int i = serviceIdx + 1; i < argc; i++) {
args.add(String16(argv[i].data(), argv[i].size()));
}
sp service;
if(waitForService) {
service = sm->waitForService(serviceName);
} else {
// 获取到对应的service
service = sm->checkService(serviceName);
}
。。。
// TODO: block until a result is returned to MyResultReceiver.
// 调用 shellCommand 方法
status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
if (error < 0) {
// 调用 shellCommand 方法
/frameworks/native/libs/binder/Binder.cpp
status_t IBinder::shellCommand(const sp& target, int in, int out, int err,
Vector& args, const sp& callback,
const sp& resultReceiver)
{
Parcel send;
Parcel reply;
// 将传入的参数封装为 Parcel
send.writeFileDescriptor(in);
send.writeFileDescriptor(out);
send.writeFileDescriptor(err);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
send.writeStrongBinder(callback != nullptr ? IInterface::asBinder(callback) : nullptr);
send.writeStrongBinder(resultReceiver != nullptr ? IInterface::asBinder(resultReceiver) : nullptr);
// 调用对应的service 的客户端去binder 通信
return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}
如前面的分析也会调用 java 层的execTransact 方法
/frameworks/base/core/java/android/os/Binder.java
private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags,
int callingUid) {
final BinderInternal.Observer observer = sObserver;
final CallSession callSession =
observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null;
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
// If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
final boolean tracingEnabled = Binder.isTracingEnabled();
try {
if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0) {
AppOpsManager.startNotedAppOpsCollection(callingUid);
try {
res = onTransact(code, data, reply, flags);
} finally {
AppOpsManager.finishNotedAppOpsCollection();
}
} else {
// 调用 onTransact 方法
res = onTransact(code, data, reply, flags);
}
=============
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
// 如果是dump 命令,则执行 dump 方法
} else if (code == DUMP_TRANSACTION) {
ParcelFileDescriptor fd = data.readFileDescriptor();
String[] args = data.readStringArray();
if (fd != null) {
try {
dump(fd.getFileDescriptor(), args);
// 如果是 adb shell cmd,则调用 shellCommand 方法
} else if (code == SHELL_COMMAND_TRANSACTION) {
ParcelFileDescriptor in = data.readFileDescriptor();
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
args, shellCallback, resultReceiver);
}
================
// shellCommand 方法的实现
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 方法
onShellCommand(in, out, err, args, callback, resultReceiver);
}
// 同样去调用 ams 的 onShellCommand 方法
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
10502 @Override
10503 public void onShellCommand(FileDescriptor in, FileDescriptor out,
10504 FileDescriptor err, String[] args, ShellCallback callback,
10505 ResultReceiver resultReceiver) {
// 创建 ActivityManagerShellCommand 对象去执行 exec
10506 (new ActivityManagerShellCommand(this, false)).exec(
10507 this, in, out, err, args, callback, resultReceiver);
10508 }
// 创建 ActivityManagerShellCommand 对象去执行 exec
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
// 继承了 ShellCommand 方法
124 final class ActivityManagerShellCommand extends ShellCommand {
125 public static final String NO_CLASS_ERROR_CODE = "Error type 3";
/frameworks/base/core/java/android/os/ShellCommand.java
// ShellCommand 又继承了 BasicShellCommandHandler
36 public abstract class ShellCommand extends BasicShellCommandHandler {
37 private ShellCallback mShellCallback;
38 private ResultReceiver mResultReceiver;
39
// 执行 exec 方法
40 public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
41 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
42 mShellCallback = callback;
43 mResultReceiver = resultReceiver;
// 调用父类BasicShellCommandHandler 的 exec 方法
44 final int result = super.exec(target, in, out, err, args);
45
// 发送结果给cmd 进程
46 if (mResultReceiver != null) {
47 mResultReceiver.send(result, null);
48 }
49
50 return result;
51 }
// 调用父类BasicShellCommandHandler 的 exec 方法
/frameworks/base/core/java/android/os/BasicShellCommandHandler.java
75 public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
76 String[] args) {
77 String cmd;
78 int start;
79 if (args != null && args.length > 0) {
// 获取adb shell cmd activity 后面的第一个参数
80 cmd = args[0];
81 start = 1;
82 } else {
83 cmd = null;
84 start = 0;
85 }
86 init(target, in, out, err, args, start);
87 mCmd = cmd;
88
89 if (DEBUG) {
90 RuntimeException here = new RuntimeException("here");
91 here.fillInStackTrace();
92 Log.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
93 Log.d(TAG, "Calling uid=" + Binder.getCallingUid()
94 + " pid=" + Binder.getCallingPid());
95 }
96 int res = -1;
97 try {
// 回调子类ActivityManagerShellCommand.java的方法 onCommand
98 res = onCommand(mCmd);
99 if (DEBUG) Log.d(TAG, "Executed command " + mCmd + " on " + mTarget);
// 回调子类ActivityManagerShellCommand.java的方法 onCommand
/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) {
// 启动activity 命令
case "start":
case "start-activity":
return runStartActivity(pw);
// 启动service 的命令
case "startservice":
case "start-service":
return runStartService(pw, false);
//如果都不满足上述情形,则执行
default:
return handleDefaultCommands(cmd);
}
/frameworks/base/core/java/android/os/BasicShellCommandHandler.java
// 调用到 父类的方法
289 public int handleDefaultCommands(String cmd) {
290 if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
291 onHelp();
又调用到子类的方法
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
// mDumping 为false
dumpHelp(pw, mDumping);
}
============
static void dumpHelp(PrintWriter pw, boolean dumping) {
if (dumping) {
。。。。。
} else {
pw.println("Activity manager (activity) commands:");
pw.println(" help");
pw.println(" Print this help text.");
pw.println(" start-activity [-D] [-N] [-W] [-P ] [--start-profiler ]");
总结:
adb shell cmd 命令:
1. 对应命令会调用到service 的 onCommand
2. 帮助命令会调用到 onHelp
adb shell dumpsys 命令:
对应命令调用到 service 的 dump方法