前面发了blog分析了ActivityManager框架的大体结构,主要就是一个进程通信机制,今天我通过深入Activity的启动过程再次深入到ActivityManager框架,对其进行一个更深入的了解
以桌面启动一个应用Activity为例,onClick事件后,会调用startActivityForResult(Intent, int)
public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
//Activity启动执行交由Instrumentation对象去处理
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
//mMainThread 在attach方法中被设置,当ActivityThread PerformLauchActivity,调用attach把ActivityThread.this传送过来
//mMainThread.getApplicationThread()它是一个进程通信服务端存根对象,提供了很多操作ActivityThread的方法,它继承了ApplicationThreadNative
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
Instrumentation.execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode) {
......
try {
//ActivityManagerNative.getDefault()实际返回的是一个ActivityManagerProxy对象
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mEmbeddedID : null,
requestCode, false, false);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
ActivityManagerProxy是实现IActivityManager接口的一个进程通信代理对象,在该方法ActivityManagerProxy.startActivity中,它只负责
准备相关的数据发送到system_process进程去处理startActivity:
public int startActivity(IApplicationThread caller, Intent intent,
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
boolean debug) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeTypedArray(grantedUriPermissions, 0);
data.writeInt(grantedMode);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(onlyIfNeeded ? 1 : 0);
data.writeInt(debug ? 1 : 0);
//mRemote是一个BinderProxy对象,transact方法本地化实现
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
到此前面3步都是在Laucher2进程中执行,调用mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);后,系统转到
system_process进程中执行,根据我前面讲的进程通信机制,入口函数是ActivityManagerNative.onTransact方法,在system_process进程中
ActivityManagerNative被继承,实际执行的是ActivityManagerService.onTransact方法,调用堆栈如下:
ActivityManagerService(ActivityManagerNative).onTransact(int, Parcel, Parcel, int) line: 129
ActivityManagerService.onTransact(int, Parcel, Parcel, int) line: 1481
ActivityManagerService(Binder).execTransact(int, int, int, int) line: 288
NativeStart.run() line: not available [native method]
在ActivityManagerService(ActivityManagerNative).onTransact中根据前面的参数START_ACTIVITY_TRANSACTION,执行对应的case代码:
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);
int grantedMode = data.readInt();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
boolean onlyIfNeeded = data.readInt() != 0;
boolean debug = data.readInt() != 0;
//执行对应Stub的IActivityManager接口方法
int result = startActivity(app, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug);
reply.writeNoException();
reply.writeInt(result);
return true;
}
前面红色的startActivity方法实际是执行的ActivityManagerService中的startActivity,接下来的执行很复杂,要想搞清楚这些细节还需要一些时间,我我们跳过这些,继续沿着主干道前行:
ActivityManagerService.startProcessLocked(ProcessRecord, String, String) line: 2043
ActivityManagerService.startProcessLocked(String, ApplicationInfo, boolean, int, String, ComponentName, boolean) line: 1982
ActivityManagerService.startSpecificActivityLocked(HistoryRecord, boolean, boolean) line: 1908
ActivityManagerService.resumeTopActivityLocked(HistoryRecord) line: 2855
ActivityManagerService.completePauseLocked() line: 2237
ActivityManagerService.activityPaused(IBinder, Bundle, boolean) line: 5963
ActivityManagerService.activityPaused(IBinder, Bundle) line: 5941
ActivityManagerService(ActivityManagerNative).onTransact(int, Parcel, Parcel, int) line: 387
ActivityManagerService.onTransact(int, Parcel, Parcel, int) line: 1481
ActivityManagerService(Binder).execTransact(int, int, int, int) line: 288
SystemServer.init1(String[]) line: not available [native method]
SystemServer.main(String[]) line: 582
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 868
ZygoteInit.main(String[]) line: 626
NativeStart.main(String[]) line: not available [native method]
在用例进程onPause后,通过ActivityManagerProxy.activityPaused执行相关操作,这也是一个用例进程到system_process进程的远程调用,原来的用例进程需要进栈,并启动一个新的Activity在屏幕最前端,我们只关注新Activity的启动,首先关注新Activity应用进程的创建,看上面的调用堆栈,在函数startProcessLocked:
//app记录的是一个要启动ActivityThread进程的信息,hostingType=activity,hostingNameStr="com.iaiai.activity/.IaiaiActivity"
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
......
//Process.start是一个静态方法,它将启动一个新的进程,新进程的的入口main方法为android.app.ActivityThread.main
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);
......
现在,我们终于看到了一个新的应用进程的创建,别急,在启动主Activity我们还有很多工作要做,我我们可以想象到得,一个新的应用肯定要建立闭环的消息循环,然后它要把的一个ApplicationThreadProxy代理对象传递给system_process进程,这样system_process进程就可以通过ApplicationThreadProxy代理对象来控制我们的应用进程了,比如它把广播消息转给应用进程,关闭应用进程等
先看新进程的main函数:
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
//建立looper消息循环队列
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
//开始主线程消息循环
Looper.loop();
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
在main函数中建立了闭环的消息循环,这个是一般ui程序做法,很容易理解,但是后续应用的启动工作是如何进程的,关注我上面标注的红色代码,这里创建了一个ActivityThread对象,ActivityThread构造时初始化了该应用进程的一些基本成员,最重要的我们关注
final Looper mLooper = Looper.myLooper();
final H mH = new H();//消息处理handler
在这里,我们建立了消息处理器,它将负责处理main线程中Looper消息循环中的消息。
还用一个成员对象值得我们关注,那就是ApplicationThread对象,在ActivityThread对象被创建时,它也被构造了,我前面已经提到过了,它继承了ApplicationThreadNative类,熟悉进程通信代理机制的朋友就清楚了,ApplicationThread就是一个通信代理存根实现类,我们可以看它的实现方法,都是调用queueOrSendMessage方法,派发消息交给ActivityThread的mH去处理,那么我们很清楚了,ActivityThread代理存根对象,它负责执行来自远程的调用,这些远程的调用大部分来自system_process,所以,system_process很容易通过ApplicationThread的客户端代理对象控制ActivityThread,事实就是如此,后面我们可以很好地看到这一点,
继续看thread.attach(false)函数,参数标识是否系统进程,系统进程的入口函数是systemMain,而不是main方法,
private final void attach(boolean system) {//system==false
sThreadLocal.set(this);//ActivityThread对象关联到主线程
mSystemThread = system;
if (!system) {//是非系统进程
...
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//把ApplicationThread mAppThread attach到系统进程system_process,以便system_process控制当前应用的ActivityThread
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
} else {
//系统进程要作的处理
...
}
//接收来自ViewRoot的ConfigurationChanged消息,派发给mH处理(H.CONFIGURATION_CHANGED),
//一旦配置发生变更,mH将执行H.CONFIGURATION_CHANGED
ViewRoot.addConfigCallback(new ComponentCallbacks() {
public void onConfigurationChanged(Configuration newConfig) {
synchronized (mPackages) {
// We need to apply this change to the resources
// immediately, because upon returning the view
// hierarchy will be informed about it.
if (applyConfigurationToResourcesLocked(newConfig)) {
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
public void onLowMemory() {
}
});
}
再来看一下attach方法的调用堆栈:
ActivityManagerProxy.attachApplication(IApplicationThread) line: 1542
ActivityThread.attach(boolean) line: 4555
ActivityThread.main(String[]) line: 4632
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 868
ZygoteInit.main(String[]) line: 626
NativeStart.main(String[]) line: not available [native method]
这里你又会看到一个熟悉的身影,ActivityManagerProxy,是的,这里又使用了进程通信,通知ActivityManagerService执行attachApplication
看一下ActivityManagerProxy.attachApplication方法的代码:
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
//参数IApplicationThread app通过进程通信传送到system_process进程,而app是一个ApplicationThread对象,不要被它的名称所迷惑
//这里它只是一个对象,它继承了ApplicationThreadNative,而ApplicationThreadNative是实现IApplicationThread接口的一个进程通信接口存根类,当它到达system_process,system_process得到的是它的一个代理类ActivityManagerProxy
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
再次回到了system_process进程,先看一下system接收到来自新的Activity的远程调用堆栈:
ActivityManagerService.attachApplicationLocked(IApplicationThread, int) line: 5591
ActivityManagerService.attachApplication(IApplicationThread) line: 5677
ActivityManagerService(ActivityManagerNative).onTransact(int, Parcel, Parcel, int) line: 363
ActivityManagerService.onTransact(int, Parcel, Parcel, int) line: 1481
ActivityManagerService(Binder).execTransact(int, int, int, int) line: 288
NativeStart.run() line: not available [native method]
我们看attachApplicationLocked的实现,由于函数比较长,而且我也没有深入仔细看,所以我只列出我理解的关键部分代码
//thread来用户进程的ApplicationThread代理对象,pid是用户进程的pid
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
......
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
//当用户进程创建时有一个标识用户进程的pid,它关联了ProcessRecord记录,现在根据pid或者该记录
app = mPidsSelfLocked.get(pid);
}
} else if (mStartingProcesses.size() > 0) {
app = mStartingProcesses.remove(0);
app.setPid(pid);
} else {
app = null;
}
......
//设置app相关参数
app.thread = thread;//设置app的thread为用户进程代理对象ActivityManagerProxy
app.curAdj = app.setAdj = -100;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.forcingToForeground = null;
app.foregroundServices = false;
app.debugging = false;
......
thread.bindApplication(processName, app.instrumentationInfo != null
? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
mConfiguration, getCommonServicesLocked());
updateLruProcessLocked(app, false, true);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
......
HistoryRecord hr = topRunningActivityLocked(null);
if (hr != null && normalMode) {
if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//realStartActivityLocked会调用thread.scheduleLaunchActivity
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
}
这里通过远程调用后thread并不是一个ApplicationThread对象,而是其一个远程代理对象ApplicationThreadProxy,通过thread,可以操作ApplicationThread对象调用bindApplication和scheduleLaunchActivity:
先看bindApplication:
ActivityThread$ApplicationThread.bindApplication(String, ApplicationInfo, List, ComponentName, String, Bundle, IInstrumentationWatcher, int, boolean, Configuration, Map) line: 1655
ActivityThread$ApplicationThread(ApplicationThreadNative).onTransact(int, Parcel, Parcel, int) line: 251
ActivityThread$ApplicationThread(Binder).execTransact(int, int, int, int) line: 288
NativeStart.run() line: not available [native method]
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
int debugMode, boolean isRestrictedBackupMode, Configuration config,
Map<String, IBinder> services) {
//获取来自system_process远程调用传递过来的相关参数
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.profileFile = profileFile;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.debugMode = debugMode;
data.restrictedBackupMode = isRestrictedBackupMode;
data.config = config;
//派发给ActivityThread.mH去处理执行H.BIND_APPLICATION
queueOrSendMessage(H.BIND_APPLICATION, data);
}
我们看mH是如何处理的,mH接收到H.BIND_APPLICATION消息执行的对应是handleBindApplication函数,handleBindApplication函数中做了大量初始化ActivityThread的操作:
初始化mConfiguration
设置进程名
本地语言设置
设置包名称
设置应用程序根路径
设置应用程序data路径
设置activity的context
等等,我没有详细看,有不正之处希望高手指正,小弟不胜感激
接着是第二步,scheduleLaunchActivity,先看调用堆栈:
ActivityThread$ApplicationThread.scheduleLaunchActivity(Intent, IBinder, int, ActivityInfo, Bundle, List, List, boolean, boolean) line: 1526
ActivityThread$ApplicationThread(ApplicationThreadNative).onTransact(int, Parcel, Parcel, int) line: 130
ActivityThread$ApplicationThread(Binder).execTransact(int, int, int, int) line: 288
NativeStart.run() line: not available [native method]
同样,该函数操作也是交给ActivityThread.mH来处理,对应case消息为:H.LAUNCH_ACTIVITY
交由函数handleLaunchActivity处理,在这个函数中,根据ActivityRecord对像,获取要启动的Activity类信息,然后创建一个Activity,执行Activity的生命周期函数:onCreate,onResume,至此ActivitThread的handleBindApplication和handleLaunchActivity完成Activity的启动操作。
最后,我再总结一下从桌面启动一个应用Activity的启动过程,画了一个时序图,有助于理解,希望走过路过的朋友别忘了留个脚印,或者留个砖板,这个blog花费了我不少时间:
相关推荐
Audio框架介绍、 Audio相关服务的创建、Audio的数据流、Audio的控制流等一些内容的介绍及代码流程分析
android framework 详解
Android Framework精编内核解析
android framework 实现细节,常见面试问题汇总
3.Android编译过程分析 4.android.mk初识 5.Android.mk学习1 6.Android.mk学习2 7.Android.mk学习3 8.Android启动课程大纲 9.Android启动模式 10.init启动分析 11.走入init启动脚本 12.init脚本解析分析 13.init脚本...
robotframework安装_RobotFramework——基于关键字驱动的 ⾃动化测。。。 突然发现官⽅Robot Framework RIDE项⽬更新了,新的版本基于wxPython4.0.4⽀持了Python3.x,⽆疑是对于Robot Framework推 ⼴的重⼤利好(由于...
Android_11_Activity 启动过程分析流程图原件
robotFramework——FOR循环语句 循环语句 robotframework⽀持FOR循环语句,语法和的语法基本相同,但robotframework中,"FOR"关键字前⾯需要增加⼀个":",写成":FOR",其它 与Python的语法相同。下⾯我们看看如何...
android Framework精编内核解析
This is a android framework full classes jar file
Android Framework精编内核解析.pdf 百度网盘永久地址
Android11.0 系统分析 Android11.0 启动分析 Android11.0 最新Framework解析 Android11.0 Binder通信原理
android framework相关面试题,详细深入的介绍了android framework相关知识点,可以很好帮助对android framework的深入理解
android Framework层的修改规则,包括了编译过程和jni调用等。
android framework 源代码
android framework面试题集 自己亲自总结的,各位有需要的可以随时下载
android framework开发经验总结
Android Framework 分析Android Framework 分析Android Framework 分析Android Framework 分析
Android framework 技术详解,framework层核心技术
Android 13.0 framework jar 包