- 浏览: 660767 次
文章分类
最新评论
-
涛声依旧是:
怎么提示掉线,怎么才能在线
基于Tomcat7、Java、WebSocket的服务器推送聊天室 -
dcode:
楼主写的不错,正好遇到点问题,看着你的文章解决了,感谢分享。。 ...
在 Visual Studio 2010 中配置SharpPcap
Android FrameWork——Activity启动过程详解
前面发了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花费了我不少时间:
相关推荐
《安卓Android源码——系统原理与开发要点详解》是一份深度剖析Android操作系统的培训资料,旨在帮助开发者深入了解Android系统的内部工作原理以及优化开发流程。这份资料涵盖了从Android系统的架构到具体开发实践的...
2. **Android Framework**:理解Intent、BroadcastReceiver、Service、ContentProvider、Activity等核心组件的工作原理。 3. **UI系统**:包括View和 ViewGroup的层次结构,以及动画、触摸事件的处理流程。 4. **...
2.3 创建第一个Android项目——HeUoAndroid 2.3.1 创建HelloAndroid项目 2.3.2 运行HelloAndroid及模拟器的使用 2.3.3 调试HelloAndroid 2.4 小结 第二部分 基础篇 第3章 Android程序设计基础 3.1 Android程序框架 ...
### Android系统启动过程详解 #### 一、概述 Android系统的启动流程从硬件加电到用户看到可用的应用程序桌面,经过了一系列复杂的过程。本篇文章将详细解释这一过程中的关键步骤及其背后的原理。 #### 二、从硬件...
它还以迭代的方式重现了各种常用的Android应用和经典Android游戏的开发全过程,既可以以它们为范例进行实战演练,又可以将它们直接应用到实际开发中去。 目录 -------------------------------------------------...
- **Application Framework**:这是Android应用程序开发的基础,包含了一系列的API,如Activity Manager、Notification Manager、Content Provider、View System等,它们构成了应用程序运行的基本环境,简化了开发者...
7.5 Android应用的灵魂——Intent和Activity介绍与实例 7.5.1 实例操作演示 7.5.2 实例编程实现 7.6 用好列表,做好程序——列表(ListView)介绍与实例 7.6.1 实例程序演示 7.6.2 实例编程实现 7.7 友好地互动交流...
7.5 Android应用的灵魂——Intent和Activity介绍与实例 106 7.5.1 实例操作演示 106 7.5.2 实例编程实现 106 7.6 用好列表,做好程序——列表(ListView)介绍与实例 111 7.6.1 实例程序演示 111 7.6.2...
《安卓系统源码详解——基于Android 14的探索与学习》 Android系统源码是开发者深入了解操作系统工作原理、定制个性化系统以及优化应用性能的重要工具。Android 14的源码,作为Android发展历程中的一个重要版本,为...
《Android系统架构详解——高焕堂视角》 在Android领域,高焕堂先生是一位备受尊敬的专家,他的讲解深入浅出,对Android系统架构的剖析尤为透彻。本篇文章将根据高焕堂先生的观点,详细阐述Android系统的架构,旨在...
### Android与JUnit单元测试详解 #### 一、JUnit简介及基本概念 JUnit 是一款非常流行的 Java 测试框架,主要用于编写和执行单元测试。随着 Android 开发的普及和发展,JUnit 在 Android 开发领域也变得越来越重要...
### Android 输入法详解 #### 一、为何关注中文输入法? 在移动设备上,中文输入法的使用极为广泛。由于中文字符数量庞大且输入方式复杂,如何通过有限的物理或虚拟按键来高效输入中文,成为了Android平台面临的一...
【标题】"Experiment15.rar" 提供的资源聚焦于 Android 编程中的一个经典案例——音乐播放器的实现。这个实验可能包含了实现一个功能完备的音乐播放应用所需的关键技术点,旨在帮助开发者深入理解 Android 应用开发...