本文转载自:
本文基于Android 11.0源码分析
前言
在Android系统中,可以用am命令来启动一个组件。例如,可以用下面的命令启动Camera:
am start -n com.android.camera/com.android.camera.Camera
1.am架构
从代码实现上来说,在Android系统中,Android Framework层的各个service作为服务端,而使用者通过RPC(远程过程调用)调用这些服务,使用者就是Client端。
从进程间通信角度来说,Android Framework层的各个service作为服务端,提供具体的功能;同时,应用程序为了访问这些service,需要通过binder机制与service进行通信,这些运行在app端的代码就是client端(诸如ActivityManagerProxy等各种服务代理)。
具体到今天分析的am来说,am作为client端,与Framework的server端的AMS通过binder进行交互;从而实现AMS提供的各种功能,如图:
(1)am的编译Android.bp
// frameworks/base/cmds/am/Android.bp
// Copyright 2008 The Android Open Source Project
//
cc_library_host_static {
name: "libinstrumentation",
srcs: ["**/*.proto"],
cflags: ["-Wall", "-Werror"],
proto: {
type: "full",
export_proto_headers: true,
},
}
java_binary {
name: "am",
wrapper: "am",
srcs: [
"src/**/*.java",
"proto/**/*.proto",
],
proto: {
plugin: "javastream",
},
static_libs: ["libprotobuf-java-lite"],
}
(2)源码路径
frameworks/base/cmds/am/
2.Am类相关代码的分析
2.1 Am类图
说明(主要对Am类进行说明):
-
Am类:即am命令的入口类,有main方法。Am是client端组件,拥有一个远程代理组建mAm;
-
数据成员mAm:
- mAm:Am类通过mAm来实现相关的功能,包括启动一个activity或service,发送一个广播等。mAm的真正实体类型是AcitivtyManagerProxy类型,因为mActivityManager是一个接口,无法实例化,而继承自mActivityManager的AcitivtyManagerProxy可以实例化。
- mArgs:即am命令的参数;
- 方法:
- runStartService:启动一个service;
- sendBroadcast:发送一个广播;
2.2 run方法的分析
am是可执行程序,其对应的实现在Am.java中,当然有main方法。在main方法中,调用了run方法。main方法调用run,代码如下:
// frameworks/base/cmds/am/src/com/android/commands/am/Am.java
public static void main(String[] args) {
(new Am()).run(args);
}
Am.java继承BaseCommand.java,而run()方法在BaseCommand.java中定义:
// frameworks/base/core/java/com/android/internal/os/BaseCommand.java
public void run(String[] args) {
if (args.length < 1) {
// 如果没有参数则显示信息
onShowUsage(System.out);
return;
}
mRawArgs = args;
mArgs.init(null, null, null, null, args, 0);
try {
// 执行onRun()
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);
}
}
回到Am.java中,它实现了onRun()方法:
// frameworks/base/cmds/am/src/com/android/commands/am/Am.java
public void onRun() throws Exception {
// 获取AMS服务
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?");
}
// 获取PKMS服务
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();
} else {
// 调用此处
runAmCmd(getRawArgs());
}
}
---------------------------------------------------------
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;
}
}
这里通过Binder通信,最后调用到AMS服务中:
// frameworks/base/core/java/android/os/Binder.java
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (code == INTERFACE_TRANSACTION) {
reply.writeString(getInterfaceDescriptor());
return true;
} 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;
} 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);
}
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(err);
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
}
return true;
}
return false;
}
----------------------------------------------------------------
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
onShellCommand(in, out, err, args, callback, resultReceiver);
}
调了onShellCommand,这个方法ActivityManagerService有重载:
// 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);
}
onShellCommand中又把具体的事情交给ActivityManagerShellCommand去做了,但是ActivityManagerShellCommand没有重载exec,他的父类ShellCommand的exec又调了父类BasicShellCommandHandler的exec,BasicShellCommandHandler的exec中调了onCommand,而ActivityManagerShellCommand重载了此方法:
// 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":
// 这里关注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);
......
return -1;
}
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
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 (mWaitOption) {
// 调用startActivityAndWait()方法,启动activity
result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
mimeType, null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
res = result.result;
} else {
res = mInternal.startActivityAsUserWithFeature(null, SHELL_PACKAGE_NAME, null,
intent, mimeType, null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
}
...
}
mInternal就是AMS,最后解析相应的参数后,通过AMS的startActivityAndWait()方法去启动Activity。
网友评论