理解 Android 进程启动之全过程

澳门新葡亰网站注册 4

2.2 四大组件与进程

Activity, Service, ContentProvider,
BroadcastReceiver这四大组件,在启动的过程,当其所承载的进程不存在时需要先创建进程.
这个创建进程的过程是调用前面讲到的startProcessLocked方法1(a) . 调用流程:
1(a) => 1(b) ==> 2(b).
下面再简单说说这4大组件与进程创建是在何时需要创建的.

Activity

Activity是展示型组件

startActivity will start a new activity,which will be placed at the top
of the activity stack.

startActivityResult will launch an activity and would return a result
when it finished.

  1. Activity.startActivityForResult
  2. Instrumentation.execStartActivity
  3. ActivityManagerProxy.startActivity
  4. ActivityManagerService.startActivity
  5. ActivityStack.startActivityMayWait
  6. ActivityStack.startActivityLocked
  7. ActivityStack.startActivityUncheckedLocked
  8. ActivityStack.resumeTopActivitiesLocked
  9. Activity.resumeTopActivityInnerLocked
  10. ActivityStack.startSpecificActivityLocked
  11. ActivityStack.realStartActivityLocked
  12. ApplicationThread.scheduleLaunchActivity
  13. sendMessage(LAUNCH_ACTIVITY)
  14. ActivityThread.handleLaunchActivity
  15. ActivityThread.performLaunchAcitvity
  16. MainActivity.onCreate

主要过程:

  1. Launcher通知AMS需要启动一个activity
  2. AMS创建一个新的进程,然后启动一个ActivityThread实例
  3. ActivityThread把ApplicationThread给AMS
  4. AMS通知ActivityThread可以启动Activity了

涉及的class

  • Launcher:android启动器
  • Activity:Activity类,包含一个成员变量m
  • Instrumentation:主要用来监控应用程序和系统间的交互
  • ActivityMangerProxy:ActivityManagerService 的代理
  • ActivityStack: 描述一个activity的堆栈
  • ApplicationThreadProxy:
  • ApplicationThread
  • ActivityThread:
  • ActivityManagerService:

ActivityManager框架

ActivityManager: Interact with the overall activities running in the
system.

澳门新葡亰网站注册 1

ActivityManager.png

ActivityManager在用户进程,执行操作的是在系统进程的AMS,从activityManager到ams是进程间通信,

可以类比如aidl以理解,ActivityManagerProxy是代理类,抽象类ActivityManagerNative是Stub类,IActivityManager是aidl类,ams就是service类;

ActivityManager使用的是remote
proxy模式设计的,可以实现跨进程的对象访问。

澳门新葡亰网站注册 2

image

这个图就是activityManager的执行的一个过程图。

ActivityStack

State and management of a single stack of activities.
activity destroy ,pause,stop,
resumeTopActivityLocked:ensure the top activity is resumed

ActivityThread

This manages the execution of the main thread in an application process,
scheduling and executing activities, broadcasts, and other operations on
it as the activity manager requests.

主线程主要管理,调度,执行activity和broadcast的操作。

ActivityThread即是Application的主线程,主线程的主要责任是快速处理UI事件和Broadcast消息,
注意的是,View组件由主线程执行,故onDraw是在主线程的,而surfaceView在后台线程。

android
app的入口是ActivityThread的main函数,这里做了这些事:创建Looper,Handler,ActivityThread,
ActivityThread的成员变量ApplicationThread是用来与AMS通信的,通信方式是binder。

ApplicationThread

ApplicationThread继承ApplicationThreadNative,

Cast a Binder object into an application thread interface, generating a
proxy if needed.

ApplicationThreadNative实现了IApplicationThread,

System private API for communicating with the application. This is given
to the activity manager by an application when it starts up, for the
activity manager to tell the application about things it needs to do.

3.7 AMS.attachApplication

[-> ActivityManagerService.java]

public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid); // 【见流程3.8】
        Binder.restoreCallingIdentity(origId);
    }
}

此处的thread便是ApplicationThreadProxy对象,用于跟前面通过Process.start()所创建的进程中ApplicationThread对象进行通信.

service

Service是计算型组件

装饰模式的目的是为了方便扩展,可以动态的给一个对象添加一些其他的职责。
activity在startService的时候使用了这个设计模式,
activity继承子contextWrapper,wrapper里有个ContextImpl的mBase,最终会调到AcitvityManagerProxy的startService。接着通过binder,调用ams的startService,

ActivityManagerService.startService
ActivityManagerService.startServiceLocked
ActivityManagerService.bringUpServiceLocked
ActivityManagerService.startProcessLocked
Process.start
ActivityThread.main
ActivityThread.attach
ActivityManagerProxy.attachApplication
ActivityManagerService.attachApplication
ActivityManagerService.attachApplicationLocked
ActivityManagerService.realStartServiceLocked
ApplicationThreadProxy.scheduleCreateService
ApplicationThread.scheduleCreateService
ActivityThread.queueOrSendMessage
H.sendMessage
H.handleMessage
ActivityThread.handleCreateService
ClassLoader.loadClass
Obtain Service
Service.onCreate

三个步骤:
主进程调用到ams,创建新进程
新进程调用到ams,获取信息
ams调用新进程,启动服务

3.5 AMP.attachApplication

[-> ActivityManagerProxy.java]

public void attachApplication(IApplicationThread app) throws RemoteException
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(app.asBinder());
    mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0); //【见流程3.6】
    reply.readException();
    data.recycle();
    reply.recycle();
}

此处 descriptor = “android.app.IActivityManager”

broadcast:

BroadcastReceiver是消息型组件

广播的好处是可以不知道对方存在,这样可以降低组件的耦合。
registerReceiver 过程分析:
AMS负责所有广播的注册和发布,
ContextWrapper.registerReceiver
ContextImpl.registerReceiver
ActivityThread.getHandler
LoadedApk.getReceiverDispatcher
ActivityManagerProxy.registerReceiver

sendBroadcast过程:
ContextWrapper.sendBroadcast
ContextImpl.sendBroadcast
ActivityManagerProxy.broadcastIntent
ActivityManagerService.broadcastIntent
ActivityManagerService.broadcastIntentLocked
ActivityManagerService.scheduleBroadcastsLocked
Handler.sendEmptyMessage
ActivityManagerService.processNextBroadcast
ActivityManagerService.deliverToRegisteredReceiverLocked
ActivityManagerService.performReceiveLocked
ApplicationThreadProxy.scheduleRegisteredReceiver
ApplicaitonThread.scheduleRegisteredReceiver
InnerReceiver.performReceive
ReceiverDispatcher.performReceive
Handler.post
Args.run
BroadcastReceiver.onReceive

3.9 ATP.bindApplication

[-> ApplicationThreadNative.java ::ApplicationThreadProxy]

class ApplicationThreadProxy implements IApplicationThread {
    ...
    public final void bindApplication(String packageName, ApplicationInfo info,
            List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
            Bundle testArgs, IInstrumentationWatcher testWatcher,
            IUiAutomationConnection uiAutomationConnection, int debugMode,
            boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,
            Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
            Bundle coreSettings) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeString(packageName);
        info.writeToParcel(data, 0);
        data.writeTypedList(providers);
        if (testName == null) {
            data.writeInt(0);
        } else {
            data.writeInt(1);
            testName.writeToParcel(data, 0);
        }
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        data.writeBundle(testArgs);
        data.writeStrongInterface(testWatcher);
        data.writeStrongInterface(uiAutomationConnection);
        data.writeInt(debugMode);
        data.writeInt(openGlTrace ? 1 : 0);
        data.writeInt(restrictedBackupMode ? 1 : 0);
        data.writeInt(persistent ? 1 : 0);
        config.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        data.writeMap(services);
        data.writeBundle(coreSettings);
        mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
    ...
}

ATP经过binder ipc传递到ATN的onTransact过程.

ContentProvider:

ContentProvider是数据共享型组件

ContentProvider下面使用的是Binder和匿名共享内存机制。
http://blog.csdn.net/luoshengyang/article/details/6963418
ArticlesAdapter.getArticleCount
ContentResolver.acqireProvider
ApplicationContentResolve.acquireProvider
ActivityThread.acquireProvider
ActivityThread.getProvider
ActivityManagerService.getContentProvider
ActivityManagerService.getContentProviderImpl
ActivityManagerService.startProcessLocked
Process.start
ActivityThread.main
ActivityThread.attach
ActivityManagerService.attachApplication
ActivityManagerService.attachApplicationLocked
ApplicationThread.bindApplication
ActivityThread.handleBindApplication
ActivityThread.installContentProviders
ActivityThread.installProvider
ContentProvider.getIContentProvider
ContentProvider.attachInfo
ArticlesProvider.onCreate
ActivityMangerService.publishContentProviders
ActivityThread.installProvider

共享数据原理:
ContentProvider组件通过匿名共享内存机制实现,只用传输一个文件描述符即可。
http://blog.csdn.net/luoshengyang/article/details/6967204
ArticlesAdapter.getArticleByPos
ContentResolver.query
ContentResolver.acquireProvider
ApplicationContentResolver.acquireProvider
ActivityThread.acquireProvider
ActivityThread.getProvider
ContentProviderProxy.query
CursorWindow.native_init
CursorWindow.initBuffer
ContentProviderProxy.bulkQueryInternal
CursorWindow.writeToParcel
CursorWindow.native_getBinder
CursorWindow.getMemory
ContentProviderNative.onTransact
CursorWindow.CREATOR.createFromParcel
CursorWindow.native_init
CursorWindow.setMemory
Transport.bulkQuery
ArticlesProvider.query
SQLiteQueryBuilder.query
SQLiteDatabase.rawQueryWithFactory
SQLiteCursorDriver.query
AbstractWindowedCursor.setWindow
SQLiteCursor.getCount
QLiteCursor.fillWindow
SQLiteCursor.fillWindow

class :
ContentResolver
This class provides applications access to the content model.
CursorWindow:
A buffer containing multiple cursor rows.
A CursorWindow is read-write when initially created and used locally.
When sent to a remote process (by writing it to a Parcel), the remote
process receives a read-only view of the cursor window. Typically the
cursor window will be allocated by the producer, filled with data, and
then sent to the consumer for reading.

3.12 H.SET_CORE_SETTINGS

[-> ActivityThread.java ::H]

当主线程收到H.SET_CORE_SETTINGS,则调用handleSetCoreSettings

private void handleSetCoreSettings(Bundle coreSettings) {
    synchronized (mResourcesManager) {
        mCoreSettings = coreSettings;
    }
    onCoreSettingsChange();
}

private void onCoreSettingsChange() {
    boolean debugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
    if (debugViewAttributes != View.mDebugViewAttributes) {
        View.mDebugViewAttributes = debugViewAttributes;

        // 由于发生改变, 请求所有的activities重启启动
        for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
            requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false);
        }
    }
}

2.3 小节

Activity, Service, ContentProvider,
BroadcastReceiver这四大组件在启动时,当所承载的进程不存在时,都需要创建.
进程的创建过程交由系统进程system_server来完成的.

澳门新葡亰网站注册 3

简称:

  • ATP: ApplicationThreadProxy
  • AT: ApplicationThread (继承于ApplicationThreadNative)
  • AMP: ActivityManagerProxy
  • AMS: ActivityManagerService (继承于ActivityManagerNative)

图解:

  1. system_server进程中调用startProcessLocked方法,该方法最终通过socket方式,将需要创建新进程的消息告知Zygote进程,并阻塞等待Socket返回新创建进程的pid;
  2. Zygote进程接收到system_server发送过来的消息,
    则通过fork的方法,将zygote自身进程复制生成新的进程,并将ActivityThread相关的资源加载到新进程app
    process,这个进程可能是用于承载activity等组件;
  3. 创建完新进程后fork返回两次, 在新进程app
    process向servicemanager查询system_server进程中binder服务端AMS,获取相对应的Client端,也就是AMP.
    有了这一对binder c/s对, 那么app
    process便可以通过binder向跨进程system_server发送请求,即attachApplication()
  4. system_server进程接收到相应binder操作后,经过多次调用,利用ATP向app
    process发送binder请求, 即bindApplication.

system_澳门新葡亰网站注册,server拥有ATP/AMS,
每一个新创建的进程都会有一个相应的AT/AMS,从而可以跨进程 进行相互通信.
这便是进程创建过程的完整生态链.

四大组件的进程创建时机:

组件 创建方法
Activity ASS.startSpecificActivityLocked()
Service ActiveServices.bringUpServiceLocked()
ContentProvider AMS.getContentProviderImpl()
Broadcast BroadcastQueue.processNextBroadcast()

四. 总结

本文首先介绍AMS的4个同名不同参数的方法startProcessLocked;
紧接着讲述了四大组件与进程的关系, Activity, Service, ContentProvider,
BroadcastReceiver这四大组件,在启动的过程,当其所承载的进程不存在时需要先创建进程.
再然后进入重点以startProcessLocked以引线一路讲解整个过程所遇到的核心方法.
在整个过程中有新创建的进程与system_server进程之间的交互过程
是通过binder进行通信的, 这里有两条binder通道分别为AMP/AMN 和 ATP/ATN.

澳门新葡亰网站注册 4

上图便是一次完整的进程创建过程,app的任何组件需要有一个承载其运行的容器,那就是进程,
那么进程的创建过程都是由系统进程system_server通过socket向zygote进程来请求fork()新进程,
当创建出来的app process与system_server进程之间的通信便是通过binder
IPC机制.

一. 概述

Android系统将进程做得很友好的封装,对于上层app开发者来说进程几乎是透明的.
了解Android的朋友,一定知道Android四大组件,但对于进程可能会相对较陌生.
一个进程里面可以跑多个app(通过share uid的方式),
一个app也可以跑在多个进程里(通过配置Android:process属性).

再进一步进程是如何创建的, 可能很多人不知道fork的存在.
在我的文章理解Android进程创建流程 集中一点详细介绍了Process.start的过程是如何一步步创建进程.本文则是从另个角度来全局性讲解Android进程启动全过程所涉及的根脉,
先来看看AMS.startProcessLocked方法.

2.1 startProcessLocked

ActivityManagerService.java关于启动进程有4个同名不同参数的重载方法,
为了便于说明,以下4个方法依次记为1(a),1(b)2(a)2(b) :

//方法 1(a)
final ProcessRecord startProcessLocked(
    String processName, ApplicationInfo info, boolean knownToBeDead,
    int intentFlags, String hostingType, ComponentName hostingName,
    boolean allowWhileBooting, boolean isolated, boolean keepIfLarge)

//方法 1(b)
final ProcessRecord startProcessLocked(
    String processName, ApplicationInfo info, boolean knownToBeDead,
    int intentFlags, String hostingType, ComponentName hostingName,
    boolean allowWhileBooting, boolean isolated, int isolatedUid,
    boolean keepIfLarge, String abiOverride, String entryPoint,
    String[] entryPointArgs, Runnable crashHandler)

//方法 2(a)
private final void startProcessLocked(
    ProcessRecord app, String hostingType, String hostingNameStr)

//方法 2(b)
private final void startProcessLocked(
    ProcessRecord app, String hostingType, String hostingNameStr,
    String abiOverride, String entryPoint, String[] entryPointArgs)

1(a) ==>
1(b): 方法1(a)将isolatedUid=0,其他参数赋值为null,再调用给1(b)

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

2(a) ==> 2(b): 方法2(a)将其他3个参数abiOverride,entryPoint,
entryPointArgs赋值为null,再调用给2(b)

private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
    startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
            null /* entryPoint */, null /* entryPointArgs */);
}

小结:

  • 1(a),1(b)的第一个参数为String类型的进程名processName,
  • 2(a), 2(b)的第一个参数为ProcessRecord类型进程记录信息ProcessRecord;
  • 1系列的方法最终调用到2系列的方法;

二. 四大组件与进程

3.3 ActivityThread.main

[-> ActivityThread.java]

public static void main(String[] args) {
    //性能统计默认是关闭的
    SamplingProfilerIntegration.start();
    //将当前进程所在userId赋值给sCurrentUser
    Environment.initForCurrentUser();

    EventLogger.setReporter(new EventLoggingReporter());
    AndroidKeyStoreProvider.install();

    //确保可信任的CA证书存放在正确的位置
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");

    //创建主线程的Looper对象, 该Looper是不运行退出
    Looper.prepareMainLooper();

    //创建ActivityThread对象
    ActivityThread thread = new ActivityThread();

    //建立Binder通道 【见流程3.4】
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    // 当设置为true时,可打开消息队列的debug log信息
    if (false) {
        Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop(); //消息循环运行
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
  • 创建主线程的Looper对象: 该Looper是不运行退出.
    也就是说主线程的Looper是在进程创建完成时自动创建完成,如果子线程也需要创建handler通信过程,那么就需要手动创建Looper对象,并且每个线程只能创建一次.
  • 创建ActivityThread对象thread = new ActivityThread():
    该过程会初始化几个很重要的变量:

    • mAppThread = new ApplicationThread()
    • mLooper = Looper.myLooper()
    • mH = new H(), H继承于Handler;用于处理组件的生命周期.
  • attach过程是当前主线程向system_server进程通信的过程,
    将thread信息告知AMS.接下来还会进一步说明该过程.
  • sMainThreadHandler通过getHandler(),获取的对象便是mH,这就是主线程的handler对象.

之后主线程调用Looper.loop(),进入消息循环状态,
当没有消息时主线程进入休眠状态,
一旦有消息到来则唤醒主线程并执行相关操作.

2.2.4 Broadcast

广播处理过程: 调用sendBroadcast,该方法经过层层调用,
最终会调用到BroadcastQueue.java中的processNextBroadcast,当BroadcastReceiver所对应的进程尚未启动,则创建相应进程.
更多关于broadcast, 见Android
Broadcast广播机制分析.

[-> BroadcastQueue.java]

final void processNextBroadcast(boolean fromMsg) {
    ...
    ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
        info.activityInfo.applicationInfo.uid, false);
    if (app != null && app.thread != null) {
        ...  //进程已创建的case
        return
    }

    if ((r.curApp=mService.startProcessLocked(targetProcess,
            info.activityInfo.applicationInfo, true,
            r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
            "broadcast", r.curComponent,
            (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
                    == null) {
        ...
    }
    ...
}