1.源码入口
- frameworks/native/cmds/dumpsys/main.cpp
1 2 3 4 5 6 7 8 9 10 11 12
int main(int argc, char* const argv[]) { signal(SIGPIPE, SIG_IGN); sp<IServiceManager> 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()); return dumpsys.main(argc, argv); }
从入口看,每次调用都是新建了一个Dumpsys,并传入了IServiceManager,并把argc,和argv传入main函数中
- frameworks/native/cmds/dumpsys/dumpsys.cpp
直接看main函数,这里是用getopt_long来解析传入的参数 (注:getopt_long和getopt都是用来解析参数的,但是getopt_long可以解析长参数,都是glibc库中)
1
2
3
4
5
6
7
8
9
int Dumpsys::main(int argc, char* const argv[]) {
while (1) {
int c;
int optionIndex = 0;
c = getopt_long(argc, argv, "+t:T:l", longOptions, &optionIndex);
}
}
2.命令分析
2.1 dumpsys -l
dumpsys -l 可以把当前正在运行的服务都枚举出来,如下:
1
2
3
4
5
6
7
8
9
10
11
console:/ # dumpsys -l
Currently running services:
DockObserver
SkgSystemUI
SurfaceFlinger
SurfaceFlingerAIDL
accessibility
account
activity
activity_task
//省略...
首先在main中就能看到找到 -l 的定义,并不带参数
1
2
3
4
5
6
7
switch (c) {
//省略
case 'l':
showListOnly = true;
break;
//省略
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Vector<String16> services;
//省略
int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
//因为showListOnly为true
if (services.empty() || showListOnly) {
//获取当前所有正在运行的服务的名字
services = listServices(priorityFlags, asProto);
setServiceArgs(args, asProto, priorityFlags);
}
const size_t N = services.size();
if (N > 1 || showListOnly) {
// first print a list of the current services
std::cout << "Currently running services:" << std::endl;
for (size_t i=0; i<N; i++) {
//这里的sm_其实就是在main.cpp中传入的IServiceManager
//这里根据服务的名字去获取对应的IBinder
//Retrieve an existing service, non-blocking.
sp<IBinder> service = sm_->checkService(services[i]);
if (service != nullptr) {
bool skipped = IsSkipped(skippedServices, services[i]);
//输出服务的名字
std::cout << " " << services[i] << (skipped ? " (skipped)" : "") << std::endl;
}
}
}
来看看下listServices函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vector<String16> Dumpsys::listServices(int priorityFilterFlags, bool filterByProto) const {
//这里sm_同上,返回当前存在的服务的列表
//Return list of all existing services.
Vector<String16> services = sm_->listServices(priorityFilterFlags);
services.sort(sort_func);
if (filterByProto) {
Vector<String16> protoServices = sm_->listServices(IServiceManager::DUMP_FLAG_PROTO);
protoServices.sort(sort_func);
Vector<String16> intersection;
std::set_intersection(services.begin(), services.end(), protoServices.begin(),
protoServices.end(), std::back_inserter(intersection));
services = std::move(intersection);
}
return services;
}
如上述代码,遍历了正在运行的服务。 看到这里就可以提前给出总结: dumpsys其实也是一个外壳,负责解析传入参数的逻辑,都是调用的sm_,而sm_在 frameworks/native/cmds/dumpsys/dumpsys.h中有定义,如下,可以看到sm_就是一个IServiceManager
1
2
3
4
5
6
7
8
9
public:
explicit Dumpsys(android::IServiceManager* sm) : sm_(sm) {
}
//省略
private:
android::IServiceManager* sm_;
std::thread activeThread_;
mutable android::base::unique_fd redirectFd_;
这里就看到在new一个dumpsys的时候,就传入了一个IServiceManager,可以回到第一部分源码入口中看下
2.2 dumpsys usb
可以在dumpsys -l中可以找到usb服务,那么用dumpsys usb就可以打印出当前usb相关状态的信息,在从dumpsys.cpp中看,usb并没有在longOptions和optstring中定义,那么getopt_long返回-1,退出循环 (注:可以查看man里的解释 If there are no more option characters, getopt() returns -1 ,getopt_long就是扩展getopt,返回值定义也是一样的)
1
2
3
4
5
6
7
8
9
10
11
12
while (1) {
int c;
int optionIndex = 0;
c = getopt_long(argc, argv, "+t:T:l", longOptions, &optionIndex);
if (c == -1) {
//退出循环
break;
}
//省略
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Vector<String16> services;
//此时,optind=1,argc=2 , argv[]={"dumpsys","usb"}
for (int i = optind; i < argc; i++) {
if (skipServices) {
skippedServices.add(String16(argv[i]));
} else {
if (i == optind) {
//i=1, 往services中添加usb
services.add(String16(argv[i]));
// 结束循环
} else {
const String16 arg(argv[i]);
args.add(arg);
// For backward compatible, if the proto argument is passed to the service, the
// dump request is also considered to use proto.
if (!asProto && !arg.compare(String16(PriorityDumper::PROTO_ARG))) {
asProto = true;
}
}
}
}
//services不是空的, showListOnly=false,就跳过以下的操作
if (services.empty() || showListOnly) {
//省略
}
//N=1,showListOnly=false ,也跳过以下的操作
const size_t N = services.size();
if (N > 1 || showListOnly) {
//省略
}
//N=1,也就一次循环
for (size_t i = 0; i < N; i++) {
// serviceName 就是"usb"
const String16& serviceName = services[i];
if (IsSkipped(skippedServices, serviceName)) continue;//这里跳过
//这里startDumpThread就是开启一个线程去打印一个指定服务的信息
if (startDumpThread(dumpTypeFlags, serviceName, args) == OK) {
bool addSeparator = (N > 1);
if (addSeparator) {
writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
}
std::chrono::duration<double> elapsedDuration;
size_t bytesWritten = 0;
status_t status =
writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(timeoutArgMs),
asProto, elapsedDuration, bytesWritten);
if (status == TIMED_OUT) {
std::cout << std::endl
<< "*** SERVICE '" << serviceName << "' DUMP TIMEOUT (" << timeoutArgMs
<< "ms) EXPIRED ***" << std::endl
<< std::endl;
}
if (addSeparator) {
writeDumpFooter(STDOUT_FILENO, serviceName, elapsedDuration);
}
bool dumpComplete = (status == OK);
stopDumpThread(dumpComplete);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
*开始一个线程去连接服务,并得到dump的输出,这个线程会重新指向输出到一个管道,
*在随后调用的stopDumpThread函数后,必须去暂停这个线程
* Starts a thread to connect to a service and get its dump output. The thread redirects
* the output to a pipe. Thread must be stopped by a subsequent call to {@code
* stopDumpThread}.
* @param dumpTypeFlags operations to perform
* @param serviceName
* @param args list of arguments to pass to service dump method.
* @return {@code OK} thread is started successfully.
* {@code NAME_NOT_FOUND} service could not be found.
* {@code != OK} error
*/
status_t Dumpsys::startDumpThread(int dumpTypeFlags, const String16& serviceName,
const Vector<String16>& args) {
//查找这个服务是否存在。并拿到这个服务
sp<IBinder> 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块完成,所以生成一个线程
// dump blocks until completion, so spawn a thread..
activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
if (dumpTypeFlags & TYPE_PID) {
status_t err = dumpPidToFd(service, remote_end, dumpTypeFlags == TYPE_PID);
reportDumpError(serviceName, err, "dumping PID");
}
if (dumpTypeFlags & TYPE_STABILITY) {
status_t err = dumpStabilityToFd(service, remote_end);
reportDumpError(serviceName, err, "dumping stability");
}
if (dumpTypeFlags & TYPE_THREAD) {
status_t err = dumpThreadsToFd(service, remote_end);
reportDumpError(serviceName, err, "dumping thread info");
}
if (dumpTypeFlags & TYPE_CLIENTS) {
status_t err = dumpClientsToFd(service, remote_end);
reportDumpError(serviceName, err, "dumping clients info");
}
//因为dumpTypeFlags=1, 进入以下操作,
//这里拿的是usb服务,不带参数,args是null的
// other types always act as a header, this is usually longer
if (dumpTypeFlags & TYPE_DUMP) {
status_t err = service->dump(remote_end.get(), args);
reportDumpError(serviceName, err, "dumping");
}
});
return OK;
}
关键操作 status_t err = service->dump(remote_end.get(), args);注意这里的service是一个实际调用的BpBinder 可以在frameworks/native/libs/binder/include/binder/BpBinder.h看到 BpBinder继承的IBinder。 frameworks/native/libs/binder/BpBinder.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
status_t BpBinder::dump(int fd, const Vector<String16>& args)
{
Parcel send;
Parcel reply;
send.writeFileDescriptor(fd);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
//这里把要传入的参数args都转给Parcel做序列化
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
//这里就是上报到jni里
status_t err = transact(DUMP_TRANSACTION, send, &reply);
return err;
}
status_t BpBinder::transact(
//省略
status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
//省略
}
在这个dump函数中,主要的工作就是把传入的参数给打包序列化,用过transact函数去上报,注意看下DUMP_TRANSACTION这个int常量 在frameworks/native/libs/binder/include/binder/IBinder.h可以看到
1
2
3
4
5
6
7
8
9
10
11
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
//省略
public:
enum {
//省略
DUMP_TRANSACTION = B_PACK_CHARS('_', 'D', 'M', 'P'),
//省略
}
//省略
}
这DUMP_TRANSACTION打印出来值是1598311760,到这里,先暂停一下,接下来从java层开始看,找到一个相对应处理DUMP_TRANSACTION地方,就能打通上下层
3.在java层分析dump流程
最直接就是看,在java层添加了dump信息后,是如何被回调的,例子如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class XXXXService extends XXXX.Stub{
@Override
protected void dump(FileDescriptor fd, PrintWriter out, String[] args) {
int size = args.length;
out.println("start dump!!");
for(int i=0 ; i < size ; i++){
out.println("args[" + i +"]="+ args[i]);
}
out.println("end dump!!");
}
}
在XXXX.aidl生产的IXXXX.java文件中可以看到XXXX.Stub就是继承的frameworks/base/core/java/android/os/Binder.java frameworks/base/core/java/android/os/IBinder.java IBinder.java是一个接口类,Binder.java实现了IBinder.java接口,在这里也发现了DUMP_TRANSACTION的定义,打印出来也是1598311760,和上面cpp里的DUMP_TRANSACTION对应上了,也定义dump接口
1
2
3
int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P';
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) throws RemoteException;
在Binder.java中看到有针对DUMP_TRANSACTION的处理,并且能看到在XXXX.Stub能找到对onTransact方法的重写,也是根据code来判断如何处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
//省略
else if (code == DUMP_TRANSACTION) {
ParcelFileDescriptor fd = data.readFileDescriptor();
//反序列化拿到参数
String[] args = data.readStringArray();
if (fd != null) {
try {
//传递参数
dump(fd.getFileDescriptor(), args);
} finally {
IoUtils.closeQuietly(fd);
}
}
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
return true;
}
//省略
}
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
doDump(fd, pw, args);
} finally {
pw.flush();
}
}
void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
//Control whether dump() calls are allowed.
final String disabled = sDumpDisabled;
if (disabled == null) {
try {
dump(fd, pw, args);
} catch (SecurityException e) {
pw.println("Security exception: " + e.getMessage());
throw e;
} 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.
pw.println();
pw.println("Exception occurred while dumping:");
e.printStackTrace(pw);
}
} else {
pw.println(sDumpDisabled);
}
}
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
@Nullable String[] args) {
}
从上面代码就很直观的看出来在XXXX.Stub中重写dump方法被调用的流程,
那么接下就是找onTransact方法如何被调用的,还是在Binder.java中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Entry point from android_util_Binder.cpp's onTransact
@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);
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
}
}
在上面的注释中,就能确认execTransact是被那native层调用的,接着往下看execTransactInternal里的就能找到调用了onTransact了
4.cpp上报到java
frameworks/base/core/jni/android_util_Binder.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderPathName);
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
//这里初始化映射到java中Binder.java中的execTransact
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mGetInterfaceDescriptor = GetMethodIDOrDie(env, clazz, "getInterfaceDescriptor",
"()Ljava/lang/String;");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
可以看到jni初始化,映射到了Binder.java的execTransact函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override
{
JNIEnv* env = javavm_to_jnienv(mVM);
LOG_ALWAYS_FATAL_IF(env == nullptr,
"Binder thread started or Java binder used, but env null. Attach JVM?");
ALOGI("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");
// 这里就是cpp调用java的地方
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
//省略
}
这里就是被BpBinder.cpp中transact后调用jni里的onTransact,就调用到上层了