Android四大组件系列11 Application创建流程
发布日期:2021-05-06 20:19:25 浏览次数:61 分类:原创文章

本文共 17031 字,大约阅读时间需要 56 分钟。

一 概述

system_server 进程和 app 进程都运行着一个或多个 app,每个 app 都会有一个对应的 Application 对象(该对象跟 LoadedApk 一一对应)。下面分别分析这两种进程创建 Application 的过程:

  • system_server 进程
  • app 进程

二 system_server进程

2.1 SystemServer.run

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer {       private static final String TAG = "SystemServer";    ......    public static void main(String[] args) {           new SystemServer().run();    }    ......    private void run() {           try {               ......                        createSystemContext();            ......        } finally {               ......        }                ......    }}private void createSystemContext() {         ActivityThread activityThread = ActivityThread.systemMain();      mSystemContext = activityThread.getSystemContext();      mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);      final Context systemUiContext =            activityThread.getSystemUiContext();      systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);}

2.2 ActivityThread.systemMain

frameworks/base/core/java/android/app/ActivityThread.java

public static ActivityThread systemMain() {           ......        ActivityThread thread = new ActivityThread();        thread.attach(true, 0);        return thread;}public final class ActivityThread extends ClientTransactionHandler {       //创建ApplicationThread对象    final ApplicationThread mAppThread = new ApplicationThread();    final Looper mLooper = Looper.myLooper();    final H mH = new H();    //当前进程中首次初始化的app对象    Application mInitialApplication;    final ArrayList<Application> mAllApplications            = new ArrayList<Application>();    //标记当前进程是否为system进程    boolean mSystemThread = false;    //记录system进程的ContextImpl对象    private ContextImpl mSystemContext;    private ContextImpl mSystemUiContext;    final ArrayMap<String, WeakReference<LoadedApk>> mPackages =             new ArrayMap<>();    static volatile Handler sMainThreadHandler;//set once in main()    private static volatile ActivityThread sCurrentActivityThread;    ActivityThread() {           mResourcesManager = ResourcesManager.getInstance();    }}

其中 mInitialApplication 的赋值过程分两种场景:

  • system_server 进程是由 ActivityThread.attach() 过程赋值
  • 普通 app 进程是由是由 ActivityThread.handleBindApplication() 过程赋值,这是进程刚创建后 attach 到 system_server 后, 便会 binder call 到 app 进程来执行该方法

ActivityThread.currentApplication 返回的便是 mInitialApplication 对象。创建完 ActivityThread 对象,接下来执行 attach() 操作。

2.3 ActivityThread.attach

private void attach(boolean system, long startSeq) {       sCurrentActivityThread = this;    mSystemThread = system; //设置mSystemThread为true    if (!system) {           ......    } else {    //system进程才执行该流程        try {              //创建Instrumentation           mInstrumentation = new Instrumentation();           mInstrumentation.basicInit(this);           ContextImpl context = ContextImpl.createAppContext(                        this, getSystemContext().mPackageInfo);           mInitialApplication =           context.mPackageInfo.makeApplication(true, null);           mInitialApplication.onCreate();        } catch (Exception e) {                   ......        }        ......    }}

2.3.1 Application.onCreate

public void onCreate() {   //方法为空, 一般由其子类实现该方法}

2.4 ContextImpl.createAppContext

static ContextImpl createAppContext(ActivityThread mainThread,        LoadedApk packageInfo) {           return createAppContext(mainThread, packageInfo, null);}static ContextImpl createAppContext(ActivityThread mainThread,       LoadedApk packageInfo, String opPackageName) {           if (packageInfo == null)         throw new IllegalArgumentException("packageInfo");        ContextImpl context = new ContextImpl(null, mainThread, packageInfo,        null, null, null, 0, null, opPackageName);        context.setResources(packageInfo.getResources());        return context;}

创建 ContextImpl 对象有多种方法,常见的有:

createSystemContext(ActivityThread mainThread)createAppContext(ActivityThread mainThread, LoadedApk packageInfo)createApplicationContext(ApplicationInfo application, int flags)createPackageContext(String packageName, int flags)createSystemUiContext(ContextImpl systemContext)createActivityContext(ActivityThread mainThread, ......)

此处,packageInfo 是 getSystemContext().mPackageInfo,getSystemContext() 获取的 ContextImpl 对象, 其成员变量 mPackageInfo 便是 LoadedApk 对象。所以先来看看 getSystemContext() 过程。

2.4.1 ActivityThread.getSystemContext

public ContextImpl getSystemContext() {       synchronized (this) {           if (mSystemContext == null) {               mSystemContext = ContextImpl.createSystemContext(this);        }        return mSystemContext;    }}

单例模式创建 mSystemContext 对象

2.4.2 ContextImpl.createSystemContext

static ContextImpl createSystemContext(ActivityThread mainThread) {           LoadedApk packageInfo = new LoadedApk(mainThread);        ContextImpl context = new ContextImpl(null, mainThread,        packageInfo, null, null, null, 0, null, null);        ......        return context;}

2.4.3 LoadedApk初始化

public final class LoadedApk {       private final ActivityThread mActivityThread;    private ApplicationInfo mApplicationInfo;    private Application mApplication;    final String mPackageName;    private final ClassLoader mBaseClassLoader;    private ClassLoader mClassLoader;    LoadedApk(ActivityThread activityThread) {           mActivityThread = activityThread;//ActivityThread对象        mApplicationInfo = new ApplicationInfo();//创建ApplicationInfo对象        mApplicationInfo.packageName = "android";        mPackageName = "android";//默认包名为"android"        ......        mBaseClassLoader = null;        mClassLoader = mAppComponentFactory.instantiateClassLoader(        mDefaultClassLoader, new ApplicationInfo(mApplicationInfo));        ......    }}

只有一个参数的 LoadedApk 构造方法只有 createSystemContext() 过程才会创建, 其中 LoadedApk 初始化过程会创建 ApplicationInfo 对象,且包名为 “android”。 创建完 LoadedApk 对象,接下来创建 ContextImpl 对象。

2.4.4 ContextImpl初始化

class ContextImpl extends Context {       final ActivityThread mMainThread;    final LoadedApk mPackageInfo;    private final IBinder mActivityToken;    private final String mBasePackageName;    private Context mOuterContext;    //缓存Binder服务    final Object[] mServiceCache =     SystemServiceRegistry.createServiceCache();    private ContextImpl(ContextImpl container, ActivityThread mainThread,    LoadedApk packageInfo, IBinder activityToken, ......) {           mOuterContext = this; //ContextImpl对象        mMainThread = mainThread; // ActivityThread赋值        mPackageInfo = packageInfo; // LoadedApk赋值        mBasePackageName = packageInfo.mPackageName; //mBasePackageName等于“android”        ......    }}

首次执行 getSystemContext,会创建 LoadedApk 和 contextImpl 对象,接下来利用刚创建的 LoadedApk 对象来创建新的 ContextImpl 对象。

2.5 LoadedApk.makeApplication

public Application makeApplication(boolean forceDefaultAppClass,            Instrumentation instrumentation) {           //保证一个LoadedApk对象只创建一个对应的Application对象        if (mApplication != null) {               return mApplication;        }        ......        Application app = null;        String appClass = mApplicationInfo.className;        if (forceDefaultAppClass || (appClass == null)) {           //system_server进程, 则进入该分支            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对象            ContextImpl appContext =             ContextImpl.createAppContext(mActivityThread, this);      //创建Application对象, 并将appContext attach到新创建的Application            app = mActivityThread.mInstrumentation.newApplication(                    cl, appClass, appContext);            appContext.setOuterContext(app);        } catch (Exception e) {               ......        }        mActivityThread.mAllApplications.add(app);        mApplication = app;//将刚创建的app赋值给mApplication        if (instrumentation != null) {               try {                   //调用application的OnCreate方法                instrumentation.callApplicationOnCreate(app);            } catch (Exception e) {                   ......            }        }        ......        return app;}

2.6 LoadedApk.initializeJavaContextClassLoader

private void initializeJavaContextClassLoader() {           IPackageManager pm = ActivityThread.getPackageManager();        android.content.pm.PackageInfo pi;        try {               pi = pm.getPackageInfo(mPackageName,             PackageManager.MATCH_DEBUG_TRIAGED_MISSING,                    UserHandle.myUserId());        } catch (RemoteException e) {               throw e.rethrowFromSystemServer();        }        if (pi == null) {               ......        }        boolean sharedUserIdSet = (pi.sharedUserId != null);        boolean processNameNotDefault =            (pi.applicationInfo != null &&             !mPackageName.equals(pi.applicationInfo.processName));        boolean sharable =               (sharedUserIdSet || processNameNotDefault);        ClassLoader contextClassLoader =            (sharable)            ? new WarningContextClassLoader()            : mClassLoader;    Thread.currentThread().setContextClassLoader(contextClassLoader);}

2.7 Instrumentation.newApplication

public Application newApplication(ClassLoader cl, String className,      Context context) throws InstantiationException, ...... {           Application app = getFactory(context.getPackageName())                .instantiateApplication(cl, className);        app.attach(context);        return app;}private AppComponentFactory getFactory(String pkg) {           if (pkg == null) {       Log.e(TAG, "No pkg specified, disabling AppComponentFactory");            return AppComponentFactory.DEFAULT;        }        if (mThread == null) {              ......            return AppComponentFactory.DEFAULT;        }        LoadedApk apk = mThread.peekPackageInfo(pkg, true);        // This is in the case of starting up "android".    if (apk == null) apk = mThread.getSystemContext().mPackageInfo;        return apk.getAppFactory();}AppComponentFactory.javapublic @NonNull Application instantiateApplication(ClassLoader cl,            @NonNull String className)            throws InstantiationException, ...... {           return (Application) cl.loadClass(className).newInstance();}

2.8 Application.attach

final void attach(Context context) {        attachBaseContext(context);     mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;}    Application父类ContextWraper.javaprotected void attachBaseContext(Context base) {       if (mBase != null) {           throw new IllegalStateException("Base context already set");    }    mBase = base;}
  • 将新创建的 ContextImpl 对象保存到 Application 父类成员变量 mBase
  • 将新创建的 LoadedApk 对象保存到 Application 的父员变量 mLoadedApk

三 App进程

3.1 ActivityThread.main

public static void main(String[] args) {       Looper.prepareMainLooper();    ......    ActivityThread thread = new ActivityThread();    thread.attach(false, startSeq);    ......    Looper.loop();}

这是运行在 app 进程,当进程由 zygote fork 后执行 ActivityThread 的 main 方法,注意 attach 函数的参数,这里为 false。

3.2 ActivityThread.attach

private void attach(boolean system, long startSeq) {       sCurrentActivityThread = this;    mSystemThread = system; //设置mSystemThread为true    if (!system) {   //app进程        ......        final IActivityManager mgr = ActivityManager.getService();        try {               mgr.attachApplication(mAppThread, startSeq);        } catch (RemoteException ex) {               throw ex.rethrowFromSystemServer();        }        ......    } else {    //system进程才执行该流程        ......    }}

经过 Binder 调用,进入 system_server 进程,执行 attachApplication。

3.3 AMS.attachApplication

public final void attachApplication(IApplicationThread thread,    long startSeq) {         if (thread == null) {           throw new SecurityException("Invalid application interface");      }      synchronized (this) {             int callingPid = Binder.getCallingPid();          final int callingUid = Binder.getCallingUid();          final long origId = Binder.clearCallingIdentity();    attachApplicationLocked(thread, callingPid, callingUid, startSeq);          Binder.restoreCallingIdentity(origId);      }}private boolean attachApplicationLocked(IApplicationThread thread,            int pid, int callingUid, long startSeq) {           ProcessRecord app;        ......        try {               ......         if (app.isolatedEntryPoint != null) {                   ......         } else if (instr2 != null) {               // 绑定App进程          thread.bindApplication(processName, appInfo, providers,              instr2.mClass,              profilerInfo, instr2.mArguments,              instr2.mWatcher,              instr2.mUiAutomationConnection, testMode,              mBinderTransactionTrackingEnabled, enableTrackAllocation,              isRestrictedBackupMode || !normalMode, app.isPersistent(),    new Configuration(app.getWindowProcessController().getConfiguration()),              app.compat, getCommonServicesLocked(app.isolated),              mCoreSettingsObserver.getCoreSettingsLocked(),              buildSerial, autofillOptions, contentCaptureOptions);         } else {                   ......         }            ......        } catch (Exception e) {              ......           return false;        }        ......        return true;}

3.3 ActivityThread.bindApplication

public final void bindApplication(String processName, ......) {          ......// 封装App进程绑定数据AppBindData    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);}

3.4 ActivityThread.handleBindApplication

private void handleBindApplication(AppBindData data) {       // 从AppBindData中取出InstrumentationInfo信息    final InstrumentationInfo ii;    if (data.instrumentationName != null) {           ii = new ApplicationPackageManager(null, 		getPackageManager()).getInstrumentationInfo(		data.instrumentationName, 0);        mInstrumentationPackageName = ii.packageName;        mInstrumentationAppDir = ii.sourceDir;        ......    }    //获取LoadedApk对象    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);    // 创建Context    final ContextImpl appContext =    ContextImpl.createAppContext(this, data.info); 	// InstrumentationInfo对象非空	// 从InstrumentationInfo中取出各参数, 基于此创建和初始化Instrumentation    if (ii != null) {            ApplicationInfo instrApp = getPackageManager()	   .getApplicationInfo(ii.packageName, 0, UserHandle.myUserId());        if (instrApp == null) {               instrApp = new ApplicationInfo();        }        // 将InstrumentationInfo里的参数拷贝到ApplicationInfo对象        ii.copyTo(instrApp);        instrApp.initForUser(UserHandle.myUserId());        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, 		        appContext.getClassLoader(), false, true, false);         final ContextImpl instrContext =        ContextImpl.createAppContext(this,		        pi, appContext.getOpPackageName());        final ClassLoader cl = instrContext.getClassLoader();        mInstrumentation = (Instrumentation) cl	    .loadClass(data.instrumentationName.getClassName()).newInstance();        final ComponentName component =         new ComponentName(ii.packageName, ii.name);        mInstrumentation.init(this, instrContext, ......);    } else {    // 初始化Instrumentation        mInstrumentation = new Instrumentation();        mInstrumentation.basicInit(this);    }     //创建Application对象    Application app =     data.info.makeApplication(data.restrictedBackupMode, null);    mInitialApplication = app;         mInstrumentation.onCreate(data.instrumentationArgs);    //调用Application.onCreate()方法.    mInstrumentation.callApplicationOnCreate(app);    ......}

在 handleBindApplication() 的过程中,会创建 Application 并调用其 onCreate 方法

四 总结

system_server 进程

其 application 创建过程都创建对象有 ActivityThread,Instrumentation,ContextImpl,LoadedApk,Application。 流程图如下:
在这里插入图片描述
app 进程

其 application 创建过程都创建对象有 ActivityThread,ContextImpl,LoadedApk,Application。 流程图如下:
在这里插入图片描述
App 进程的 Application 创建过程,跟 system 进程的核心逻辑都差不多。只是 app 进程多了两次 binder 调用。

上一篇:JAVA设计模式之代理模式
下一篇:Android四大组件系列10 深入理解Context

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月30日 05时30分47秒