Android问道--四大组件的工作过程-2-广播与内容提供者

 

广播的注册发送和接收过程

广播作为四大组件之一,使用频率没有Activity这么高,但是广播的工作过程也是有必要了解的,我们将从三个方面讲解广播,分别是注册,发送和接收

广播的注册过程

广播的注册就是广播接收者注册自己感兴趣的广播,广播的注册分为两种,分别是动态注册静态注册

  • 静态注册在应用安装的时候由PackageManagerService来完成注册过程
  • 动态注册的过程是复杂的,时序图如下所示
sequenceDiagram
	调用 ->> ContextWrapper : registerReceiver
	activate ContextWrapper
	ContextWrapper ->> ContextImpl : registerReceiver
	deactivate ContextWrapper
	activate ContextImpl
	ContextImpl ->> ContextImpl : registerReceiverInternal
	ContextImpl ->> IActivityManager : registerReceiver
	deactivate ContextImpl
	activate IActivityManager
	IActivityManager ->> AMS : registerReceiver
	deactivate IActivityManager
	activate AMS
	deactivate AMS

想要动态注册广播,需要调用registerReceiver方法,它在ContextWrapper中实现

@Override
public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter,
        String broadcastPermission, Handler scheduler) {
        return mBase.registerReceiver(receiver, filter, broadcastPermission,
                scheduler);
}

mBase具体指向ContextImpl,ContextImpl.registerReceiver有很多个重载方法,最后会调用ContextImpl.registerReceiverInternal方法

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        IIntentReceiver rd = null;
        if (receiver != null) {
            //判断LoadedApk类型的mPackageInfo和上下文是否非空
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                //获得rd,rd是IIntentReceiver类型,是一个Binder接口,用于广播的跨进程通信
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                //没有获得rd的话就创建rd
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
            //调用AMS代理服务的registerReceiver方法,并将rd作为参数传进去
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
}

rdLoadedApk.ReceiverDispatcher.InnerReceiver中实现final static class InnerReceiver extends IIntentReceiver.Stub

在调用AMS代理服务的registerReceiver方法的时候我们传入了IIntentReceiver类型的rd参数,这里我们不直接将广播接收者传递进去是因为注册广播是跨进程的过程,所有需要有有跨进程能力的IIntentReceiverc参与进来

接下来运行到了ActivityManagerService.registerReceiver方法

registerReceiver第一部分

  • 通过getRecordForAppLocked方法获得ProcessRecord类型的callerApp变量,该变量用于描述请求AMS注册广播接收者的Activity所在的应用程序进程

    callerApp = getRecordForAppLocked(caller);
    
  • 根据传入的IntentFilter类型变量filter来得到actions列表

    Iterator<String> actions = filter.actionsIterator();
    
  • 根据actions列表和userIds来得到所有的粘性广播的intent,并且传入到stickyIntents

    while (actions.hasNext()) {
            String action = actions.next();
            for (int id : userIds) {
                ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                if (stickies != null) {
                    ArrayList<Intent> intents = stickies.get(action);
                    if (intents != null) {
                        if (stickyIntents == null) {
                            stickyIntents = new ArrayList<Intent>();
                        }
                        //将获得的粘性广播的Intent传入到stickyIntents中
                        stickyIntents.addAll(intents);
                    }
                }
            }
        }
    
  • 遍历寻找匹配的粘性广播,并且存储在allSticky

     ArrayList<Intent> allSticky = null;
    if (stickyIntents != null) {
                final ContentResolver resolver = mContext.getContentResolver();
                // 遍历广播
                for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                    Intent intent = stickyIntents.get(i);
                    // Don't provided intents that aren't available to instant apps.
                    if (instantApp &&
                            (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                        continue;
                    }
                    //寻找匹配参数的粘性广播
                    if (filter.match(resolver, intent, true, TAG) >= 0) {
                        if (allSticky == null) {
                            allSticky = new ArrayList<Intent>();
                        }
                        allSticky.add(intent);
                    }
                }
            }
    

registerReceiver第二部分

  • 获得ReceiverList列表,ReceiverList继承于ArrayList,用来存储广播接收者

    ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
    
  • 如果获得ReceiverList为null,创建ReceiverList

    if (rl == null){
    	rl = new ReceiverList(this, callerApp, callingPid, callingUid,userId, receiver);
    }
    
  • 创建BroadcastFilter并将rl传递进去,BroadcastFilter用来描述注册的广播接收者

    BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                        permission, callingUid, userId, instantApp, visibleToInstantApps);
    
  • 将BroadcastFilter添加到ReceiverList(将接收者添加到接收者列表)

    rl.add(bf);
    
  • BroadcastFilter添加到IntentResolver类型的mReceiverResolver中,当AMS接收到广播的时候可以从mReceiverResolver中找到对应的广播接收者

    mReceiverResolver.addFilter(bf);
    

BroadcastFilter添加到IntentResolver后,完成了广播的注册过程

广播的发送和接收过程

广播的发送和接收分为两个部分,分别是ContextImpl到AMS的调用过程和AMS到BroadcastReceiver的调用过程

ContextImpl到AMS的过程

广播的发送有多种类型,无序广播(普通广播)有序广播粘性广播

我们以无序广播为例子来解析广播的发送过程,无序广播发送要调用sendBroadcast方法,该方法在ContextWrapper方法中实现

sequenceDiagram
	调用 ->> ContextWrapper : sendBroadcast
	activate ContextWrapper 
	ContextWrapper ->> ContextImpl : sendBroadcast
	deactivate ContextWrapper
	activate ContextImpl
	ContextImpl ->> IActivityManager : broadcastIntent
	deactivate ContextImpl
	activate IActivityManager
	IActivityManager ->> AMS : broadcastIntent
	deactivate IActivityManager
	activate AMS
	AMS ->> AMS : broadcastInetntLocked
	deactivate AMS

ContextWrapper.sendBroadcast方法中调用了

mBase.sendBroadcast(intent)

mBase指向的是ContextImpl,接下来来到ContextImpl.sendBroadcast方法,该方法最后也是通过AMS的代理调用了ActivityManagerService.broadcastIntent方法

ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());

ActivityManagerService.broadcastIntent方法中执行了以下逻辑

public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            //验证广播是否合法
            intent = verifyBroadcastLocked(intent);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            //执行broadcastIntentLocked方法
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

验证广播合法性执行了以下逻辑

  • 判断Intent是否不为null,并且文件描述符不为null,否则抛出IllegalArgumentException

    if (intent != null && intent.hasFileDescriptors() == true)
    
  • 获得intent的flag

    int flags = intent.getFlags();
    
  • 如果系统在启动过程中

    if (!mProcessesReady)
    
    • 执行以下判断

      //判断flag是否设置为  启动时只接受动态注册的广播接收者
      if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
         		//不做处理
      //判断flag没有设置为  只接受动态注册的广播接收者
      } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
             Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent+ " before boot completion");
          	//抛出错误
             throw new IllegalStateException("Cannot broadcast before boot completed");
      }
      

接下来代码执行到broadcastIntentLocked方法中,该方法执行了以下逻辑

  • 动态注册的广播接收者和静态注册的广播接收者按照优先级顺序存储在不同的列表中,之后将两个列表合并到receivers列表中,这样receivers列表中就包含了所有的广播接收者

  • 创建BroadcastRecord对象并将receivers传递进去

    BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                        callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                        requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                        resultCode, resultData, resultExtras, ordered, sticky, false, userId);
    
  • 调用BroadcastQueue的scheduleBroadcastsLocked方法

    queue.enqueueParallelBroadcastLocked(r);
    

AMS到BroadcastReceiver的过程

sequenceDiagram
	调用 ->> BroadcastQueue : scheduleBroadcastsLocked
	activate BroadcastQueue
	BroadcastQueue ->> BroadcastHandler : handleMessage
	deactivate BroadcastQueue
	activate BroadcastHandler
	BroadcastHandler ->> BroadcastQueue : processNextBroadcast
	deactivate BroadcastHandler
	activate BroadcastQueue
	BroadcastQueue ->> BroadcastQueue : deliverToRegisteredReceiverLocked
	BroadcastQueue ->> BroadcastQueue : performReceiveLocked
	BroadcastQueue ->> ApplicationThread : scheduleRegisteredReceiver
	deactivate BroadcastQueue
	activate ApplicationThread
	ApplicationThread ->> InnerReceiver : performReceive
	deactivate ApplicationThread
	activate InnerReceiver
	InnerReceiver ->> ReceiverDispatcher : performReceive
	deactivate InnerReceiver
	activate ReceiverDispatcher
	ReceiverDispatcher ->> Args : run
	deactivate ReceiverDispatcher
	activate Args
	Args ->> BroadcastReceiver : onReceive
	deactivate Args
	activate BroadcastReceiver
	deactivate BroadcastReceiver

BroadcastQueue.scheduleBroadcastsLocked方法中向BroadcastHandler类型的mHandler发送一个消息,消息类型为BROADCAST_INTENT_MSG

mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));

这个消息在BroadcastHandler.handleMessage方法中进行处理

@Override
public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
                    //调用此处
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }

handleMessage方法中调用了processNextBroadcast方法,这个方法对无序广播和有序广播分别进行处理,目的是将广播发送给广播接收者,接下来代码来到processNextBroadcast方法中

  • 判断fromMsg参数,我们知道调用processNextBroadcast方法的时候传入的fromMsg参数为true
    • 将mBroadcastsScheduled变量设置为false,表示已经处理了BROADCAST_INTENT_MSG消息
    • 遍历存储无序广播的列表while (mParallelBroadcasts.size() > 0)
    • 获取无序广播, r = mParallelBroadcasts.remove(0);,r变量是BroadcastRecord类型
    • 将r变量描述的广播发送给对应的广播接收者

      deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
      

deliverToRegisteredReceiverLocked方法会先检查广播发送者和广播接收者的权限,如果通过了权限就会调用

 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);

接下来代码运行到performReceiveLocked方法中

  • 判断广播接收者所在的应用程序进程存在并且正在运行

    if (app != null) 
    if (app.thread != null)
    
  • 使用广播接收者所在应用程序进程来接收广播

    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                                data, extras, ordered, sticky, sendingUser, app.repProcState);
    

app.thread指的是ApplicationThread,接下来我们到了ApplicationThread.scheduleRegisteredReceiver方法中,该方法调用了

receiver.performReceive(intent, resultCode, dataStr, extras, ordered,sticky, sendingUser);

receiverIIntentReceiver类型,是用于广播的跨进程通信,具体实现为LoadedApk.ReceiverDispatcher.InnerReceiver

IIntentReceiver和IActivityManager一样是使用了AIDL来完成进程之间的通信。

InnerReceiver继承于IIntentReceiver.Stub,我Binder通信时的服务器端,IIntentReceiver是客户端

在其performReceive方法中主要是执行了

 rd.performReceive(intent, resultCode, data, extras,ordered, sticky, sendingUser);

rd是ReceiverDispatcher类型,代码在ReceiverDispatcher.performReceive中执行了

  • 将广播的intent对象等信息封装为Args对象

    final Args args = new Args(intent, resultCode, data, extras, ordered,sticky, sendingUser);
    
  • 调用mActivityThread的post方法并且传入Args对象

    if (intent == null || !mActivityThread.post(args.getRunnable()))
    

    mActivityThread是Handler对象,指向了H类

    这一段代码的意思就是将Args对象的getRunnable方法通过H类发送到线程的消息队列中

接下来来到Args.getRunnable方法中,该方法中主要执行了BroadcastReceiver对象的onReceive方法

receiver.onReceive(mContext, intent);

这样注册的广播接收者就接收到了广播并且得到了intent

ContentProvider的启动过程

内容提供者没有其他的组件使用频繁,主要是用于进程内和进程间的数据共享,ContentProvider分为两个部分

  • query方法到AMS的调用过程
  • AMS启动ContentProvider的过程

query到AMS的调用过程

流程图

sequenceDiagram
	调用 ->> ContentResolver : query
	activate ContentResolver
	ContentResolver ->> ContentResolver : acquireUnstableProvider
    ContentResolver ->> ApplicationContentResolver : acquireUnstableProvider 
    deactivate ContentResolver
    activate ApplicationContentResolver
    ApplicationContentResolver ->> ActivityThread : acquireProvider
    deactivate ApplicationContentResolver
    activate ActivityThread
    ActivityThread ->> IActivityManager : getContentProvider
    deactivate ActivityThread
    activate IActivityManager
    IActivityManager ->> AMS : getContentProvider
    deactivate IActivityManager
    activate AMS
    AMS ->> AMS : getContentProviderImpl
    AMS ->> ActivityThread : main
    deactivate AMS
    activate ActivityThread
    ActivityThread ->> ActivityThread : attach
    ActivityThread ->> IActivityManager : attachApplication
    deactivate ActivityThread
    activate IActivityManager
    IActivityManager ->> AMS : attachApplication
    deactivate IActivityManager
    activate AMS
    deactivate AMS

为了方便理解ContentProvider的启动过程,先解释一下如何调用ContentProvider

		//准备ContentResolver
        ContentResolver cr = getContentResolver();
        //uri
        Uri uri = Uri.parse("content://hello_world");
        //向数据库中增加的数据的值
        ContentValues values = new ContentValues();
        values.put("_name", "Susan");
        values.put("_age", 44);
        values.put("_phone", "14444444444");
        values.put("_email", "test@text.org");
        //执行增加
        cr.insert(uri, values);

上面的代码向着Uri指向的内容提供者插入了一条数据,我们插入一条数据,需要使用ContentResolver,需要通过调用getContentResolver方法来获得

@Override
public ContentResolver getContentResolver() {
        return mBase.getContentResolver();
}

该方法中调用了mBase.getContentResolver() mBase指向的就是ContextImpl,代码执行到ContextImpl.getContentResolver

@Override
public ContentResolver getContentResolver() {
        return mContentResolver;
}

这个方法返回了ApplicationContentResolver类型的mContentResolver对象,ApplicationContentResolver是ContextImpl的静态内部类,继承于ContentResolver,在ContextImpl的构造方法中被创建,所以可以说当我们调用ContentResolverinsertqueryupdatee等方法的时候,内容提供者就会启动

我们以ContentResolver的query方法举例,query方法在ApplicationContentResolver的父类ContentResolver中实现,query方法中主要执行了以下代码

  • 通过acquireUnstableProvider方法获得IContentProvider类型的unstableProvider对象

    IContentProvider unstableProvider = acquireUnstableProvider(uri);
    
  • 调用unstableProvider的query方法

    qCursor = unstableProvider.query(mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
    

先来到acquireUnstableProvider方法,查看其做了什么

  • 判断uri的scheme是否等于content(SCHEME_CONTENT变量的值为content),如果不等于,直接return null

     if (!SCHEME_CONTENT.equals(uri.getScheme())) {
                return null;
            }
    
  • 调用acquireUnstableProvider方法,该方法是一个抽象方法,在ContentResolver的子类ApplicationContentResolver中实现,ApplicationContentResolver是ContentImpl的静态内部类

    acquireUnstableProvider(mContext, uri.getAuthority());
    

代码运行到ContextImpl.ApplicationContentResolver.acquireUnstableProvider方法中

@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
            return mMainThread.acquireProvider(c,
                    ContentProvider.getAuthorityWithoutUserId(auth),
                    resolveUserIdFromAuthority(auth), false);
}

该方法返回了ActivityThread类型的mMainThread的对象的acquireProvider方法,也就是一个IContentProvider对象,接下来来到ActivityThread.acquireProvider方法中

  • 使用acquireExistingProvider方法检查ActivityThread的全局变量mProviderMap中是否包含目标内容提供者

    final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
    
  • 判断provider变量是否为null,不为null就直接return provider 如果为null就往下执行

  • 调用IActivityManager的getContentProvider方法,也就是ActivityManagerService的getContentProvider方法

    holder = ActivityManager.getService().getContentProvider(getApplicationThread(), auth, userId, stable);
    
  • 调用installProvider方法来安装内容提供者,并且将getContentProvider获得的内容提供者相关数据存储在mProviderMap中,起到缓存的作用

    holder = installProvider(c, holder, holder.info,true /*noisy*/, holder.noReleaseNeeded, stable);
    

接下来我们来到ActivityManagerService.getContentProvider方法中,该方法返回了getContentProviderImpl方法

return getContentProviderImpl(caller, name, null, stable, userId);

ActivityManagerService.getContentProviderImpl方法中,关键部分为

  • 通过getProcessRecordLocked方法来获取目标内容提供者的应用程序进程,信息通过ProcessRecord类型的proc对象来表示

    ProcessRecord proc = getProcessRecordLocked(cpi.processName, cpr.appInfo.uid, false);
    
  • 如果该应用程序进程已启动就执行

    proc.thread.scheduleInstallProvider(cpi);
    

    如果该应用程序进程没有启动则启动进程

    proc = startProcessLocked(cpi.processName,cpr.appInfo, false, 0, "content provider",
                              new ComponentName(cpi.applicationInfo.packageName,cpi.name), 
                              false, false, false);
    

我们假设应用程序进程还未启动,startProcessLocked执行的结果就是应用程序进程最后会调用ActivityThread的main方法

  • 通过prepareMainLooper方法在ThreadLocal中获得Looper

    Looper.prepareMainLooper();
    
  • 开启消息循环

    Looper.loop();
    
  • 创建ActivityThread,调用其attach方法

    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    

ActivityThread.attach方法主要内容如下

//获得IActivityManager
final IActivityManager mgr = ActivityManager.getService();
try {
    //调用IActivityManager的attachApplication方法,并且将ApplicationThread类型的mAppThread传进去
    //因为IActivityManager是ActivityManagerService的代理,最后调用的是AMS的attachApplication方法
	mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
	throw ex.rethrowFromSystemServer();
}

AMS启动ContentProvide的过程

流程图

sequenceDiagram
	调用 ->>AMS : attachApplication
	activate AMS
	AMS ->> AMS : attachApplicationLocked
	AMS ->> IApplicationThread : bindApplication
	deactivate AMS
	activate IApplicationThread
	IApplicationThread ->> ApplicationThread : bindApplication
	deactivate IApplicationThread
	activate ApplicationThread
	ApplicationThread ->> ActivityThread : sendMessage
	deactivate ApplicationThread
	activate ActivityThread 
	ActivityThread ->> H : handleMessage
	deactivate ActivityThread
	activate H
	H ->> ActivityThread : handleBindApplication
	deactivate H
	activate ActivityThread
	ActivityThread ->> ActivityThread : installContentProviders
	ActivityThread ->> ActivityThread : installProvider
	ActivityThread ->> ContentProvider : attachInfo
	deactivate ActivityThread
	activate ContentProvider
	ContentProvider ->> ContentProvider : onCreate
	deactivate ContentProvider

我们查看AMS的attachApplication方法

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

该方法调用了attachApplicationLocked方法,在attachApplicationLocked方法中执行了thread.bindApplication方法

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

thread是IApplicationThread类型的,采用AIDL,bindApplication方法的实现是ApplicationThread类,是ActivityThread的内部类,ApplicationThread类定义如下

private class ApplicationThread extends IApplicationThread.Stub

ActivityThread.ApplicationThread.bindApplication方法最后调用了sendMessage方法

sendMessage(H.BIND_APPLICATION, data);

sendMessage方法向H类发送了BIND_APPLICATION类型的消息,消息会在handleMessage方法中得到处理

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;

当判断到是BIND_APPLICATION类型的消息,就会执行handleBindApplication方法,该方法执行了如下逻辑

  • 创建ContextImpl

    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    
  • 通过反射创建Instrumentation

    mInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();
    
  • 初始化Instrumentation

    mInstrumentation.init(this, instrContext, appContext, component,
                        data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
    
  • 创建Application

    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    
  • 调用installContentProviders方法启动ContentProvider

    installContentProviders(app, data.providers);
    
  • 调用Application的onCreate方法,意味着ContentProvider所在的应用程序已经启动

    mInstrumentation.onCreate(data.instrumentationArgs);
    

handleBindApplication方法中执行了installContentProviders来启动ContentProvider

  • 遍历当前应用程序进程的ProviderInfo列表,得到每个ContentProvider的信息

    for (ProviderInfo cpi : providers)
    
  • 调用installProvider方法来启动这些ContentProvider

    ContentProviderHolder cph = installProvider(context, null, cpi,
    							false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
    
  • 使用AMS的publishContentProviders方法将这些ContentProvider存储在AMS的mProviderMap中,起到缓存的作用

    ActivityManager.getService().publishContentProviders(getApplicationThread(), results);
    

最后来到installProvider方法查看是如何启动ContentProvider的

  • 通过反射来创建ContentProvider类型的localProvider对象

    localProvider = (ContentProvider)cl.loadClass(info.name).newInstance();
    
  • 调用ContentProvider的attachInfo方法

    localProvider.attachInfo(c, info);
    

    在attachInfo方法中调用了ContentProvider.this.onCreate();,这是一个抽象方法

到此为止,ContentProvider启动成功

四大组件启动过程总结

到此为止,学习完了四大组件的启动过程,Android8.0和Android7.0的主要区别是使用AIDL来代替了proxy代理类,四大组件启动过程都大同小异