Android 8.0 ContentProvider的学习和分析

本文详细介绍了 Android 系统中 ContentProvider 的应用。它用于不同应用间的数据交换,阐述了创建、注册 ContentProvider 的方法,以及使用 ContentResolver 查询数据库的方式。还介绍了涉及的关键类和关系,以及 Provider 进程启动后的发布流程和查询操作等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  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<ProviderInfo>

  /packages/providers/TelephonyProvider/AndroidManifest.xml

  <provider android:name="TelephonyProvider"

                  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<ProviderInfo> 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<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {

  List<ProviderInfo> 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<N; 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<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) {

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

  final ArrayList<ContentProviderHolder> 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<ContentProviderHolder> 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发布,直到发布后才退出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值