前言

本章继续讲解 AMS 相关的知识点,如何 Hook Activity 的启动流程;
attach
我们这样直接从 attach 入口讲起
private void attach(boolean system, long startSeq) {
// 省略部分代码
// AMS
final IActivityManager mgr = ActivityManager.getService();
try {
// 这里直接调用到了 AMS 的 attachApplication 方法;
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
attach 中直接调用到了 AMS 的 attachApplication 方法,我们进入这个方法看下:
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
// 获取调用端的 pid
int callingPid = Binder.getCallingPid();
// 获取调用端的 uid
final int callingUid = Binder.getCallingUid();
// 把 pid/uid 设置成 AMS 的
final long origId = Binder.clearCallingIdentity();
//
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
// 恢复为 app 的
Binder.restoreCallingIdentity(origId);
}
}
这里有一个比较关键的点就是:把 binder 的 id 设置成 AMS 的,这样做是为了权限验证;Binder.clearCallingIdentity() 最终调用到 IPCThreadState.cpp 中的同名方法,我们进入这个 cpp 文件的同名方法看下:
int64_t IPCThreadState::clearCallingIdentity() {
int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid;
clearCaller();
return token;
}
这里调用了 clearCaller 函数,我们进入这个函数看下:
// 清空远程调用端的uid和pid,用当前本地进程的uid和pid替代
void IPCThreadState::clearCaller() {
mCallingPid = getpid();
mCallingUid = getuid();
}
restoreCallingIdentity 也是调用的同名方法;
// 从token中解析出pid和uid,并赋值给相应变量,该方法正好是clearCallingIdentity的相反过程
void IPCThreadState::restoreCallingIdentity(int64_t token) {
mCallingUid = (int)(token>>32);
mCallingPid = (int)token;
}

AndroidManifest.xml 中的 Activity 是在哪里注册的?
我们在启动一个 Activity 的时候,如果没有在 AndroidManifest 中进行注册的话,就会抛出一段异常,那么 AndroidManifest.xml 中的 Activity 是在哪里注册的呢?
我们直接进入启动 Activity 的代码中看下:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
// 省略部分代码
// 调用 AMS 的 startActivity 方法并获取一个放回结果,然后检测这个结果
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
}
这里调用 AMS 的 startActivity 方法并获取一个返回结果,然后检测这个结果;
public static void checkStartActivityResult(int res, Object intent) {
if (!ActivityManager.isStartResultFatalError(res)) {
return;
}
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent &&a

最低0.47元/天 解锁文章
2036

被折叠的 条评论
为什么被折叠?



