美文网首页
从一个APP进程启动说起(下)

从一个APP进程启动说起(下)

作者: 我叫王菜鸟 | 来源:发表于2017-08-28 22:11 被阅读0次

简介

回顾我们上一次说的一个app进程的启动过程,比如现在是当我们点击桌面上应用的图标,就会通过AMS,也就是system_server进程去和zygoteinit所在进程也就是zygote进程通过socket方式将启动进程所需要的参数传递给zygote,zygote在一个循环中一直在监听,当监有数据到来时候将数据封装之后fork出来子进程,子进程创建完成之后做一些Android环境的初始化,最终通过抛出异常的方式将调用到ActivityThread.main方法中。

我们今天的主题就接着上次说,开始我们可见的app之旅吧。

简介

回顾我们上一次说的一个app进程的启动过程,比如现在是当我们点击桌面上应用的图标,就会通过AMS,也就是system_server进程去和zygoteinit所在进程也就是zygote进程通过socket方式将启动进程所需要的参数传递给zygote,zygote在一个循环中一直在监听,当监有数据到来时候将数据封装之后fork出来子进程,子进程创建完成之后做一些Android环境的初始化,最终通过抛出异常的方式将调用到ActivityThread.main方法中。

我们今天的主题就接着上次说,开始我们可见的app之旅吧。

AT.main().png

扫个盲

//ZygoteInit.main()
public static void main(String argv[]) {
    try {
        runSelectLoop(abiList);
        ....
    } catch (MethodAndArgsCaller caller) {
        caller.run(); 
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}

我们昨天一开始就执行这段代码,这段代码最终又跑去子进程的这段代码中caller.run();所以故事发生在主线程

1. ActivityThread.main()

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通道
    thread.attach(false);//[2]
    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");
}

这里注意事项:

ActivityThread还有一个地方可以创建就是在:

SystemServer.run()
    createSystemContext()
        ActivityThread.systemMain()
            ActivityThread thread = new ActivityThread();
            thread.attach(true);//这里是true

小节上面:

  • 创建主线程的Looper对象, 该Looper是不运行退出
  • 创建ActivityThread对象

我们还要注意,在创建AT中发生了什么:

  • 创建了ResourcesManager对象
ActivityThread() {
    mResourcesManager = ResourcesManager.getInstance();
}
  • 成员变量中创建了ApplicationThread mAppThread = new ApplicationThread();
  • H mH = new H();给主线程发送消息的Handler对象

2. ActivityThread.attach()

ActivityThread.java

//这里system=false
private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
         //开启虚拟机的jit即时编译功能
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());

        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //创建ActivityManagerProxy对象
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //调用基于IActivityManager接口的Binder通道
            mgr.attachApplication(mAppThread);//[3]
        } catch (RemoteException ex) {
        }

        //观察是否快接近heap的上限
        BinderInternal.addGcWatcher(new Runnable() {
            @Override public void run() {
                if (!mSomeActivitiesChanged) {
                    return;
                }
                Runtime runtime = Runtime.getRuntime();
                long dalvikMax = runtime.maxMemory();
                long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                if (dalvikUsed > ((3*dalvikMax)/4)) {
                    mSomeActivitiesChanged = false;
                    try {
                        //当已用内存超过最大内存的3/4,则请求释放内存空间
                        mgr.releaseSomeActivities(mAppThread);
                    } catch (RemoteException e) {
                    }
                }
            }
        });
    } else {
        ...
    }
    //添加dropbox日志到libcore
    DropBox.setReporter(new DropBoxReporter());

    //添加Config回调接口
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mResourcesManager) {
                if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        @Override
        public void onLowMemory() {
        }
        @Override
        public void onTrimMemory(int level) {
        }
    });
}

这里做的事情:

  • ensureJitEnabled();具体是啥不知道
  • android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());设置进程名
  • 创建AMP
  • 给AMP绑定ApplicationThread对象
  • 看app进程内存情况,如果太大则释放内存
  • 给ViewRootImpl添加一个config的回调接口

这里需要注意:
final IActivityManager mgr = ActivityManagerNative.getDefault();

static public IActivityManager getDefault() {
    return gDefault.get();
}

这里得到的Service是activity,activity是在SystemServer中通过AMS.setSystemProcess()中添加的服务,对应AMS

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

3. AMS.attachApplication()

ActivityManagerService.java

在这里我们把握一个核心,这里子进程已经通过Binder调用到了AMS所在进程,也就是system_server进程了

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {//此pid是调用者的pid
    ProcessRecord app;
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid); // 根据pid获取ProcessRecord对象
        }
    } else {
        app = null;
    }
    if (app == null) {
        if (pid > 0 && pid != MY_PID) {
            //ProcessRecord为空,则杀掉该进程
            Process.killProcessQuiet(pid);
        } else {
            //退出新建进程的Looper
            thread.scheduleExit();
        }
        return false;
    }

    //还刚进入attach过程,此时thread应该为null,若不为null则表示该app附到上一个进程,则立刻清空
    if (app.thread != null) {
        handleAppDiedLocked(app, true, true);
    }

    final String processName = app.processName;
    try {
        //绑定死亡通知,注意这里是ApplicationThread的代理对象要linkToDeath
        //也就是如果ApplicationThread(继承Binder)挂掉了在AppDeathRecipient中可以接收到信息
        AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        startProcessLocked(app, "link fail", processName); //重新启动进程
        return false;
    }

    //重置进程信息
    app.makeActive(thread, mProcessStats); //执行完该语句,则app.thread便不再为空
    app.curAdj = app.setAdj = -100;
    app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
    app.forcingToForeground = null;
    updateProcessForegroundLocked(app, false, false);
    app.hasShownUi = false;
    app.debugging = false;
    app.cached = false;
    app.killedByAm = false;
    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); //移除进程启动超时的消息,这里超时是在AMS启动进程时候加上去的,所以这里一旦启动就要移除

    //系统处于ready状态或者该app为FLAG_PERSISTENT进程,则为true
    boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
    List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;

    //app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
    //这里已经开始provider的操作了
    if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
        Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
        msg.obj = app;
        mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
    }

    try {
        ...
        //获取应用appInfo
        ApplicationInfo appInfo = app.instrumentationInfo != null
                ? app.instrumentationInfo : app.info;
        ...
        // 绑定应用[4]
        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked());
        //更新进程LRU队列
        updateLruProcessLocked(app, false, null);
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
    } catch (Exception e) {
        app.resetPackageList(mProcessStats);
        app.unlinkDeathRecipient();
        //每当bind操作失败,则重启启动进程, 此处有可能会导致进程无限重启
        startProcessLocked(app, "bind fail", processName);
        return false;
    }

    mPersistentStartingProcesses.remove(app);
    mProcessesOnHold.remove(app);
    boolean badApp = false;
    boolean didSomething = false;

    //Activity: 检查最顶层可见的Activity是否等待在该进程中运行
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            badApp = true;
        }
    }

    //Service: 寻找所有需要在该进程中运行的服务
    if (!badApp) {
        try {
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
            badApp = true;
        }
    }

    //Broadcast: 检查是否在这个进程中有下一个广播接收者
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        try {
            didSomething |= sendPendingBroadcastsLocked(app);
        } catch (Exception e) {
            badApp = true;
        }
    }
    //检查是否在这个进程中有下一个backup代理
    if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
        ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
        try {
            thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
                    compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
                    mBackupTarget.backupMode);
        } catch (Exception e) {
            badApp = true;
        }
    }
    if (badApp) { //杀掉bad应用
        app.kill("error during init", true);
        handleAppDiedLocked(app, false, true);
        return false;
    }
    if (!didSomething) {
        updateOomAdjLocked(); //更新adj的值
    }
    return true;
}

我们这里必须小节一下:

  • 设置代表该应用进程的ProcessRecord对象的一些成员变量
  • 初步设置oo_adj的值,这个是进程优先级核心
  • 撤销PROC_START+TIMEOUT_MSG对应操作
  • 调用ApplicationThread的binderApplication
  • 通知应用进程启动Acivity,Service等组件其中用于启动activity的函数是realStartActivityLocked

4. ApplicationThread.bindApplication()

我们通过APP所在进程,然后通过binder跨到AMS,通过AMS做一些处理之后,然后又调用到APP的进程中保存一些AMS处理过后的信息

public final void bindApplication(String processName, ApplicationInfo appInfo,
        List<ProviderInfo> providers, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation,
        boolean isRestrictedBackupMode, boolean persistent, Configuration config,
        CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {

    if (services != null) {
        //保存AMS传递来系统service的信息
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);//给主线程发消息H.SET_CORE_SETTINGS保存coreSettings的值

    AppBindData data = new AppBindData();//存储变量的
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.instrumentationUiAutomationConnection = instrumentationUiConnection;
    data.debugMode = debugMode;
    data.enableBinderTracking = enableBinderTracking;
    data.trackAllocation = trackAllocation;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    sendMessage(H.BIND_APPLICATION, data);//[5]给主线程发送消息BIND_APPLICATION,将data传递过去
}

其中setCoreSettings(coreSettings);这一句也很重要

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);
        }
    }
}

5. ActivityThread.handleBindApplication(data);

private void handleBindApplication(AppBindData data) {

    mBoundApplication = data;
    mConfiguration = new Configuration(data.config);
    mCompatConfiguration = new Configuration(data.config);
    ...

    //设置进程名, 也就是说进程名是在进程真正创建以后的BIND_APPLICATION过程中才取名,前面那个名字不算
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());

    if (data.persistent) {
        //低内存设备, persistent进程不采用硬件加速绘制,以节省内存使用量
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(false);
        }
    }

    //重置时区
    TimeZone.setDefault(null);
    Locale.setDefault(data.config.locale);

    //更新系统配置
    mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
    mCurDefaultDisplayDpi = data.config.densityDpi;
    applyCompatConfiguration(mCurDefaultDisplayDpi);

    //获取LoadedApk对象[5.1]
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    // 创建ContextImpl上下文
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    if (!Process.isIsolated()) {
        final File cacheDir = appContext.getCacheDir();
        if (cacheDir != null) {
            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
        }

        //用于存储产生/编译的图形代码
        final File codeCacheDir = appContext.getCodeCacheDir();
        if (codeCacheDir != null) {
            setupGraphicsSupport(data.info, codeCacheDir);
        }
    }
    ...

    //当处于调试模式,则运行应用生成systrace信息
    boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    Trace.setAppTracingAllowed(appTracingAllowed);

    //初始化 默认的http代理
    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    if (b != null) {
        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
        final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
        Proxy.setHttpProxySystemProperty(proxyInfo);
    }

    if (data.instrumentationName != null) {
        ...
    } else {
        mInstrumentation = new Instrumentation();
    }

    //FLAG_LARGE_HEAP则清除内存增长上限
    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    } else {
        dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
    }

    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象[5.2]
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        if (!data.restrictedBackupMode) {
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                installContentProviders(app, providers);
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }

        mInstrumentation.onCreate(data.instrumentationArgs);
        //调用Application.onCreate()回调方法.
        mInstrumentation.callApplicationOnCreate(app);

    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

小节:

  • 创建一个Application对象,该对象是本进程中运行的第一个Application,是通过指LoadedApk
  • 如果该Application有ContentProvider则应该安装他们

在这里就开始创建ContentProvider了,所以ContentProvider的创建比其他组件要早。

5.1 ActivityThread.getPackageInfoNoCheck()

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
        CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
        ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
    final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (differentUser) {
            // Caching not supported across users
            ref = null;
        } else if (includeCode) {
            ref = mPackages.get(aInfo.packageName);
        } else {
            ref = mResourcePackages.get(aInfo.packageName);
        }

        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            packageInfo =
                new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

            if (mSystemThread && "android".equals(aInfo.packageName)) {
                packageInfo.installSystemApplicationInfo(aInfo,
                        getSystemContext().mPackageInfo.getClassLoader());
            }

            if (differentUser) {
                // Caching not supported across users
            } else if (includeCode) {
                mPackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            }
        }
        return packageInfo;
    }
}

5.1做的事情主要就是创建了LoadedApk然后返回

5.2 LoadedApk.makeApplication()

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }
    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";//默认在这里
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);//创建ContextImpl对象
        //创建Application对象, 该对象名来自于mApplicationInfo.className.
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    }

    // Rewrite the R 'constants' for all library apks.
    SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
            .getAssignedPackageIdentifiers();
    final int N = packageIdentifiers.size();
    for (int i = 0; i < N; i++) {
        final int id = packageIdentifiers.keyAt(i);
        if (id == 0x01 || id == 0x7f) {
            continue;
        }
        //写R常量
        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    }
    return app;
}

主要做了三件事

  • 创建ContextImpl对象
  • 创建Application对象, 该对象名来自于mApplicationInfo.className.
  • 重写了R常量

扫个盲

//ZygoteInit.main()
public static void main(String argv[]) {
    try {
        runSelectLoop(abiList);
        ....
    } catch (MethodAndArgsCaller caller) {
        caller.run(); 
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}

我们昨天一开始就执行这段代码,这段代码最终又跑去子进程的这段代码中caller.run();所以故事发生在主线程

1. ActivityThread.main()

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通道
    thread.attach(false);//[2]
    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");
}

这里注意事项:

ActivityThread还有一个地方可以创建就是在:

SystemServer.run()
    createSystemContext()
        ActivityThread.systemMain()
            ActivityThread thread = new ActivityThread();
            thread.attach(true);//这里是true

小节上面:

  • 创建主线程的Looper对象, 该Looper是不运行退出
  • 创建ActivityThread对象

我们还要注意,在创建AT中发生了什么:

  • 创建了ResourcesManager对象
ActivityThread() {
    mResourcesManager = ResourcesManager.getInstance();
}
  • 成员变量中创建了ApplicationThread mAppThread = new ApplicationThread();
  • H mH = new H();给主线程发送消息的Handler对象

2. ActivityThread.attach()

ActivityThread.java

//这里system=false
private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
         //开启虚拟机的jit即时编译功能
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());

        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //创建ActivityManagerProxy对象
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //调用基于IActivityManager接口的Binder通道
            mgr.attachApplication(mAppThread);//[3]
        } catch (RemoteException ex) {
        }

        //观察是否快接近heap的上限
        BinderInternal.addGcWatcher(new Runnable() {
            @Override public void run() {
                if (!mSomeActivitiesChanged) {
                    return;
                }
                Runtime runtime = Runtime.getRuntime();
                long dalvikMax = runtime.maxMemory();
                long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                if (dalvikUsed > ((3*dalvikMax)/4)) {
                    mSomeActivitiesChanged = false;
                    try {
                        //当已用内存超过最大内存的3/4,则请求释放内存空间
                        mgr.releaseSomeActivities(mAppThread);
                    } catch (RemoteException e) {
                    }
                }
            }
        });
    } else {
        ...
    }
    //添加dropbox日志到libcore
    DropBox.setReporter(new DropBoxReporter());

    //添加Config回调接口
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mResourcesManager) {
                if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        @Override
        public void onLowMemory() {
        }
        @Override
        public void onTrimMemory(int level) {
        }
    });
}

这里做的事情:

  • ensureJitEnabled();具体是啥不知道
  • android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());设置进程名
  • 创建AMP
  • 给AMP绑定ApplicationThread对象
  • 看app进程内存情况,如果太大则释放内存
  • 给ViewRootImpl添加一个config的回调接口

这里需要注意:
final IActivityManager mgr = ActivityManagerNative.getDefault();

static public IActivityManager getDefault() {
    return gDefault.get();
}

这里得到的Service是activity,activity是在SystemServer中通过AMS.setSystemProcess()中添加的服务,对应AMS

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

3. AMS.attachApplication()

ActivityManagerService.java

在这里我们把握一个核心,这里子进程已经通过Binder调用到了AMS所在进程,也就是system_server进程了

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {//此pid是调用者的pid
    ProcessRecord app;
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid); // 根据pid获取ProcessRecord对象
        }
    } else {
        app = null;
    }
    if (app == null) {
        if (pid > 0 && pid != MY_PID) {
            //ProcessRecord为空,则杀掉该进程
            Process.killProcessQuiet(pid);
        } else {
            //退出新建进程的Looper
            thread.scheduleExit();
        }
        return false;
    }

    //还刚进入attach过程,此时thread应该为null,若不为null则表示该app附到上一个进程,则立刻清空
    if (app.thread != null) {
        handleAppDiedLocked(app, true, true);
    }

    final String processName = app.processName;
    try {
        //绑定死亡通知,注意这里是ApplicationThread的代理对象要linkToDeath
        //也就是如果ApplicationThread(继承Binder)挂掉了在AppDeathRecipient中可以接收到信息
        AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        startProcessLocked(app, "link fail", processName); //重新启动进程
        return false;
    }

    //重置进程信息
    app.makeActive(thread, mProcessStats); //执行完该语句,则app.thread便不再为空
    app.curAdj = app.setAdj = -100;
    app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
    app.forcingToForeground = null;
    updateProcessForegroundLocked(app, false, false);
    app.hasShownUi = false;
    app.debugging = false;
    app.cached = false;
    app.killedByAm = false;
    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); //移除进程启动超时的消息,这里超时是在AMS启动进程时候加上去的,所以这里一旦启动就要移除

    //系统处于ready状态或者该app为FLAG_PERSISTENT进程,则为true
    boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
    List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;

    //app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
    //这里已经开始provider的操作了
    if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
        Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
        msg.obj = app;
        mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
    }

    try {
        ...
        //获取应用appInfo
        ApplicationInfo appInfo = app.instrumentationInfo != null
                ? app.instrumentationInfo : app.info;
        ...
        // 绑定应用[4]
        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked());
        //更新进程LRU队列
        updateLruProcessLocked(app, false, null);
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
    } catch (Exception e) {
        app.resetPackageList(mProcessStats);
        app.unlinkDeathRecipient();
        //每当bind操作失败,则重启启动进程, 此处有可能会导致进程无限重启
        startProcessLocked(app, "bind fail", processName);
        return false;
    }

    mPersistentStartingProcesses.remove(app);
    mProcessesOnHold.remove(app);
    boolean badApp = false;
    boolean didSomething = false;

    //Activity: 检查最顶层可见的Activity是否等待在该进程中运行
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            badApp = true;
        }
    }

    //Service: 寻找所有需要在该进程中运行的服务
    if (!badApp) {
        try {
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
            badApp = true;
        }
    }

    //Broadcast: 检查是否在这个进程中有下一个广播接收者
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        try {
            didSomething |= sendPendingBroadcastsLocked(app);
        } catch (Exception e) {
            badApp = true;
        }
    }
    //检查是否在这个进程中有下一个backup代理
    if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
        ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
        try {
            thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
                    compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
                    mBackupTarget.backupMode);
        } catch (Exception e) {
            badApp = true;
        }
    }
    if (badApp) { //杀掉bad应用
        app.kill("error during init", true);
        handleAppDiedLocked(app, false, true);
        return false;
    }
    if (!didSomething) {
        updateOomAdjLocked(); //更新adj的值
    }
    return true;
}

我们这里必须小节一下:

  • 设置代表该应用进程的ProcessRecord对象的一些成员变量
  • 初步设置oo_adj的值,这个是进程优先级核心
  • 撤销PROC_START+TIMEOUT_MSG对应操作
  • 调用ApplicationThread的binderApplication
  • 通知应用进程启动Acivity,Service等组件其中用于启动activity的函数是realStartActivityLocked

4. ApplicationThread.bindApplication()

我们通过APP所在进程,然后通过binder跨到AMS,通过AMS做一些处理之后,然后又调用到APP的进程中保存一些AMS处理过后的信息

public final void bindApplication(String processName, ApplicationInfo appInfo,
        List<ProviderInfo> providers, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation,
        boolean isRestrictedBackupMode, boolean persistent, Configuration config,
        CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {

    if (services != null) {
        //保存AMS传递来系统service的信息
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);//给主线程发消息H.SET_CORE_SETTINGS保存coreSettings的值

    AppBindData data = new AppBindData();//存储变量的
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.instrumentationUiAutomationConnection = instrumentationUiConnection;
    data.debugMode = debugMode;
    data.enableBinderTracking = enableBinderTracking;
    data.trackAllocation = trackAllocation;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    sendMessage(H.BIND_APPLICATION, data);//[5]给主线程发送消息BIND_APPLICATION,将data传递过去
}

其中setCoreSettings(coreSettings);这一句也很重要

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);
        }
    }
}

5. ActivityThread.handleBindApplication(data);

private void handleBindApplication(AppBindData data) {

    mBoundApplication = data;
    mConfiguration = new Configuration(data.config);
    mCompatConfiguration = new Configuration(data.config);
    ...

    //设置进程名, 也就是说进程名是在进程真正创建以后的BIND_APPLICATION过程中才取名,前面那个名字不算
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());

    if (data.persistent) {
        //低内存设备, persistent进程不采用硬件加速绘制,以节省内存使用量
        if (!ActivityManager.isHighEndGfx()) {
            HardwareRenderer.disable(false);
        }
    }

    //重置时区
    TimeZone.setDefault(null);
    Locale.setDefault(data.config.locale);

    //更新系统配置
    mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
    mCurDefaultDisplayDpi = data.config.densityDpi;
    applyCompatConfiguration(mCurDefaultDisplayDpi);

    //获取LoadedApk对象[5.1]
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    // 创建ContextImpl上下文
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    if (!Process.isIsolated()) {
        final File cacheDir = appContext.getCacheDir();
        if (cacheDir != null) {
            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
        }

        //用于存储产生/编译的图形代码
        final File codeCacheDir = appContext.getCodeCacheDir();
        if (codeCacheDir != null) {
            setupGraphicsSupport(data.info, codeCacheDir);
        }
    }
    ...

    //当处于调试模式,则运行应用生成systrace信息
    boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    Trace.setAppTracingAllowed(appTracingAllowed);

    //初始化 默认的http代理
    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    if (b != null) {
        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
        final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
        Proxy.setHttpProxySystemProperty(proxyInfo);
    }

    if (data.instrumentationName != null) {
        ...
    } else {
        mInstrumentation = new Instrumentation();
    }

    //FLAG_LARGE_HEAP则清除内存增长上限
    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    } else {
        dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
    }

    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象[5.2]
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        if (!data.restrictedBackupMode) {
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                installContentProviders(app, providers);
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }

        mInstrumentation.onCreate(data.instrumentationArgs);
        //调用Application.onCreate()回调方法.
        mInstrumentation.callApplicationOnCreate(app);

    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

小节:

  • 创建一个Application对象,该对象是本进程中运行的第一个Application,是通过指LoadedApk
  • 如果该Application有ContentProvider则应该安装他们

在这里就开始创建ContentProvider了,所以ContentProvider的创建比其他组件要早。

5.1 ActivityThread.getPackageInfoNoCheck()

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
        CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
        ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
    final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (differentUser) {
            // Caching not supported across users
            ref = null;
        } else if (includeCode) {
            ref = mPackages.get(aInfo.packageName);
        } else {
            ref = mResourcePackages.get(aInfo.packageName);
        }

        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            packageInfo =
                new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

            if (mSystemThread && "android".equals(aInfo.packageName)) {
                packageInfo.installSystemApplicationInfo(aInfo,
                        getSystemContext().mPackageInfo.getClassLoader());
            }

            if (differentUser) {
                // Caching not supported across users
            } else if (includeCode) {
                mPackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            }
        }
        return packageInfo;
    }
}

5.1做的事情主要就是创建了LoadedApk然后返回

5.2 LoadedApk.makeApplication()

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }
    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";//默认在这里
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);//创建ContextImpl对象
        //创建Application对象, 该对象名来自于mApplicationInfo.className.
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    }

    // Rewrite the R 'constants' for all library apks.
    SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
            .getAssignedPackageIdentifiers();
    final int N = packageIdentifiers.size();
    for (int i = 0; i < N; i++) {
        final int id = packageIdentifiers.keyAt(i);
        if (id == 0x01 || id == 0x7f) {
            continue;
        }
        //写R常量
        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    }
    return app;
}

主要做了三件事

  • 创建ContextImpl对象
  • 创建Application对象, 该对象名来自于mApplicationInfo.className.
  • 重写了R常量

相关文章

  • 从一个APP进程启动说起(下)

    简介 回顾我们上一次说的一个app进程的启动过程,比如现在是当我们点击桌面上应用的图标,就会通过AMS,也就是sy...

  • Android应用程序进程启动过程-源码分析

    Android系统中,启动一个app首先要保证该app所在的进程已经被启动。本文就介绍下app进程,即应用程序进程...

  • 优化APP的启动速度

    1、启动方式 1、冷启动App没有启动过或App进程被killed, 系统中不存在该App进程。需要创建App进程...

  • 冷启动 原理 及 优化加速

    冷启动:应用进程被杀掉状态下的启动;热启动:应用进程仍然存活状态下,点击桌面APP的图标启动或从任务列表启动。 冷...

  • App 启动速度怎么做优化与监控?

    App的启动分类 一般情况下,App 的启动分为冷启动和热启动。 冷启动是指, App 点击启动前,它的进程不在系...

  • iOS app 启动

    App 启动动干了那些事情 一般情况下app 启动分为冷启动和热启动** 冷启动是指,App点击启动前,他的进程不...

  • 关于App启动速度优化

    冷启动、热启动 冷启动:App启动前,它的进程不在系统里,系统新创建一个进程分配给它启动;热启动:App冷启动后,...

  • Activity,Application的启动

    创建进程 ①App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,...

  • App启动

    App启动涉及三个进程和六个大类: 三个进程: Launcher进程:整个App启动流程的起点,负责接收用户点击屏...

  • iOS APP启动时间优化

    APP启动分为冷启动和热启动。 冷启动:App 点击启动前,它的进程不在系统里,需要系统新创建一个进程分配给它启动...

网友评论

      本文标题:从一个APP进程启动说起(下)

      本文链接:https://www.haomeiwen.com/subject/qkkndxtx.html