Android7.0 PhoneApp的启动

前言 
最近准备写一写Android中数据业务相关的内容,考虑到数据业务是基于PhoneApp的,因此需要先来分析一下PhoneApp是如何启动的。

版本 
Android 7.0

1 AndroidManifest.xml 
为了弄清楚PhoneApp如何启动,我们首先必须先看一下PhoneApp对应的AndroidManifest.xml,它的位置为package/services/Telephony。

............
<application android:name="PhoneApp"
            //注意persistent字段
            android:persistent="true"
            android:label="@string/phoneAppLabel"
            android:icon="@mipmap/ic_launcher_phone"
            android:allowBackup="false"
            android:supportsRtl="true"
            android:usesCleartextTraffic="true"
            android:defaultToDeviceProtectedStorage="true"
            //注意directBootAware字段
            android:directBootAware="true">

............
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

上面的代码中,persistent表示应用是常驻的;directBootAware表示应用是可直接启动的。这两个字段决定了PhoneApp开机后,将被ActivityManagerService启动。

从 Android N 开始,在首次开机时,在用户尚未来得及解锁设备之前,设备可直接启动到一种名为 Direct Boot(直接启动)的新模式中。在此模式下,操作系统可以全功能运行,但不允许访问私有应用数据,只能运行经过更新、可支持直接启动功能的应用。

2 启动过程 
现在,我们来看看具体的启动过程。 
我们知道,当SystemServer进程被zygote进程创建后,在SystemServer的run方法中会启动系统所需的关键服务:

.........
try {
    Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
    startBootstrapServices();
    startCoreServices();
    startOtherServices();
} catch (Throwable ex) {
    .......
} finally {
    .......
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在startBootstrapServices函数中将启动ActivityServiceManager:

private void startBootstrapServices() {
    ...........
    //SystemServiceManager反射加载ActivityManagerService.Lifecycle
    //ActivityManagerService.Lifecycle创建出ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService();       
    ............
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

之后在startOtherServices中:

private void startOtherServices() {
    .............
    mActivityManagerService.systemReady(new Runnable() {......});
    .............
}
  • 1
  • 2
  • 3
  • 4
  • 5

在ActivityManagerService的systemReady函数中:

public void systemReady(final Runnable goingCallback) {
    ............
    //注意此处的参数MATCH_DIRECT_BOOT_AWARE
    startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
    ............
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

从上面的代码可以看出,systemReady将调用startPersistentApps启动某一类Application。

private void startPersistentApps(int matchFlags) {
    ........
    synchronized (this) {
        try{
            //从PackageManagerService中获取同时具有Persistent和directBootAware标签的应用列表
            final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
                             .getPersistentApplications(STOCK_PM_FLAGS | matchFlags)
                             .getList();
            for (ApplicationInfo app : apps) {
                if (!"android".equals(app.packageName)) {
                    //启动这些应用
                    addAppLocked(app, false, null /* ABI override */);
                }
            }
        }catch (RemoteException ex) {
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

从上面的代码,我们知道PhoneApp将有addAppLocked进行处理:

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated, String abiOverride) {
    .........
    startProcessLocked(app, "added application", app.processName, abiOverride,
                    null /* entryPoint */, null /* entryPointArgs */);
    .........
}

private final void startProcessLocked(........) {
    .........
    //这里之前的blog提到过,将利用socket发送消息给zygote分裂出应用所需的进程
    //进程创建出后,将调用对应类的main函数,对于PhoneApp而言,即android.app.ActivityThread
    Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在ActivityThread.java的main函数中:

.........
ActivityThread thread = new ActivityThread();
//PhoneApp不是系统App
thread.attach(false);
.........
  • 1
  • 2
  • 3
  • 4
  • 5

继续看看attach函数:

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        .............
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //binder通信,获取Remote端
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //将ApplicationThread传给AM,实际上传递的是binder代理
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        ...........
    }..............
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

从上面的代码可以看出,流程再次回到了ActivityManagerService:

@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    ...........
    //将调用ApplicationThread的bindApplication
    thread.bindApplication(.....);
    ...........
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

我们看看ApplicationThreadNative.java中ApplicationThreadProxy的bindApplication函数:

class ApplicationThreadProxy implements IApplicationThread {
    ............
    @Override
    public final void bindApplication(....) {
        ........
        //利用binder通信,ActivityManagerService将消息发回给PhoneApp中的ActivityThread
        mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);
        ........
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在ActivityThread.java中的handler H的handleMessage处理消息(在PhoneApp中的binder解析完收到的数据后,触发BIND_APPLICATION消息给H):

.............
case BIND_APPLICATION:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
    AppBindData data = (AppBindData)msg.obj;
    //处理数据
    handleBindApplication(data);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
............
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
private void handleBindApplication(AppBindData data) {
    ..........
    try {
        mInstrumentation.callApplicationOnCreate(app);
    } catch (Exception e) {
        ........
    }
    ........
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
public void callApplicationOnCreate(Application app) {
    app.onCreate();
}
  • 1
  • 2
  • 3

经过上面的过程,PhoneApp终于可以启动了。 
我们大致回忆一下整个过程: 
1. SystemServer进程会创建出AM和PM,PM会加载Application的信息。 
2. 当AM的SystemReady被调用后,将利用PM得到具有persistent和directBootAware的应用列表,PhoneApp就在其中。 
3. AM利用socket向zygote发送消息,启动PhoneApp对应的进程。 
4. zygote进程启动PhoneApp进程后,将利用反射调用PhoneApp中ActivityThread的main函数。 
5. ActivityThread的main函数被调用后,将利用binder通信向AM发送消息;AM进行对应的处理,处理完成后,同样利用binder通信将处理结果返回给ActivityThread。 
6. 最后ActivityThread收到处理结果后,完成最后的准备工作(设置参数之类),并调用PhoneApp的onCreate函数。

结束语 
上属流程中有一部分应该适用于所有应用的启动,当然AM和PM的流程,包括Binder的一些内容,分析起来比较复杂,自己目前也没有深入研究,因此上面只描述了主要结构。



原文地址:http://blog.csdn.net/gaugamela/article/details/52311508

猜你喜欢

转载自blog.csdn.net/f2006116/article/details/78031493
今日推荐