↓双击 Markdown插件,就可以开始编辑啦。
APP进程
ActivityThread的启动
public static void main(String[] args) {
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
}
在attach方法中主要做了以下重要的事情:
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
attach方法把应用进程的ApplicationThread通过IActivityManager传递到ActivityManagerService,而IActivityManager是ActivityManagerService系统服务在APP进程的一个代理,这个是一个跨进程的调用,最终会调用到ActivityManagerService的attachApplication方法:
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
attachApplication方法里面又调用到:
IApplicationThread是APP进程ApplicationThread在系统进程的一个代理对象,bindApplication是一个系统进程到APP进程的跨进层调用,负责把一些初始化的数据回传到APP进程,例如系统服务的各种Binder代理对象,bindApplication最后会调用到ApplicationThread的bindApplication方法,这里面主要做了三件事:
- 一个是把系统服务的Binder对象缓存到ServiceManager中
- 第二个是创建LoadedApk对象,LoadedApk是应用在内存上的一个体现,包含了应用信息,资源路径,内部文件路径,apk路径,receiver信息,Service信息
- 第三个是通过Handler类对象H来实现Application的创建,onCreate的回调
ActivityThread的启动流程
App进程与AMS进程的通信过程如图所示
系统进程
SystemServer启动
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
在system_process进程启动的时候就会初始化一些系统服务,例如ActivityManagerService:
APP进程启动
通过LocalSocket来用命令的方式启动Process
Activity启动
Activity启动的核心类
- ActivityThread:应用进程的启动初始化和四大组件在应用进程的调度
- ApplicationThread:应用进程和系统进程夸进程通信的服务端
- IActivityManager:ActivityManagerService在应用进程的binder代理对象,系统进程和应用进程进行跨进程通信的客户端
- SystemServer:系统进程的启动初始化
- ActivityManagerService:四大组件在系统进程的调度,系统进程和应用进程进行夸进程通信的服务端
- IApplicationThread:ApplicationThread在系统进程的binder代理对象,系统进程和应用进程进行夸进程通信的客户端
- ServiceManager:系统服务的管理
Activity启动过程
- 通过Context的startActivity方法发起Activity的启动
- 然后进入ContextImpl中的startActivity方法,并在该方法中通过ActivityThread获取到Instrumentation对象,并调用execStartActivity方法
- 在execStartActivity方法中会通过IActivityManager代理对象触发夸进程调用,把Activity的一些信息参数传递到系统进程ActivityManagerService中
- 在ActivityManagerService会逐层调用,然后进入ActivityStarter类中的startActivityMayWait方法,ActivityStarter会进行一些权限检查,并创建ActivityRecord对象把Activity信息存到该对象中去
- 加下来会执行到ActivityStack中,顾名思义,这个是对Activity栈进行管理的操作
- 接着继续执行到ActivityStackSupervisor类的startSpecificActivityLocked方法,在这个方法里面就会去判断当前需要启动的Activity所在的进程是否已经存在如果存在则调用realStartActivityLocked方法,否则就startProcessAsync方法优先启动进程
- 接下来Android8.0以后的代码和8.0以前的代码就有一些小差异,但是做的事情都是一样的:通过IApplicationThread跨进程通知应用进程,并继续在应用进程执行下一步操作
- 应用进程在收到通知后会在Handler类H中去执行Activity的创建以及回掉各个Activity的生命周期的方法(通过状态模式来实现Activity的生命周期的切换)
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " to state: " + getStateName(state));
}
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, mPendingActions,
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
mTransactionHandler.handleStopActivity(r.token, false /* show */,
0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
0 /* configChanges */, false /* getNonConfigInstance */,
"performLifecycleSequence. cycling to:" + path.get(size - 1));
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(r.token, false /* start */);
break;
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
}
}
}
- 这里注意一个误区,Activity的启动计时是以onWindowFocused为准而不是以onResume为准,应为onResume执行完了之后,Activity才添加到Window中并进行进行界面布局的绘制,至此Activity的启动基本完成
Activity启动流程总结
- Activity启动过程中其实就是应用进程和系统进程通过AIDL来进行双向跨进程通信的一个过程
解决ActivityNotFoundException问题
为什么会有ActivityNotFoundException这个异常
- Activity需要在配置文件中注册,然后在系统进程中对配置文件中的Activity进行检测,如果发现Activity没有注册就会返回一个错误的结果,然后在Instrumentation类的checkStartActivityResult方法中会抛出这个异常
实现插件化启动Activity如何解决这个问题?
- Activity的信息类是被装在Intent中传递给ActivityManagerService中的,然后在ActivityManagerService去对Activity信息进行检测,如果我们想启动一个没有注册过的Activity可以在应用进程的某一处节点hook掉,把我们要启动的目标Activity替换成已经注册好的Activity,这样在系统进程进行Activity检测的时候就可以骗过去
- 系统进程完成Activity检测后会再回传到应用进程,然后根据Activity信息来创建Activity类并执行生命周期的方法,所以我们可以在应用进程的某一处节点再hook一下,把Activity类信息替换回我们想要启动的目标Activity,这样就可以启动未注册过的Activity而不报错
如何寻找Hook点?
- 由于我们锁需要hook的地方都是在应用进程的,所以应用进程的hook我们是可以轻松的通过Java反射,动态代理来进行拦截的
- Hook的原则是静态变量或者单例对象,尽量Hook pulic的对象和方法,非public不保证每个版本都一样,需要适配
Activity启动流程的hook点(针对Android9.0以上)
- ActivityManager的IActivityManagerSingleton属性
hook代码:
Method getServiceMethod = ActivityManager.class.getDeclaredMethod("getService");
getServiceMethod.setAccessible(true);
Object iActivityManagerObj = getServiceMethod.invoke(ActivityManager.class, null);
Field IActivityManagerSingleton = ActivityManager.class.getDeclaredField("IActivityManagerSingleton");
IActivityManagerSingleton.setAccessible(true);
Object IActivityManagerSingletonObj = IActivityManagerSingleton.get(ActivityManager.class);
Class<?> singletonCls = Class.forName("android.util.Singleton");
Field mInstance = singletonCls.getDeclaredField("mInstance");
mInstance.setAccessible(true);
Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
Object iActivityManagerProxy = Proxy.newProxyInstance(ActivityManager.class.getClassLoader()
, new Class<?>[]{iActivityManagerInterface}, new IActivityManagerHandler(iActivityManagerObj));
mInstance.set(IActivityManagerSingletonObj, iActivityManagerProxy);
-
用Java动态代理把Activity信息替换成代理Activity
-
通过hook Handle的Callback来拦截回传Activity的信息,并换回我们要启动的Activity