Android 8.0 ContentProvider的学习和分析

  1. ContentProvider的介绍和应用使用方法
    1. 如何使用ContentProvider

ContentProvider 组建主要用于 Android 系统中不同应用程序间的数据交换.例如应用程序 A 通过 ContentProvider 暴露内部的数据, 应用程序B 通过 ContentResolver 和 A 提供的 Uri 来操作(增, 删 改, 查) A 的数据.

如何创建一个contentPorvider

      1. 实现ContentProvider

创建一个类继承ContentProvider,然后实现ContentProvider的抽象类

  insert(Uri, ContentValues):插入新数据;

  delete(Uri, String, String[]):删除已有数据;

  update(Uri, ContentValues, String, String[]):更新数据;

  query(Uri, String[], String, String[], String):查询数据;

  onCreate():执行初始化工作;

  getType(Uri):获取数据MIME类型。

  ContentProvider的生命周期非常简单这里面只有一个onCreate方法

      1. 注册ContentProvider,

注册ContentProvider只需在AndroidManifest.xml配置文件中做如下声明

  例如TelephonyProvider需要做如下声明,这样开机的时候PKMS进行扫描会把TelephonyProvider加入到对应应用的List

  /packages/providers/TelephonyProvider/AndroidManifest.xml

 

                  android:authorities="telephony"

                  android:exported="true"

                  android:singleUser="true"

                  android:multiprocess="false" />

 

      1. 创建DB数据库文件

一般我们在contentProvider的实现类里面会定义一个内部类继承于SQLiteOpenHelper,用来创建操作具体的DB数据库文件,这里就不在详细介绍,之后再详细分析

 

    1. 如何使用ContentResolver查询对应的数据库

其他进程或者应用想要访问contentPorvider暴露出来的数据库,必须通过ContentResolver来实现,应用必须获取它的ContentResolver类才可以通过它访问contentPorvider的相关操作。

这里举个例子/vendor/sprd/platform/frameworks/base/telephony/java/android/telephony/DmykTelephonyManager.java

这里通过context 获取到ContentResolver,然后执行qurey操作,返回cursor对象,包含了我们要查找的对象,然后进行数据解析。

Cursor cursor = mContext.getContentResolver().query(Uri.parse(APN_URI + "preferapn/subId/" + subId), new String[] {

532                    "_id"}, where, null,orderBy);

533            if (cursor != null) {

534                if (cursor.getCount() > 0 && cursor.moveToFirst()) {

535                    preferedId = cursor.getInt(0);

536                    Log.d(TAG, "preferedId = " + preferedId + ", sub id = " + subId);

537                    if (preferedId != -1) {

538                        uri =  Uri.parse(APN_URI + preferedId);

539                    }

540                }

541                cursor.close();

542            }

 

    1. ContentProvider涉及的一些关键类和关系的介绍:

ContextImpl:Activity,Service,Application都是ContextWrapper的子类。ContextWrapper里面有一个Context类型的成员变量mBase,当然它实际的类型是ContextImpl,所以我们上文提到的getContentResolver实现就是在ContextImpl中

ApplicationContentResolver:getContentResolver获取的是mContentResolver对象,实际上它就是ApplicationContentResolver的实例。它是ContentResolver的实现类。

ActivityThread:应用进程的主线程

ContentProviderNative:ContentProviderNative这个文件是Framework binder服务实现的标志实现,这里面ContentProviderNative 继承Binder实现IContentProvider接口,主要作为IContentProvider的service端。

ContentProviderProxy:实现IContentProvider接口,主要是IContentProvider服务,binder通信的代理断,我们可以通过ContentProviderNative.asInterface(iBinder)获取ContentProviderProxy的实例

Transport:ContentProviderNative的实现类,也是ContentProvider的内部类,作为IContentProvider binder服务server端的最后实现类。

ContentProviderHolder:在installProvider的时候会为要启动的provider创建,里面主要有两个变量一个是(IContentProvider)Provider,一个(IBinder)connection。

ContentProviderRecord:AMS管理provider信息的,每public一个contentProvider会创建一个,和ActivityRecord,serviceRecord类似,里面有如下几个重要变量

  IContentProvider provider:在ActivityThread的installProvider()过程,会创建ContentProvider对象,那么也会创建Transport作为自己的binder服务端,放入到ContentProviderHolder的新实例中。经过binder传递到system_server 进程的便是ContentProvider.Transport的binder代理对象, 由publishContentProviders()过程完成赋值;

  proc:记录provider所在的进程,是在publishContentProviders()过程完成赋值;

  launchingApp:记录等待provider所在进程启动情况,getContentProviderImpl()过程执行创建进程之后赋值;

  connections:记录该ContentProvider的所有连接信息,

          添加连接过程:incProviderCountLocked

          减少连接过程:decProviderCountLocked,removeDyingProviderLocked,cleanUpApplicationRecordLocked;

ContentProviderConnection:连接contentProvider与请求该provider所对应的进程

几个重要变量:

  provider:目标provider所对应的ContentProviderRecord结构体;

  client:请求该provider的客户端进程;

  waiting:该连接的client进程正在等待该provider发布

ProviderInfo:PKMS解析应用后,会为每个ContentProvider声明创建一个该对象,写入相关信息

ProviderClientRecord:在AT里面记录新创建的Provider的信息,它的contentProvider,binder代理对象,ContentProviderHolde对象,UIR的auths对象

 

 

  1. Provider进程启动后的发布流程

Provider进程启动方式跟之前写过的AMS启动Activity类似,都需要先调用AMS.startProcessLocked()方法创建应用进程,应用进程启动后ActivityThread都会执行attached AMS的操作。

我们便从attached AMS的操作开始跟踪后续的发布过程。

AT-ActivityThread

AT经过binder调用AMS的attachApplicationLocked方法,

    1. AMS.attachApplicationLocked

private final boolean attachApplicationLocked(IApplicationThread thread,

            int pid) {

  //调用generateApplicationProvidersLocked获取对应app的ProviderInfo list,这个在开机的时候PKMS扫描解析出来声明的contentProvider

  List providers = normalMode ? generateApplicationProvidersLocked(app) : null;

  if (providers != null && checkAppInLaunchingProvidersLocked(app)) {//检查app是否正在launch,正常刚启动的进程为true

          Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);

          msg.obj = app;

          mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);//发生Provider public超时监测

          didSomething = true;

  }

  //调用对端应用主线程 AT.bindApplication

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

}

      1. AMS.generateApplicationProvidersLocked

private final List generateApplicationProvidersLocked(ProcessRecord app) {

  List providers = null;

  try {

          //从PKMS获取app对应进程的Provider list

          providers = AppGlobals.getPackageManager()

                           .queryContentProviders(app.processName, app.uid,

                                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS

                                                             | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/ null)

                           .getList();

  } catch (RemoteException ex) {

  }

 

  int userId = app.userId;

  if (providers != null) {

          int N = providers.size();

          app.pubProviders.ensureCapacity(N + app.pubProviders.size());//pubProviders进行list扩容

          for (int i=0; i

                   ProviderInfo cpi =

                           (ProviderInfo)providers.get(i);

                  boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,

                                    cpi.name, cpi.flags);

                   if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) {

                           // 判断对应ProviderInfo是单独进程的,同时不是系统用户

                           providers.remove(i);//从list移除ProviderInfo

                           N--;

                           i--;

                           continue;

                   }

                   //创建对应Provider的组件对象,包括包名和contentprovider名

                   ComponentName comp = new ComponentName(cpi.packageName, cpi.name);

                   //mProviderMap是AMS存储ContentProvider各种对应关系的类,这里主要是把ComponentName 和ContentProviderRecord对应起来,存入HashMap表。

                   ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);

                   if (cpr == null) {

                           cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);

                           mProviderMap.putProviderByClass(comp, cpr);

                   }

                   //pubProviders是ProcessRecord管理要public的Provider的list表

                   app.pubProviders.put(cpi.name, cpr);

                   if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {

                           // Don't add this if it is a platform component that is marked

                           // to run in multiple processes, because this is actually

                           // part of the framework so doesn't make sense to track as a

                           // separate apk in the process.

                           app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode,

                                            mProcessStats);

                   }

                   notifyPackageUse(cpi.applicationInfo.packageName,

                                                     PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER);

          }

  }

  return providers;

}

    1. AT.bindApplication

ActivityThread.java

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

  AppBindData data = new AppBindData();

  data.processName = processName;

  data.appInfo = appInfo;

  data.providers = providers;//通过data 放入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;

  sendMessage(H.BIND_APPLICATION, data);//发送BIND_APPLICATION消息调用到handleBindApplication(data)

}

 

      1. AT.handleBindApplication

private void handleBindApplication(AppBindData data) {

  if (!data.restrictedBackupMode) {

          if (!ArrayUtils.isEmpty(data.providers)) {//providers列表不为null

                   startTime = CheckTime.getTime();

                   installContentProviders(app, data.providers);//初始化安装Provider.

                   mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);

                   CheckTime.checkTime(startTime, "handleBindApplication : installContentProviders");

          }

  }

}

      1. AT.installContentProviders

private void installContentProviders(

          Context context, List providers) {

  final ArrayList results = new ArrayList<>();

 

  for (ProviderInfo cpi : providers) {

          遍历传入的providers list,调用installProvider安装对应ProviderInfo的Provider

          ContentProviderHolder cph = installProvider(context, null, cpi,

                           false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);

          if (cph != null) {

                   cph.noReleaseNeeded = true;

                   results.add(cph);

          }

  }

 

  try {

          //调用AMS 的publishContentProviders方法,public Provider,传入的参数是results

          ActivityManager.getService().publishContentProviders(

                   getApplicationThread(), results);

          if (SystemProperties.get("persist.support.securetest").equals("1"))

          {

//           下面逻辑主要是把proviedname数组的这些Provider,他们的binder 代理段注册到ServiceManager,这样可以直接从ServiceManager通过authority获取对应的Provider代理端

//                for(IActivityManager.ContentProviderHolder holder : results)

                   for(ContentProviderHolder holder : results)

                   {

                           Log.i(TAG , "add content provider authority:" + holder.info.authority + ", provider binder:" + holder.provider.asBinder());

                           String proviedname [] = {"sms","mms","mms-sms","call_log","contacts;com.android.contacts","icc","media",null} ;

                           for (int i = 0 ; proviedname[i] != null ; i++)

                           {

                                    if (proviedname[i].equals(holder.info.authority))

                                    {

                                            ServiceManager.addService(holder.info.authority, holder.provider.asBinder());

                                    }

                           }

                   }

          }

  } catch (RemoteException ex) {

          throw ex.rethrowFromSystemServer();

  }

}

 

      1. AT.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)) {

                   //AT的context的包名和ProviderInfo中包名相同

                   c = context;

          } else if (mInitialApplication != null &&

                           mInitialApplication.getPackageName().equals(ai.packageName)) {

                   //

                   c = mInitialApplication;

          } else {

                   try {

                           //如果前面的都不符合要求,创建context

                           c = context.createPackageContext(ai.packageName,

                                            Context.CONTEXT_INCLUDE_CODE);

                   } catch (PackageManager.NameNotFoundException e) {

                           // Ignore

                   }

          }

 

          if (info.splitName != null) {

                   try {

                           c = c.createContextForSplit(info.splitName);

                   } catch (NameNotFoundException e) {

                           throw new RuntimeException(e);

                   }

          }

 

          try {

                   final java.lang.ClassLoader cl = c.getClassLoader();

                   通过反射创建目标ContentProvider对象

                   localProvider = (ContentProvider)cl.

                           loadClass(info.name).newInstance();、

                   //获取localProvider的binder代理端Transport

                   provider = localProvider.getIContentProvider();

                   ....

                   //回调目标ContentProvider.onCreate方法,ContentProvider.this.onCreate();

                   localProvider.attachInfo(c, info);

          } catch (java.lang.Exception e) {

                   if (!mInstrumentation.onException(null, e)) {

                           throw new RuntimeException(

                                            "Unable to get provider " + info.name

                                            + ": " + e.toString(), e);

                  }

                   return null;

          }

  } else {

          provider = holder.provider;

          if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "

                           + info.name);

  }

 

  ContentProviderHolder retHolder;

  synchronized (mProviderMap) {

          if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider

                           + " / " + info.name);

          IBinder jBinder = provider.asBinder();

          if (localProvider != null) {

                   把新创建的localProvider,创建一个对应的ProviderClientRecord,并放入到mLocalProvidersByName 和mLocalProviders map表中

                  ComponentName cname = new ComponentName(info.packageName, info.name);

                   ProviderClientRecord pr = mLocalProvidersByName.get(cname);

                   if (pr != null) {

                           if (DEBUG_PROVIDER) {

                                    Slog.v(TAG, "installProvider: lost the race, "

                                                    + "using existing local provider");

                           }

                           provider = pr.mProvider;

                   } else {

                           holder = new ContentProviderHolder(info);

                           holder.provider = provider;

                           holder.noReleaseNeeded = true;

                           pr = installProviderAuthoritiesLocked(provider, localProvider, holder);

                           mLocalProviders.put(jBinder, pr);

                           mLocalProvidersByName.put(cname, pr);

                   }

                   retHolder = pr.mHolder;

          } ....

  return retHolder;

}

    1. AMS.publishContentProviders

public final void publishContentProviders(IApplicationThread caller,

          List providers) {

  if (providers == null) {

          return;

  }

 

  enforceNotIsolatedCaller("publishContentProviders");

  synchronized (this) {

          //通过caller获取对应的应用进程对象ProcessRecord

          final ProcessRecord r = getRecordForAppLocked(caller);

          if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid);

          .....

 

          final long origId = Binder.clearCallingIdentity();

 

          final int N = providers.size();

          for (int i = 0; i < N; i++) {

                   //遍历providers列表,取出每个ContentProviderHolder对象

                   ContentProviderHolder src = providers.get(i);

                   if (src == null || src.info == null || src.provider == null) {

                           continue;

                   }

                   //之前这些要发布的Provider放到了pubProviders列表,此处根据name取出对应的ContentProviderRecord对象

                   ContentProviderRecord dst = r.pubProviders.get(src.info.name);

                   if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);

                   if (dst != null) {

                           //还是根据包名和Provider名字创建组件名字实例

                           ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);

                           //把创建的组件实例和ContentProviderRecord实例以键值对的形式存入mProviderMap的putProviderByClass hashmap表。

                           mProviderMap.putProviderByClass(comp, dst);

                           String names[] = dst.info.authority.split(";");

                           for (int j = 0; j < names.length; j++) {

                                    //将URI的authority信息解析成字符串数组,也存入putProviderByName map表

                                    mProviderMap.putProviderByName(names[j], dst);

                           }

                           //然后把这些Provider的ContentProviderRecord实例从launchingCount列表移除

                           int launchingCount = mLaunchingProviders.size();

                           int j;

                           boolean wasInLaunchingProviders = false;

                           for (j = 0; j < launchingCount; j++) {

                                    if (mLaunchingProviders.get(j) == dst) {

                                            mLaunchingProviders.remove(j);

                                            wasInLaunchingProviders = true;

                                            j--;

                                            launchingCount--;

                                    }

                           }

                           //移除public 超时信息

                           if (wasInLaunchingProviders) {

                           mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);

                           }

                           synchronized (dst) {

                                    dst.provider = src.provider;

                                    dst.proc = r;

                                    //唤醒客户端的wait等待方法,可能有些进程正在等待Provider进程的公布。

                                    dst.notifyAll();

                           }

                           //更新当前Provider进程的adj

                           updateOomAdjLocked(r, true);

                           maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,

                                            src.info.authority);

                   }

          }

 

          Binder.restoreCallingIdentity(origId);

  }

}

 

  1. 应用查询Provider的调用流程

第一章介绍过,我们先获取ContentResolver对象进行相关操作。

    1. getContentResolver

我们一般都是获取当前应用的context,然后调用getContentResolver,实际的执行则是在ContextImpl实现的

ContextImpl.java

public ContentResolver getContentResolver() {

  return mContentResolver;

}

那么mContentResolver对象在那赋值的呢

实在ContextImpl构造函数里面

mContentResolver = new ApplicationContentResolver(this, mainThread, user);

前面介绍过ApplicationContentResolver就是ContentResolver的实现类

    1. ContentResolver.query

ApplicationContentResolver没有复写query,所以还是调用ContentResolver.query

public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,

          @Nullable String[] projection, @Nullable Bundle queryArgs,

          @Nullable CancellationSignal cancellationSignal) {

  Preconditions.checkNotNull(uri, "uri");

  //调用 AT.acquireExistingProvider查询本地的Provider,如果没有则调用AMS查询对应的Provider的代理对象

  IContentProvider unstableProvider = acquireUnstableProvider(uri);

  if (unstableProvider == null) {

          return null;

  }

  IContentProvider stableProvider = null;

  Cursor qCursor = null;

  try {

          //记录开始查询时间

          long startTime = SystemClock.uptimeMillis();

 

          ICancellationSignal remoteCancellationSignal = null;

          if (cancellationSignal != null) {

                   cancellationSignal.throwIfCanceled();

                   remoteCancellationSignal = unstableProvider.createCancellationSignal();

                   cancellationSignal.setRemote(remoteCancellationSignal);

          }

          try {

                   //通过调用Provider代理端,访问Provider服务提供者的query方法

                   qCursor = unstableProvider.query(mPackageName, uri, projection,

                                    queryArgs, remoteCancellationSignal);

          } catch (DeadObjectException e) {

                   // 远程进程死亡,处理unstable provider死亡过程

                   unstableProviderDied(unstableProvider);

                   //unstable类型死亡后,再创建stable类型的provider

                   stableProvider = acquireProvider(uri);

                   if (stableProvider == null) {

                           return null;

                   }

                   //再次执行查询操作

                   qCursor = stableProvider.query(

                                    mPackageName, uri, projection, queryArgs, remoteCancellationSignal);

          }

          if (qCursor == null) {

                   return null;

          }

 

          /强制执行查询操作,可能会失败并跑出RuntimeException

          qCursor.getCount();

          //查询持续时间

          long durationMillis = SystemClock.uptimeMillis() - startTime;

          maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);

 

          // Wrap the cursor object into CursorWrapperInner object.

          final IContentProvider provider = (stableProvider != null) ? stableProvider

                           : acquireProvider(uri);

          ////创建对象CursorWrapperInner

          final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);

          stableProvider = null;

          qCursor = null;

          return wrapper;

  } catch (RemoteException e) {

          // Arbitrary and not worth documenting, as Activity

          // Manager will kill this process shortly anyway.

          return null;

  } finally {

          if (qCursor != null) {

                   qCursor.close();

          }

          if (cancellationSignal != null) {

                   cancellationSignal.setRemote(null);

          }

          if (unstableProvider != null) {

                   releaseUnstableProvider(unstableProvider);

          }

          if (stableProvider != null) {

                   releaseProvider(stableProvider);

          }

  }

}

    1. AT.acquireUnstableProvider

ContentResolver.acquireUnstableProvider最后的实现都在ApplicationContentResolver,对应的调用都是分别调用如下

mMainThread.acquireExistingProvid

 

public final IContentProvider acquireExistingProvider(

          Context c, String auth, int userId, boolean stable) {

  synchronized (mProviderMap) {

          //根据传入的auth, userId创建一个对应的key

          final ProviderKey key = new ProviderKey(auth, userId);

          然后根据key从mProviderMap查询对应的ProviderClientRecord

          final ProviderClientRecord pr = mProviderMap.get(key);

          if (pr == null) {

                   return null;

          }

          从获取的ProviderClientRecord中获取IContentProvider 实例mProvider也就是本地Provider的代理对象

          IContentProvider provider = pr.mProvider;

          IBinder jBinder = provider.asBinder();

          if (!jBinder.isBinderAlive()) {

                   // The hosting process of the provider has died; we can't

                   // use this one.

                   Log.i(TAG, "Acquiring provider " + auth + " for user " + userId

                                    + ": existing object's process dead");

                   handleUnstableProviderDiedLocked(jBinder, true);

                   return null;

          }

          // 增加引用计数

          ProviderRefCount prc = mProviderRefCountMap.get(jBinder);

          if (prc != null) {

                   incProviderRefLocked(prc, stable);

          }

          return provider;

  }

}

    1. AT.acquireProvider

ContentResolver.acquireProvider

最后的实现都在ApplicationContentResolver,对应的调用都是分别调用如下

mMainThread.acquireProvider

public final IContentProvider acquireProvider(

            Context c, String auth, int userId, boolean stable) {

  //通过AT mProviderMap 获取 ProviderClientRecord,然后在找出对应的IContentProvider对象

  final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);

  if (provider != null) {

        return provider;

  }

  ContentProviderHolder holder = null;

  try {

          //向AMS传入auth,userId等信息,查询我要查询的Provider对应的ContentProviderHolder实例

          holder = ActivityManager.getService().getContentProvider(

                           getApplicationThread(), auth, userId, stable);

  } catch (RemoteException ex) {

          throw ex.rethrowFromSystemServer();

  }

  if (holder == null) {

          Slog.e(TAG, "Failed to find provider info for " + auth);

          return null;

  }

  // 根据传入的holder,调用installProvider,如果传入的holder不为null则主要实现增加引用计数

  holder = installProvider(c, holder, holder.info,

                   true /*noisy*/, holder.noReleaseNeeded, stable);

  // 这样我们就获取了IContentProvider 实例provider

  return holder.provider;  

}

 

    1. AMS.getContentProvider

它主要在getContentProviderImpl中实现的

这里面的代码不少,我主要把里面重要的内容摘取出来,主要先关注查询的一个大概流程

ContentProviderRecord cpr;

ContentProviderConnection conn = null;

ProviderInfo cpi = null;

ProcessRecord r = null;

获取调用应用在AMS的ProcessRecord实例

r = getRecordForAppLocked(caller);

根据name,userId获取要查询的Provider在AMS的ContentProviderRecord实例,下面会根据不同场景选择userid,这里不做赘述,只贴出主要方法

cpr = mProviderMap.getProviderByName(name, requestedFromAppClone ? UserHandle.USER_OWNER : userId);

//providerRunning 作为Provider进程是否启动并在AMS发布的一个判断值

boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;

 

下面我会有两种情况,Provider进程已经启动,或者没启动

我们先看

Provider进程已经启动的情况:

cpi = cpr.info;

if (r != null && cpr.canRunHere(r)) {

  //当允许运行在调用者进程且已发布,则直接返回

  ContentProviderHolder holder = cpr.newHolder(null);

  holder.provider = null;

  return holder;

}

//增加引用计数

conn = incProviderCountLocked(r, cpr, token, stable);

if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {

  if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {

          // 更新LUR队列

          checkTime(startTime, "getContentProviderImpl: before updateLruProcess");

          updateLruProcessLocked(cpr.proc, false, null);

         checkTime(startTime, "getContentProviderImpl: after updateLruProcess");

  }

}

当Provider进程没有启动,则启动

//根据authority,获取ProviderInfo对象

cpi = AppGlobals.getPackageManager().

                        resolveContentProvider(name,

                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);

//当provider并没有处于mLaunchingProviders队列,则启动它

proc = startProcessLocked(cpi.processName,

                                    cpr.appInfo, false, 0, "content provider",

                                    new ComponentName(cpi.applicationInfo.packageName,

                                            cpi.name), false, false, false);

最后会等待Provider发布,直到发布后才退出

你可能感兴趣的:(Android 8.0 ContentProvider的学习和分析)