当前位置:   article > 正文

【Android】ContentProvider启动源码分析_content provider源码

content provider源码

一、概述

ContentProvider作为Android四大组件之一,是Android应用对外开放的数据接口,只要符合它所定义的Uri格式的请求,均可以正常访问执行操作。其他的Android应用可以使用ContentResolver对象通过与ContentProvider同名的方法请求执行,被执行的就是ContentProvider中的同名的方法。
本文主要介绍ContentProvider的启动流程。

二、正文

在这里插入图片描述

类图1
在这里插入图片描述

类图2
在这里插入图片描述

时序图1
在这里插入图片描述

时序图2
1.A应用发送信息给AMS(ActivityManagerService,进程system_server)要访问B应用的XXXContentProvider
2.AMS检查B应用没有被启动过,则新开一个进程启动B应用
3.启动应用B后,AMS向B应用启动XXXContentProvider,并实行相应的onCreate,返回IActivityManager.ContentProviderHolder,其中实现IContentProvider接口的Transact
4.AMS 把IActivityManager.ContentProviderHolder对象返回给A应用,A应用改造成代理ContentProviderProxy(即IContentProvider),此时A应用就可以调用增删改查等接口到B应用了。
照着类图和时序图的步数来分析:
在A应用进程处理:Step1、2、3、4、5、6、18、19
在AMS system_server进程处理:Step7、10、11、12、17
在B应用进程处理:Step8、9、13、14、15、16、20
Step1:
  ContentResolver contentResolver = Conext.getContentResolver();
返回是ApplicationContentResolver,定义在ContextImpl内部静态类。

Step2:
  Uri uri = Uri.parse(“content://cn.umbrella.providers.contact/item”);
Cursor cursor = contentResolver.query(uri, new String[]{“id”,“name”,“phone”}, null, null, “id asc”);
在ApplicationContentResolver.acquireProvider()调用ActivityThread类的acquireProvider函数进一步执行获取Content Provider接口的操作。

Step3、4、5:
  ActivityThread. acquireProvider:先本地查找,若有,则直接返回,没有则调用ActivityManagerNative.getDefault().getContentProvider(getApplicationThread(), auth, userId, stable)即ActivityManagerProxy到AMS的getContentProvider()。

Step6:
  在AMS. getContentProvider()调用getContentProviderImpl进一步处理,
在AMS中:ProviderMap mProviderMap成员变量是保存系统中的ContentProvider信息,boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed先检查XXXContentProvider存在、宿主进程以及没有被杀的情况下,就直接返回。
  若不存在,则会通过AppGlobals.getPackageManage().resolveContentProvider和getApplicationInfo来分别获取XXXProvider应用程序的相关信息,并保存cpi和cpr变量中。接下来会判断mLaunchingProviders(系统中所有正在加载的Content Provider都保到这里面)是不是正在被其它应用程序加载XXXContentProvider,如果B应用进程已开启,但对应的contentprovider未初始化过,则会走proc.thread.scheduleInstallProvider(cpi),到B应用的ActivityThread的handleInstallProvider、installContentProviders初始化contentProvider,略过Step7-13步直接Step14。
  如果B应用进程未启动,则继续走Step7 调用startProcessLocked函数来启动新进程并加装XXXContentProvider,并且把这个正在加载的信息增加到mLaunchingProviders中去,同步等到XXXContentProvider初始化完,while循环cpr.provider判空,然后cpr.wait(),等到Step17步publishContentProviders会dst.notifyAll()过来。

Step7、8、9、10:
  ActivityManagerService.startProcessLocked、Process.start、ActivityThread.main、ActivityThread.attach、ActivityManagerService.attachApplication 新进程的创建完回到AMS的过程,可参考startService源码从AMS进程到service的新进程启动过程分析
Step11:
  AMS. attachApplicationLocked, 会对这个B应用进程记录块做一些初始化,并获得需要加装的ContentProvider列表,即包括XXXContentProvider,然后调用从参数传进来的IApplicationThread对象thread(即ApplicationThreadProxy)的bindApplication进入到B应用程序XXXContentProvider进程中的ApplicationThread对象的bindApplication函数中去。

Step12、13:
  ApplicationThread(ActivityThread 变量). bindApplication通过H(Handler)到ActivityThread主进程中handleBindApplication处理,调用installContentProviders函数来在初始化XXXContent Providers信息,以及Application等初始化工作。

Step14、15:
  ActivityThread.installContentProviders 先调用installContentProviders对XXXContentProvider的初始化attachInfo,并调用onCreate,并把ContextProvider的成员变量Transport(父类ContentProviderNative,是binder对象,并且实现了IContentProvider接口)然后调用ActivityManagerNative.getDefault().publishContentProviders(getApplicationThread(), results),到Step16.
Step16:
  ActivityManagerProxy. publishContentProviders(IApplicationThread caller, List providers)通知AMS进程 ,B应用进程及XXXContentProvider都已初始化完毕,并把相应的IContentProvider给过去。

Step17 :
  AMS. publishContentProviders:会把B应用进程的的ContentProvider保存起来,并移除mLaunchingProviders里面相应的值,然后通知dst.notifyAll();到Step6的getContentProviderImpl,接着返回给A应用进程的ContentProviderHolder对象。

Step18:
  在AMS进程通过binder返回给A应用对象ContentProviderHolder,会把B应用进程的IContentProvider接口(即Transport)通过ContentProviderNative.asInterface(source.readStrongBinder())改造为ContentProviderProxy。

Step19、20:
  A应用进程拿到B应用进程的Transport后, ContentResolver.query()中调用ContentProviderProxy.query,这里面会BulkCursorToCursorAdaptor,包含CursorWindow等匿名共享内存方式读取数据。

附上一些关键的源码:

ContextImpl.java:

class ContextImpl extends Context {
   
    private final ApplicationContentResolver mContentResolver;
    @Override
    public ContentResolver getContentResolver() {
   
        return mContentResolver;
    }
    ...
    private static final class ApplicationContentResolver extends ContentResolver {
   
        private final ActivityThread mMainThread;
        private final UserHandle mUser;
        ...
        @Override
        protected IContentProvider acquireUnstableProvider(Context c, String auth) {
   
            return mMainThread.acquireProvider(c,
                    ContentProvider.getAuthorityWithoutUserId(auth),
                    resolveUserIdFromAuthority(auth), false);
        }
       ...
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

ContentResolver.java:

public abstract class ContentResolver {
   
    public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
            @Nullable String[] projection, @Nullable String selection,
            @Nullable String[] selectionArgs, @Nullable String sortOrder,
            @Nullable CancellationSignal cancellationSignal) {
   
        Preconditions.checkNotNull(uri, "uri");
        IContentProvider unstableProvider = acquireUnstableProvider(uri);
        ...
        try {
   
            qCursor = unstableProvider.query(mPackageName, uri, projection,
                    selection, selectionArgs, sortOrder, remoteCancellationSignal);
        } 
        ...
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

ActivityThread.java:

public final class ActivityThread {
   

    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
   
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        if (provider != null) {
   
            return provider;
        }
        ...
        IActivityManager.ContentProviderHolder holder = null;
        try {
   
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), auth, userId, stable);
        } catch (RemoteException ex) {
   
            throw ex.rethrowFromSystemServer();
        }
        ...
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }
    
    public final IContentProvider acquireExistingProvider(
            Context c, String auth, int userId, boolean stable) {
   
        synchronized (mProviderMap) {
   
            final ProviderKey key = new ProviderKey(auth, userId);
            final ProviderClientRecord pr = mProviderMap.get(key);
            ...
            IContentProvider provider = pr.mProvider;
            IBinder jBinder = provider.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/892113
推荐阅读
相关标签
  

闽ICP备14008679号