您的位置:首页 > 移动开发 > Android开发

Android FrameWork——Activity启动过程详解

2016-04-14 09:58 579 查看
前面发了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("");

//建立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()

: "";

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 providers,

ComponentName instrumentationName, String profileFile,

Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,

int debugMode, boolean isRestrictedBackupMode, Configuration config,

Map 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花费了我不少时间:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: