Android 进阶——Framework 核心四大组件之跨进程共享组件ContentProvider 创建和启动机制源码详细分析(二)

文章大纲

  • 引言
  • 一、ContentProvider启动概述
  • 二、ContentProvider启动的源码分析
    • 1、App程序的运行入口
    • 2、AMS#attachApplication
    • 3、ActivityThread$ActivityApplication#bindApplication
    • 4、ActivityThread#handleBindApplication 通过Handler消息机制处理
    • 5、LoaderApk#makeApplication 创建Application对象
    • 6、ActivityThread#installContentProviders创建ContentProvider
    • 7、ContentProvider#attachInfo 主动回调onCreate
    • 8、 Instrumentation#callApplicationOnCreate触发Application#onCreate方法
  • 小结

引言

前一篇Android 进阶——Framework 核心四大组件之跨进程共享组件ContentProvider 核心知识总结(一)文章,总结了ContentProvider机制的基本概念及开发中的应用,这一篇文章好好结合源码分析下其背后的机制和原理。如果做过插件化或者热修复,自己去加载四大组件,会发现ContentProvider的加载过程有些特殊…ContentProvider的onCreate方法先于Application的onCreate而执行。

  • Android 进阶——Framework 核心四大组件之跨进程共享组件ContentProvider 核心知识总结(一)
  • Android 进阶——Framework 核心四大组件之跨进程共享组件ContentProvider 创建和启动机制源码详细分析(二
  • Android 进阶——Framework 核心四大组件之跨进程共享组件ContentProvider 工作机制源码详细分析(三)

源码基于API 28,源码有删减,只保留本专题相关的核心代码,仅供参考。

一、ContentProvider启动概述

Android 进阶——Framework 核心四大组件之跨进程共享组件ContentProvider 创建和启动机制源码详细分析(二)_第1张图片

二、ContentProvider启动的源码分析

ActivityThread 与Thread 没有任何继承关系,源码涉及到核心类有android.app.ActivityThread.ApplicationThread、android.app.ActivityThread.AppBindData、android.content.ContentProvider、android.app.LoadedApk、android.content.pm.ApplicationInfo、com.android.server.am.ActivityManagerService、android.app.ActivityManager。

1、App程序的运行入口

Android四大组件在APP启动后随时可用,所以从App程序的运行入口开始,即ActivityThread#main方法(一般源码中的带有main方法的类都是作为启动类,由Framework 机制去调用的,比如使用adb 命令、cmd命令等等配置的参数都是传到对应启动类的方法里的)

    public static void main(String[] args) {
	    ...
		//初始化MainLooper 并以ThreadLocal形式存储
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
		// 通过Binder进行IPC通信
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
		// 开启Looper消息循环
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

在App的入口方法里创建自身ActivityThread对象之后,通过Binder与ActivityManagerService(AMS)进行通信

private void attach(boolean system, long startSeq) {
		
        if (!system) {
			...
			//Binder通信,获取到的是ActivityManagerService的代理
            final IActivityManager mgr = ActivityManager.getService();
            try {
            	//AMS#attachApplication(final ApplicationThread mAppThread = new ApplicationThread();) 通过IPC通信与AMS 通信,即由AMS去接力
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
			...
        } else {
            ...
        }
		...
        ViewRootImpl.addConfigCallback(configChangedCallback);
    }
  • ActivityManager.getService() ——获取系统服务AMS,本质上是从ServiceManager中获取,典型的AIDL。
 final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
 final IActivityManager am = IActivityManager.Stub.asInterface(b);
  • mgr.attachApplication 本质上就是调用ActivityManagerService#attachApplication 方法。
  • ApplicationThread 是ActivityThread的内部类,本质上是对应IApplicationThread接口的Binder对象,同时也是用于ActivityThread与AMS 之间的IPC通信

2、AMS#attachApplication

通过ActivityThread的attach方法把接力棒交到AMS,由AMS往下执行

    @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            ...
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        }
    }

ActivityManagerService#attachApplicationLocked

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
		...
        try {
            ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info;
            app.compat = compatibilityInfoForPackageLocked(appInfo);
            // If we were asked to attach an agent on startup, do so now, before we're binding
            // application code.
            if (preBindAgent != null) {
                thread.attachAgent(preBindAgent);
            }
            if (app.isolatedEntryPoint != null) {
                thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
            } else if (app.instr != null) {
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, isAutofillCompatEnabled);
            } 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);
            }
			...
        } catch (Exception e) {
        }
        return true;
    }

3、ActivityThread$ActivityApplication#bindApplication

又回到了ActivityThread$ActivityApplication#bindApplication方法中

private class ApplicationThread extends IApplicationThread.Stub {
       ...
        public final void scheduleSleeping(IBinder token, boolean sleeping) {
            sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
        }

        public final void scheduleReceiver(Intent intent, ActivityInfo info,
                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                boolean sync, int sendingUser, int processState) {
           
            sendMessage(H.RECEIVER, r);
        }

        public final void scheduleCreateBackupAgent(ApplicationInfo app,
                CompatibilityInfo compatInfo, int backupMode) {
    
            sendMessage(H.CREATE_BACKUP_AGENT, d);
        }

        public final void scheduleDestroyBackupAgent(ApplicationInfo app,
                CompatibilityInfo compatInfo) {
            sendMessage(H.DESTROY_BACKUP_AGENT, d);
        }

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {

            sendMessage(H.CREATE_SERVICE, s);
        }

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            sendMessage(H.BIND_SERVICE, s);
        }


        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 services, Bundle coreSettings,
                String buildSerial, boolean autofillCompatibilityEnabled) {
  
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
			...
            sendMessage(H.BIND_APPLICATION, data);
        }

        public void processInBackground() {
            mH.removeMessages(H.GC_WHEN_IDLE);
            mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
        }

        @Override
        public void scheduleLowMemory() {
            sendMessage(H.LOW_MEMORY, null);
        }
    }

在bindApplication中初始化AppBindData数据之后通过ActivityThread$H#sendMessage(H.BIND_APPLICATION, data)通过Handler机制把数据传递(msg.obj)出去,

4、ActivityThread#handleBindApplication 通过Handler消息机制处理

在H中进行处理调用ActivityThread#handleBindApplication方法完成四件事:

  • 创建初始化ContextImpl 和Instrumentation
  • 创建Application对象
  • 启动当前进程的ContentProvider并主动调用其onCreate方法
  • 通过Instrumentation触发Application的onCreate方法

经过以上四部曲之后,ContentProvider所在进程及ContentProvider皆已成功启动了。

    private void handleBindApplication(AppBindData data) {

        final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
		
        final InstrumentationInfo ii;
        if (data.instrumentationName != null) {
            try {
                ii = new ApplicationPackageManager(null, getPackageManager())
                        .getInstrumentationInfo(data.instrumentationName, 0);
            } catch (PackageManager.NameNotFoundException e) {
                throw new RuntimeException(
                        "Unable to find instrumentation info for: " + data.instrumentationName);
            }
            mInstrumentationPackageName = ii.packageName;
            mInstrumentationAppDir = ii.sourceDir;
        } else {
            ii = null;
        }
		
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        // Continue loading instrumentation.
        if (ii != null) {
            ApplicationInfo instrApp;
            try {
                instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
                        UserHandle.myUserId());
            } catch (RemoteException e) {
                instrApp = null;
            }
            if (instrApp == null) {
                instrApp = new ApplicationInfo();
            }
            ii.copyTo(instrApp);
            instrApp.initForUser(UserHandle.myUserId());
			//APK的内存表现形式
            final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
			// 创建初始化Context 上下文对象		
            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

            try {
                final ClassLoader cl = instrContext.getClassLoader();
				//反射创建Instrumentation
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
               
            }

            final ComponentName component = new ComponentName(ii.packageName, ii.name);
			//初始化Instrumentation
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

        } else {
            mInstrumentation = new Instrumentation();
            mInstrumentation.basicInit(this);
        }

        // Allow disk access during application and provider setup. This could
        // block processing ordered broadcasts, but later processing would
        // probably end up doing the same disk access.
        Application app;
        try {
            // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class. 
			// 创建初始化Application 对象
            app = data.info.makeApplication(data.restrictedBackupMode, null);

            // Propagate autofill compat state
            app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);

            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
					//创建启动当前进程的ContentProvider 并主动调用自己的onCreate方法
                    installContentProviders(app, data.providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }
			
            // Do this after providers, since instrumentation tests generally start their
            // test thread at this point, and we don't want that racing.
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
              
            }
            try {
				// 触发Application 的onCreate方法
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
             
            }
        } 
		    // Preload fonts resources
        FontsContract.setApplicationContextForResources(appContext);
    }
  • data——就是H发送Message时封装到msg.obj里的数据,类型为AppBindData
  • AppBindData——android.app.ActivityThread.AppBindData,里面封装了App的所有信息APK的内存对象LoaderApk、ApplicationInfo、ProviderInfo、进程名称等信息。
  • data.info——AppBindData的成员变量android.app.LoadedApk类型

5、LoaderApk#makeApplication 创建Application对象

通过data.info.makeApplication(data.restrictedBackupMode, null)方法把创建Application的接力棒交到了LoaderApk

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

        Application app = null;
        String appClass = mApplicationInfo.className;
        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //创建Application 对象
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
		//第一次创建时instrumentation 为null 不执行,
        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
            }
        }
        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
        return app;
    }

因为第一次创建时instrumentation 为null 所以instrumentation 没有调用callApplicationOnCreate方法即Application的onCreate方法没有被触发

6、ActivityThread#installContentProviders创建ContentProvider

接着调用链回到android.app.ActivityThread#installContentProviders方法,首先遍历当前进程的ProviderInfo列表并一一调用installProvider方法来启动,最后将已经运行的ContentProvider 注册到AMS中(AMS 存储到ProviderMap),这样其他进程使用时就可以通过Binder 与AMS获取对应的ContentProvider。

 private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
        for (ProviderInfo cpi : providers) {
            ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
        }
        try {
			//又回到AMS
            ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

android.app.ActivityThread#installProvider,通过类加载器

    private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
        if (holder == null || holder.provider == null) {
            Context c = null;
            ApplicationInfo ai = info.applicationInfo;
            if (context.getPackageName().equals(ai.packageName)) {
                c = context;
            } else if (mInitialApplication != null &&
                    mInitialApplication.getPackageName().equals(ai.packageName)) {
                c = mInitialApplication;
            } else {
                try {
                    c = context.createPackageContext(ai.packageName,
                            Context.CONTEXT_INCLUDE_CODE);
                } 
            }
            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
                if (packageInfo == null) {
                    // System startup case.
                    packageInfo = getSystemContext().mPackageInfo;
                }
                localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
                        //本质是通过android.app.AppComponentFactory#instantiateProvider 反射创建ContentProvider对象
                provider = localProvider.getIContentProvider();
                if (provider == null) {
                    return null;
                }
                // XXX Need to create the correct context for this provider.
                localProvider.attachInfo(c, info);
            } catch (java.lang.Exception e) {
            }
        } else {
            provider = holder.provider;
        }
        return retHolder;
    }

7、ContentProvider#attachInfo 主动回调onCreate

接力棒交到android.content.ContentProvider#attachInfo

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
    mNoPerms = testing;
    /*
     * Only allow it to be set once, so after the content service gives
     * this to us clients can't change it.
     */
    if (mContext == null) {
        mContext = context;
        if (context != null) {
            mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
                    Context.APP_OPS_SERVICE);
        }
        //ContentProvider自身执行自己的onCreate方法
        ContentProvider.this.onCreate();
    }
}

然后调用链再次回到handleBindApplication 方法中

8、 Instrumentation#callApplicationOnCreate触发Application#onCreate方法

mInstrumentation.callApplicationOnCreate(app) 被执行Application#onCreate方法被触发。

小结

简而言之,ContentProvider是在ActivityThread#handleBindApplication方法里被创建并由自身对象去主动调用自己的onCreate方法的;而Application虽然是由LoadedApk先于ContentProvider创建,但是它的onCreate方法是由Instrumentation 去触发的,而初次创建时Instrumentation为null,未完待续…

你可能感兴趣的:(Android,进阶,Android系统组件使用)