学记记录:应用程序启动过程(二)

源代码版本:Android9.0

最近在调研启动优化相关的知识,所以用几篇文章在这里做一下学习记录~~~

App进程Application的创建过程

每个App进程都会运行着一个App,每个App都会有一个对应的Application对象(该对象 跟LoadedApk一一对应)。这篇文章主要分析App进程中Application的创建过程。

具体过程分析如下:(解析添加到了注释当中)

  • 1. ActivityThread.main
frameworks/base/core/java/android/app/ActivityThread.java
    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        ......
        //这个main方法里面进行了一些初始化和Looper的启动操作
        //但是对于Application的创建,这两句关键代码就够了
        ActivityThread thread = new ActivityThread();
        //startSeq是作为main参数传进来的
        thread.attach(false, startSeq);

        ......
    }
    private void attach(boolean system/*这个地方传进来的是false*/, long startSeq) {
        //将当前的ActivityThread赋值为main当中new出来的
        sCurrentActivityThread = this;
        //当前线程不是系统线程
        mSystemThread = system;
        if (!system) {
            android.ddm.DdmHandleAppName.setAppName("",
                                                    UserHandle.myUserId());
            //初始化RuntimeInit对象的mApplicationObject
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //这里通过binder调用,进入system_server进程,执行后续操作。
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ......
        } else {
            ......
        }

        ......
    }
  • 2. ActivityManagerService.attachApplication
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
@GuardedBy("this")
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
            ......
            ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
            ......
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            }
        ......
        return true;
    }

这里面的thread是ActivityThread类中的ApplicationThread内部类对象private class ApplicationThread extends IApplicationThread.Stub,thread在ActivityThread属性声明时直接被new出来。
上面的在拿到一堆参数后通过binder调到了这里。

      public final void bindApplication(String processName, ApplicationInfo appInfo,
                List 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 services, Bundle coreSettings,
                String buildSerial, AutofillOptions autofillOptions,
                ContentCaptureOptions contentCaptureOptions) {
            if (services != null) {
                if (false) {
                    // Test code to make sure the app could see the passed-in services.
                    for (Object oname : services.keySet()) {
                        if (services.get(oname) == null) {
                            continue; // AM just passed in a null service.
                        }
                        String name = (String) oname;

                        // See b/79378449 about the following exemption.
                        switch (name) {
                            case "package":
                            case Context.WINDOW_SERVICE:
                                continue;
                        }

                        if (ServiceManager.getService(name) == null) {
                            Log.wtf(TAG, "Service " + name + " should be accessible by this app");
                        }
                    }
                }

                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);

            //进行参数封装,然后将AppBindData通过Handler传过去
            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;
            data.buildSerial = buildSerial;
            data.autofillOptions = autofillOptions;
            data.contentCaptureOptions = contentCaptureOptions;
            sendMessage(H.BIND_APPLICATION, data);
        }
-------------------------------------------------------------------------------------------------
      public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);

            //这里可以清楚地看到,当主线程收到H.BIND_APPLICATION
            //则调用handleBindApplication
            //接下继续了解handleBindApplication函数干了什么~~~
            ......

  • 3. ActivityThread.handleBindApplication
frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
    ......
    // send up app name; do this *before* waiting for debugger
    Process.setArgV0(data.processName);
    ......
    //这里获取loadedApk对象,【4】详细介绍
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ......
    //创建ContextImpl上下文
    //这个函数里面new了一个ContextImpl对象,同时填充了LoadedApk的Resources对象
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    ......
    Application app;
    ......
    try {
        //如果要启动应用进行完全备份或还原,请在以下位置启动应用
         //具有基本应用程序类的受限环境。
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象
        //这里最终是通过反射创建的Application对象,并且进行了初始化
        //将新创建的ContextImpl对象保存到Application的父类成员变量mBase;
        //将新创建的LoadedApk对象保存到Application的父员变量mLoadedApk;
        app = data.info.makeApplication(data.restrictedBackupMode, null);

        //传播自动填充兼容性状态
        app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);

        mInitialApplication = app;

        //不要以受限模式启动提供程序; 他们可能取决于在提供者之后执行此操作,因为通常会进行测试
        //在这一点上测试线程,我们不希望出现这种情况。
        try {
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
            ........
        }
        try {
            //这个函数里面仅仅是调用了app.onCreate();
            //回调了Application的onCreate方法
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
                ......
        }
        ......
}

在handleBindApplication()的过程中,同时设置了以下两个值:

  • LoadedApk.mApplication

  • ActivityThread.mInitialApplication

  • 4. ActivityThread.getPackageInfoNoCheck
frameworks/base/core/java/android/app/ActivityThread.java
    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 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) {
                if (!isLoadedApkResourceDirsUpToDate(packageInfo, aInfo)) {
                    packageInfo.updateApplicationInfo(aInfo, null);
                }

                return packageInfo;
            }
            ......
            //创建LoadApk对象,同时将ActivityThread对象传进去初始化LoadedApk里面的ActivityThread属性
            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) {
                //将新创建的LoadApk对象加入到mPaackges里面
                //创建LoadedApk对象,并将将新创建的LoadedApk加入到mPackages. 
                //也就是说每个app都会创建唯一的LoadedApk对象. 
                //此处aInfo来源于ProcessRecord.info变量, 也就是进程中的第一个app
                mPackages.put(aInfo.packageName,
                        new WeakReference(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                        new WeakReference(packageInfo));
            }

            return packageInfo;
        }
    }

通过以上步骤,应用程序进程的Application对象就创建出来了,同时它的onCreate方法也被回调,程序正式开始运行~~~

你可能感兴趣的:(学记记录:应用程序启动过程(二))