ContentProvider相关学习(1)-客户端query相
以query为例,学习四大组件中的ContentProvider的相关逻辑
服务端启动逻辑
ContextImpl#getContentResolver
241 @Override
242 public ContentResolver getContentResolver() {
243 return mContentResolver;
244 }
ContentResolve#query
643 * @param uri The URI, using the content:// scheme, for the content to
644 * retrieve.
645 * @param projection A list of which columns to return. Passing null will
646 * return all columns, which is inefficient.
//这个参数告诉查询要返回的列
647 * @param selection A filter declaring which rows to return, formatted as an
648 * SQL WHERE clause (excluding the WHERE itself). Passing null will
649 * return all rows for the given URI.
//一个简化版的sql where语句
650 * @param selectionArgs You may include ?s in selection, which will be
651 * replaced by the values from selectionArgs, in the order that they
652 * appear in the selection. The values will be bound as Strings.
//配合第三个参数使用,你可以在第三个参数中使用占位符"?",那么在第四个参数据会替换掉占位符
653 * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
654 * clause (excluding the ORDER BY itself). Passing null will use the
655 * default sort order, which may be unordered.
656 * @return A Cursor object, which is positioned before the first entry, or null
657 * @see Cursor
658 */
659 public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
660 @Nullable String[] projection, @Nullable String selection,
661 @Nullable String[] selectionArgs, @Nullable String sortOrder) {
662 android.util.SeempLog.record_uri(13, uri);
663 return query(uri, projection, selection, selectionArgs, sortOrder, null);
664 }
ContentResolver#query
/**
709 * Query the given URI, returning a {@link Cursor} over the result set
710 * with support for cancellation.
711 *
712 * <p>For best performance, the caller should follow these guidelines:
713 *
714 * <li>Provide an explicit projection, to prevent reading data from storage
715 * that aren't going to be used.
716 *
717 * Provider must identify which QUERY_ARG_SORT* arguments were honored during
718 * the preparation of the result set by including the respective argument keys
719 * in the {@link Cursor} extras {@link Bundle}. See {@link #EXTRA_HONORED_ARGS}
720 * for details.
721 *
722 * @see #QUERY_ARG_SORT_COLUMNS, #QUERY_ARG_SORT_DIRECTION, #QUERY_ARG_SORT_COLLATION.
723 *
724 * @param uri The URI, using the content:// scheme, for the content to
725 * retrieve.
726 * @param projection A list of which columns to return. Passing null will
727 * return all columns, which is inefficient.
728 * @param queryArgs A Bundle containing any arguments to the query.
729 * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
730 * If the operation is canceled, then {@link OperationCanceledException} will be thrown
731 * when the query is executed.
732 * @return A Cursor object, which is positioned before the first entry, or null
733 * @see Cursor
734 */
735 public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
736 @Nullable String[] projection, @Nullable Bundle queryArgs,
737 @Nullable CancellationSignal cancellationSignal) {
738 android.util.SeempLog.record_uri(13, uri);
739 Preconditions.checkNotNull(uri, "uri");
740 IContentProvider unstableProvider = acquireUnstableProvider(uri); //得到unstable provider
741 if (unstableProvider == null) {
742 return null;
743 }
744 IContentProvider stableProvider = null;
745 Cursor qCursor = null;
746 try {
747 long startTime = SystemClock.uptimeMillis();
748
749 ICancellationSignal remoteCancellationSignal = null;
750 if (cancellationSignal != null) {
751 cancellationSignal.throwIfCanceled();
752 remoteCancellationSignal = unstableProvider.createCancellationSignal();
753 cancellationSignal.setRemote(remoteCancellationSignal);
754 }
755 try {
// binder call到服务端,返回了一个cursor对象
//当调用cursor.close时,会调用调releaseProvider来释放ContentProvider服务端与客户端之间的引用(从而保证客户端进程不会被联级杀死)
756 qCursor = unstableProvider.query(mPackageName, uri, projection,
757 queryArgs, remoteCancellationSignal);
758 } catch (DeadObjectException e) {
759 // The remote process has died... but we only hold an unstable
760 // reference though, so we might recover!!! Let's try!!!!
761 // This is exciting!!1!!1!!!!1
//先释放客户端的unstableProvider相关的引用,然后杀死unstable contentprovider所在的宿主进程
762 unstableProviderDied(unstableProvider);
764 //stableProvider = acquireProvider(uri);
765 //if (stableProvider == null) {
766 // return null;
767 //}
768 //qCursor = stableProvider.query(mPackageName, uri, projection,
769 //selection, selectionArgs, sortOrder, remoteCancellationSignal);
770 if(ContentResolverInjector.isForceAcquireUnstableProvider(mPackageName, uri)){
//miui逻辑,意思是对于某些客户端进程,当服务端被杀后,不让其走到下面的stable ContentProvider query,而是再走一遍unstableProvider.query,保证核心进程(客户端)不因为服务端的被杀而被杀死
771 qCursor = ContentResolverInjector.unstableQuery(this, uri, projection,
772 queryArgs, remoteCancellationSignal);
773 }else {
// 第二次进行尝试时,将使用stableProvider
774 stableProvider = acquireProvider(uri);
775 if (stableProvider == null) {
776 return null;
777 }
// 注意,失败一次后将使用stableProvider,这次如果服务端进程被杀
// 并且cursor还没有调用close之前,那么客户端的进程会受到牵连也被杀死
778 qCursor = stableProvider.query(
779 mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
780 }
781 // END
782 }
783 if (qCursor == null) {
784 return null;
785 }
786
787 // Force query execution. Might fail and throw a runtime exception here.
788 qCursor.getCount();
789 long durationMillis = SystemClock.uptimeMillis() - startTime;
790 maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
791
792 // Wrap the cursor object into CursorWrapperInner object.
793 final IContentProvider provider = (stableProvider != null) ? stableProvider
794 : acquireProvider(uri);
795 final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
796 stableProvider = null;
797 qCursor = null;
798 return wrapper;
799 } catch (RemoteException e) {
800 // Arbitrary and not worth documenting, as Activity
801 // Manager will kill this process shortly anyway.
802 return null;
803 } finally {
// 如果不为空才close
// 上面的操作如果成功了,qCursor是不会是空的,所以这个关闭操作交给了APP端来做
804 if (qCursor != null) {
805 qCursor.close();
806 }
807 if (cancellationSignal != null) {
808 cancellationSignal.setRemote(null);
809 }
810 if (unstableProvider != null) {
811 releaseUnstableProvider(unstableProvider);
812 }
813 if (stableProvider != null) {
814 releaseProvider(stableProvider);
815 }
816 }
817 }
首先尝试得到Unstable ContentProvider,返回其实例的binder代理
ContentResolve#acquireUnstableProvider
1783 /**
1784 * Returns the content provider for the given content URI.
1785 *
1786 * @param uri The URI to a content provider
1787 * @return The ContentProvider for the given URI, or null if no content provider is found.
1788 * @hide
1789 */
1790 public final IContentProvider acquireUnstableProvider(Uri uri) {
1791 if (!SCHEME_CONTENT.equals(uri.getScheme())) {
1792 return null;
1793 }
1794 String auth = uri.getAuthority();
1795 if (auth != null) {
1796 return acquireUnstableProvider(mContext, uri.getAuthority());
1797 }
1798 return null;
1799 }
ContextImpl.ApplicationContentResolver#acquireUnstableProvider
2510 @Override
2511 protected IContentProvider acquireUnstableProvider(Context c, String auth) {
2512 return mMainThread.acquireProvider(c,
2513 ContentProvider.getAuthorityWithoutUserId(auth),
2514 resolveUserIdFromAuthority(auth), false);
2515 }
调用ActivityThread中的acquireProvider
5845 public final IContentProvider acquireProvider(
5846 Context c, String auth, int userId, boolean stable) {
5847 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
//看看客户端中的mProviderMap是否有保存相应的ContentProviderRecord
5848 if (provider != null) {
5849 return provider; //若已保存则直接返回
5850 }
5851
5852 // There is a possible race here. Another thread may try to acquire
5853 // the same provider at the same time. When this happens, we want to ensure
5854 // that the first one wins.
5855 // Note that we cannot hold the lock while acquiring and installing the
5856 // provider since it might take a long time to run and it could also potentially
5857 // be re-entrant in the case where the provider is in the same process.
5858 ContentProviderHolder holder = null;
5859 try {
5860 holder = ActivityManager.getService().getContentProvider(
5861 getApplicationThread(), auth, userId, stable);
//通过AMS的getContentProvider获得相关的ContentProviderHolder,其中保存了IContentProvider
5862 } catch (RemoteException ex) {
5863 throw ex.rethrowFromSystemServer();
5864 }
5865 if (holder == null) {
//无法获取auth所对应的provider则直接返回
5866 Slog.e(TAG, "Failed to find provider info for " + auth);
5867 return null;
5868 }
5869
5870 // Install provider will increment the reference count for us, and break
5871 // any ties in the race.
//如果ContentProvider install过了,这个功能只是增加引用计数
5872 holder = installProvider(c, holder, holder.info,
5873 true /*noisy*/, holder.noReleaseNeeded, stable);
5874 return holder.provider;
5875 }
首先查看acquireExistingProvider
ActivityThread#acquireExistingProvider
查找已存储的provider,返回IContentProvider,找不到就返回null
6109 public final IContentProvider acquireExistingProvider(
6110 Context c, String auth, int userId, boolean stable) {
6112 return acquireExistingProvider(c, new ProviderKey(auth, userId), stable);
6113 }
6115 public final IContentProvider acquireExistingProvider(
6116 Context c, ProviderKey key, boolean stable) {
6118 synchronized (mProviderMap) {
6119 final ProviderClientRecord pr = mProviderMap.get(key);
6120 if (pr == null) {
6121 return null;
//首先从ActivityThread的mProviderMap查询是否存在相对应的provider,若不存在则直接返回(即查看客户端有没有保存相应的IContentProvider binder proxy)
6122 }
6123
6124 IContentProvider provider = pr.mProvider; //得到保存的IContentProvider
6125 IBinder jBinder = provider.asBinder();
6126 if (!jBinder.isBinderAlive()) { //提供ContentProvider的服务端已死亡
6127 // The hosting process of the provider has died; we can't
6128 // use this one.
6130 //Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
6131 Log.i(TAG, "Acquiring provider " + key.authority + " for user " + key.userId
6132 + ": existing object's process dead");
6133 handleUnstableProviderDiedLocked(jBinder, true); //jbinder代表服务端ContentProvider的binder对象
//调用handleUnstableProviderDiedLocked清理客户端相关信息,provider信息,杀死provider宿主进程,并返回null
6134 return null;
6135 }
6136
6137 // Only increment the ref count if we have one. If we don't then the
6138 // provider is not reference counted and never needs to be released.
6139 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
//provider已经在宿主进程被安装过了,直接增加引用计数就行了
6140 if (prc != null) {
6141 incProviderRefLocked(prc, stable);
//找到了存储的IContentProvider,且ContentProvider进程未被销毁,则客户端数据结构增加引用计数即可
6142 }
//并返回已保存的IContentProvider
6143 return provider;
6144 }
6145 }
两个重要函数:
handleUnstableProviderDiedLocked
incProviderRefLocked
ActivityThread#handleUnstableProviderDiedLocked
6285 final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
6286 ProviderRefCount prc = mProviderRefCountMap.get(provider);
6287 if (prc != null) {
6288 if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
6289 + provider + " " + prc.holder.info.name);
6290 mProviderRefCountMap.remove(provider);
//移除IContentProvider所对应的mProviderRefCountMap对象
6291 for (int i=mProviderMap.size()-1; i>=0; i--) {
6292 ProviderClientRecord pr = mProviderMap.valueAt(i);
6293 if (pr != null && pr.mProvider.asBinder() == provider) {
6294 Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString());
6295 mProviderMap.removeAt(i);
//移除对应的ProviderClientRecord对象
6296 }
6297 }
6298 //对本地mProviderRefCountMap和mProviderMap做清理工作(当ContentProvider服务端所在进程已死亡时)
6299 if (fromClient) {
6300 // We found out about this due to execution in our client
6301 // code. Tell the activity manager about it now, to ensure
6302 // that the next time we go to do anything with the provider
6303 // it knows it is dead (so we don't race with its death
6304 // notification).
6305 try {
6306 ActivityManager.getService().unstableProviderDied(
6307 prc.holder.connection); //AMS中对ContentProvider服务端进程的清理
6308 } catch (RemoteException e) {
6309 //do nothing content provider object is dead any way
6310 }
6311 }
6312 }
6313 }
ActivityManagerService#unstableProviderDied
针对ContentProvider服务端进程的清理
12407 public void unstableProviderDied(IBinder connection) { //connection:代表ContentResolver客户端(AMS中表示为ContentProviderConnection)的binder对象
12408 ContentProviderConnection conn;
12409 try {
12410 conn = (ContentProviderConnection)connection;
12411 } catch (ClassCastException e) {
12412 String msg ="refContentProvider: " + connection
12413 + " not a ContentProviderConnection";
12414 Slog.w(TAG, msg);
12415 throw new IllegalArgumentException(msg);
12416 }
12417 if (conn == null) {
12418 throw new NullPointerException("connection is null");
12419 }
12420
12421 // Safely retrieve the content provider associated with the connection.
12422 IContentProvider provider;
12423 synchronized (this) {
12424 provider = conn.provider.provider; //从客户端的数据结构ContentProviderConnection找到其服务端
12425 }
12426
12427 if (provider == null) {
12428 // Um, yeah, we're way ahead of you.
12429 return;
12430 }
12431
12432 // Make sure the caller is being honest with us.
12433 if (provider.asBinder().pingBinder()) { //服务端不允许死亡时
/** pingBinder
* Default implementation always returns true -- if you got here,
* the object is alive.
*/
12434 // Er, no, still looks good to us.
12435 synchronized (this) {
12436 Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
12437 + " says " + conn + " died, but we don't agree");
12438 return;
12439 }
12440 }
12441
12442 // Well look at that! It's dead!
12443 synchronized (this) {
12444 if (conn.provider.provider != provider) {
12445 // But something changed... good enough.
12446 return;
12447 }
12448
12449 ProcessRecord proc = conn.provider.proc; // if non-null, hosting process. (宿主进程)
12450 if (proc == null || proc.thread == null) {
12451 // Seems like the process is already cleaned up. //服务端(ContentProvider宿主进程已死亡)
12452 return;
12453 }
12454
12455 // As far as we're concerned, this is just like receiving a
12456 // death notification... just a bit prematurely.
12457 Slog.i(TAG, "Process " + proc.processName + " (pid " + proc.pid
12458 + ") early provider death");
12459 final long ident = Binder.clearCallingIdentity();
12460 try {
12461 appDiedLocked(proc); //kill宿主进程(服务端)死亡
12462 } finally {
12463 Binder.restoreCallingIdentity(ident);
12464 }
12465 }
12466 }
ActivityThread#incProviderRefLocked
6040 private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
6041 if (stable) {
6042 prc.stableCount += 1;
6043 if (prc.stableCount == 1) {
6044 // We are acquiring a new stable reference on the provider.
6045 int unstableDelta;
6046 if (prc.removePending) {
6047 // We have a pending remove operation, which is holding the
6048 // last unstable reference. At this point we are converting
6049 // that unstable reference to our new stable reference.
6050 unstableDelta = -1;
6051 // Cancel the removal of the provider.
6052 if (DEBUG_PROVIDER) {
6053 Slog.v(TAG, "incProviderRef: stable "
6054 + "snatched provider from the jaws of death");
6055 }
6056 prc.removePending = false;
6057 // There is a race! It fails to remove the message, which
6058 // will be handled in completeRemoveProvider().
6059 mH.removeMessages(H.REMOVE_PROVIDER, prc);
6060 } else {
6061 unstableDelta = 0;
6062 }
6063 try {
6064 if (DEBUG_PROVIDER) {
6065 Slog.v(TAG, "incProviderRef Now stable - "
6066 + prc.holder.info.name + ": unstableDelta="
6067 + unstableDelta);
6068 }
6069 ActivityManager.getService().refContentProvider(
6070 prc.holder.connection, 1, unstableDelta);
6071 } catch (RemoteException e) {
6072 //do nothing content provider object is dead any way
6073 }
6074 }
6075 } else {
6076 prc.unstableCount += 1;
6077 if (prc.unstableCount == 1) {
6078 // We are acquiring a new unstable reference on the provider.
//removePending = true,意味着stable和unstable的引用都会设置为0
//相应的ProviderRefCount待移除,除了服务端进程被杀导致的移除外,还有正常realease的情况
//见ActivityThread#releaseProvider
6079 if (prc.removePending) {
6080 // Oh look, we actually have a remove pending for the
6081 // provider, which is still holding the last unstable
6082 // reference. We just need to cancel that to take new
6083 // ownership of the reference.
6084 if (DEBUG_PROVIDER) {
6085 Slog.v(TAG, "incProviderRef: unstable "
6086 + "snatched provider from the jaws of death");
6087 }
//当ProviderRefCount有了新的引用计数时,则removePending必须记为false
//且移除REMOVE_PROVIDER消息,停止移除ProviderRefCount改对象信息,参考completeRemoveProvider((ProviderRefCount)msg.obj);
6088 prc.removePending = false;
6089 mH.removeMessages(H.REMOVE_PROVIDER, prc);
6090 } else {
//当不是第一个reference时
6091 // First unstable ref, increment our count in the
6092 // activity manager.
6093 try {
6094 if (DEBUG_PROVIDER) {
6095 Slog.v(TAG, "incProviderRef: Now unstable - "
6096 + prc.holder.info.name);
6097 }
6098 ActivityManager.getService().refContentProvider(
6099 prc.holder.connection, 0, 1);
6100 } catch (RemoteException e) {
6101 //do nothing content provider object is dead any way
6102 }
6103 }
6104 }
6105 }
6106 }
ActivityManagerService#refContentProvider
增加(说改变更准确,减少的时候也能用的到)AMS中客户端相关结构ContentProviderConnection的引用计数
12366 public boolean refContentProvider(IBinder connection, int stable, int unstable) {
12367 ContentProviderConnection conn;
12368 try {
12369 conn = (ContentProviderConnection)connection;
12370 } catch (ClassCastException e) {
12371 String msg ="refContentProvider: " + connection
12372 + " not a ContentProviderConnection";
12373 Slog.w(TAG, msg);
12374 throw new IllegalArgumentException(msg);
12375 }
12376 if (conn == null) {
12377 throw new NullPointerException("connection is null");
12378 }
12379
12380 synchronized (this) {
12381 if (stable > 0) {
12382 conn.numStableIncs += stable;
12383 }
12384 stable = conn.stableCount + stable;
12385 if (stable < 0) {
12386 throw new IllegalStateException("stableCount < 0: " + stable);
12387 }
12388
12389 if (unstable > 0) {
12390 conn.numUnstableIncs += unstable;
12391 }
12392 unstable = conn.unstableCount + unstable;
12393 if (unstable < 0) {
12394 throw new IllegalStateException("unstableCount < 0: " + unstable);
12395 }
12396
12397 if ((stable+unstable) <= 0) {
12398 throw new IllegalStateException("ref counts can't go to zero here: stable="
12399 + stable + " unstable=" + unstable);
12400 }
12401 conn.stableCount = stable;
12402 conn.unstableCount = unstable;
12403 return !conn.dead;
12404 }
12405 }
以上是acquireExistingProvider的大体流程,下面接着看:
5860 holder = ActivityManager.getService().getContentProvider(
5861 getApplicationThread(), auth, userId, stable);
ActivityManagerService#getContentProvider
12032 @Override
12033 public final ContentProviderHolder getContentProvider(
12034 IApplicationThread caller, String name, int userId, boolean stable) {
12035 enforceNotIsolatedCaller("getContentProvider");
12036 if (caller == null) {
12037 String msg = "null IApplicationThread when getting content provider "
12038 + name;
12039 Slog.w(TAG, msg);
12040 throw new SecurityException(msg);
12041 }
12042 // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
12043 // with cross-user grant.
12044 return getContentProviderImpl(caller, name, null, stable, userId);
12045 }
ActivityManagerService#getContentProviderImpl
11766 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
11767 String name, IBinder token, boolean stable, int userId) {
11768 ContentProviderRecord cpr;
11769 ContentProviderConnection conn = null;
11770 ProviderInfo cpi = null;
11771
11772 synchronized(this) {
11773 long startTime = SystemClock.uptimeMillis();
11774
11775 ProcessRecord r = null;
11776 if (caller != null) {
11777 r = getRecordForAppLocked(caller); //得到查询ContentProvider的客户端进程
11778 if (r == null) {
11779 throw new SecurityException(
11780 "Unable to find app for caller " + caller
11781 + " (pid=" + Binder.getCallingPid()
11782 + ") when getting content provider " + name);
11783 }
11784 }
11785
11786 boolean checkCrossUser = true;
11787
11788 checkTime(startTime, "getContentProviderImpl: getProviderByName");
11789
11790 // First check if this content provider has been published...
11791 cpr = mProviderMap.getProviderByName(name, userId);
//从AMS中的mProviderMap查询相应的ContentProviderRecord,也需要被publish,类似Service
11792 // If that didn't work, check if it exists for user 0 and then
11793 // verify that it's a singleton provider before using it.
11794 if (cpr == null && userId != UserHandle.USER_SYSTEM) {
11795 cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
11796 if (cpr != null) {
11797 cpi = cpr.info;
11798 if (isSingleton(cpi.processName, cpi.applicationInfo,
11799 cpi.name, cpi.flags)
11801 // && isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
11802 && isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
11805 userId = UserHandle.USER_SYSTEM;
11806 checkCrossUser = false;
11807 } else {
11808 cpr = null;
11809 cpi = null;
11810 }
11811 }
11812 }
11813
11814 boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed; //cpr代表 ContentProviderRecord ,记录ContentProvider
11815 if (providerRunning) { //目标proovider已存在
11816 cpi = cpr.info;
11817 String msg;
11818 checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
11819 if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
11820 != null) { //判断客户端是否有权限get ContentProvider
11821 throw new SecurityException(msg);
11822 }
11823 checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
11824
11825 if (r != null && cpr.canRunHere(r)) { //ContentProvider能否运行在客户端进程
11826 // This provider has been published or is in the process
11827 // of being published... but it is also allowed to run
11828 // in the caller's process, so don't make a connection
11829 // and just let the caller instantiate its own instance.
11830 ContentProviderHolder holder = cpr.newHolder(null);
11831 // don't give caller the provider object, it needs
11832 // to make its own.
11833 holder.provider = null;
11834 return holder;
11835 }
11836 // Don't expose providers between normal apps and instant apps
11837 try {
11838 if (AppGlobals.getPackageManager()
11839 .resolveContentProvider(name, 0 /*flags*/, userId) == null) { //针对instant app
11840 return null;
11841 }
11842 } catch (RemoteException e) {
11843 }
11844
11845 final long origId = Binder.clearCallingIdentity();
11846
11847 checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
11848
11849 // In this case the provider instance already exists, so we can
11850 // return it right away.
//区别与客户端的incProviderRefLocked,incProviderRefLocked是增加客户端和AMS中保存的引用计数
//incProviderCountLocked是增加AMS中代表客户端的ContentProviderConnection的引用计数,并返回相应的ContentProviderConnection
11851 conn = incProviderCountLocked(r, cpr, token, stable);
11852 if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
11853 if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
11854 // If this is a perceptible app accessing the provider,
11855 // make sure to count it as being accessed and thus
11856 // back up on the LRU list. This is good because
11857 // content providers are often expensive to start.
//更新进程优先级
11858 checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
11859 updateLruProcessLocked(cpr.proc, false, null);
11860 checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
11861 }
11862 }
11863
11864 checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
11865 final int verifiedAdj = cpr.proc.verifiedAdj;
11866 boolean success = updateOomAdjLocked(cpr.proc, true);
11867 // XXX things have changed so updateOomAdjLocked doesn't actually tell us
11868 // if the process has been successfully adjusted. So to reduce races with
11869 // it, we will check whether the process still exists. Note that this doesn't
11870 // completely get rid of races with LMK killing the process, but should make
11871 // them much smaller.
11872 if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
11873 success = false;
11874 }
11875 maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
11876 checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
11877 if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
11878 // NOTE: there is still a race here where a signal could be
11879 // pending on the process even though we managed to update its
11880 // adj level. Not sure what to do about this, but at least
11881 // the race is now smaller.
11882 if (!success) {//服务端被杀,做相关清理工作
11883 // Uh oh... it looks like the provider's process
11884 // has been killed on us. We need to wait for a new
11885 // process to be started, and make sure its death
11886 // doesn't kill our process.
11887 Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
11888 + " is crashing; detaching " + r);
11889 boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
11890 checkTime(startTime, "getContentProviderImpl: before appDied");
11891 appDiedLocked(cpr.proc);
11892 checkTime(startTime, "getContentProviderImpl: after appDied");
11893 if (!lastRef) { //lastRef = false代表客户端未完全断开
11894 // This wasn't the last ref our process had on
11895 // the provider... we have now been killed, bail.
11896 return null;
11897 }
11898 providerRunning = false;
11899 conn = null;
11900 } else {
11901 cpr.proc.verifiedAdj = cpr.proc.setAdj;
11902 }
11903
11904 Binder.restoreCallingIdentity(origId);
11905 }
11906
11907 if (!providerRunning) {
11908 try {
11909 checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
11910 cpi = AppGlobals.getPackageManager().
11911 resolveContentProvider(name,
11912 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
//根据authority,获取ProviderInfo对象
11913 checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");
11914 } catch (RemoteException ex) {
11915 }
11916 if (cpi == null) {
11917 return null;
11918 }
11919 // If the provider is a singleton AND
11920 // (it's a call within the same user || the provider is a
11921 // privileged app)
11922 // Then allow connecting to the singleton provider
11923 boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
11924 cpi.name, cpi.flags)
11925
11926 // && isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
11927 && isValidSingletonCall(r.uid, cpi.applicationInfo.uid)
11928 || ActivityManagerServiceInjector.shouldCrossXSpace(cpi.applicationInfo.packageName, userId);
11929 // END
11930 if (singleton) {
11931 userId = UserHandle.USER_SYSTEM;
11932 }
11933 cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
11934 checkTime(startTime, "getContentProviderImpl: got app info for user");
11935
11936 String msg;
11937 checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
11938 if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
11939 != null) {
11940 throw new SecurityException(msg);
11941 }
11942 checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
11943
11944 if (!mProcessesReady
11945 && !cpi.processName.equals("system")) {
11946 // If this content provider does not run in the system
11947 // process, and the system is not yet ready to run other
11948 // processes, then fail fast instead of hanging.
11950 // throw new IllegalArgumentException(
11951 // "Attempt to launch content provider before system ready";
11952 throw new IllegalArgumentException(
11953 "Attempt to launch content provider " + name + " before system ready, By app " + cpi.applicationInfo.packageName);
11955 }
11956
11957 // Make sure that the user who owns this provider is running. If not,
11958 // we don't want to allow it to run.
11959 if (!mUserController.isUserRunningLocked(userId, 0)) {
11960 Slog.w(TAG, "Unable to launch app "
11961 + cpi.applicationInfo.packageName + "/"
11962 + cpi.applicationInfo.uid + " for provider "
11963 + name + ": user " + userId + " is stopped");
11964 return null;
11965 }
11966
11967 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
11968 checkTime(startTime, "getContentProviderImpl: before getProviderByClass");
11969 cpr = mProviderMap.getProviderByClass(comp, userId); //通过cpi查找cpr
11970 checkTime(startTime, "getContentProviderImpl: after getProviderByClass");
11971 final boolean firstClass = cpr == null; //第一次
11972 if (firstClass) {
11973 final long ident = Binder.clearCallingIdentity();
11974
11975 // If permissions need a review before any of the app components can run,
11976 // we return no provider and launch a review activity if the calling app
11977 // is in the foreground.
11978 if (mPermissionReviewRequired) {
11979 if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
11980 return null;
11981 }
11982 }
11983
11984 try {
11985 checkTime(startTime, "getContentProviderImpl: before getApplicationInfo");
11986 ApplicationInfo ai =
11987 AppGlobals.getPackageManager().
11988 getApplicationInfo(
11989 cpi.applicationInfo.packageName,
11990 STOCK_PM_FLAGS, userId);
11991 checkTime(startTime, "getContentProviderImpl: after getApplicationInfo");
11992 if (ai == null) {
11993 Slog.w(TAG, "No package info for content provider "
11994 + cpi.name);
11995 return null;
11996 }
11997 ai = getAppInfoForUser(ai, userId);
11998 cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
//创建 ContentProviderRecord
11999 } catch (RemoteException ex) {
12000 // pm is in same process, this will never happen.
12001 } finally {
12002 Binder.restoreCallingIdentity(ident);
12003 }
12004 }
12005
12006 checkTime(startTime, "getContentProviderImpl: now have ContentProviderRecord");
12007
12008 if (r != null && cpr.canRunHere(r)) {
//当允许运行在调用者进程且ProcessRecord不为空,则直接返回
12009 // If this is a multiprocess provider, then just return its
12010 // info and allow the caller to instantiate it. Only do
12011 // this if the provider is the same user as the caller's
12012 // process, or can run as root (so can be in any process).
12013 return cpr.newHolder(null);
12014 }
12015
12016 if (DEBUG_PROVIDER) Slog.w(TAG_PROVIDER, "LAUNCHING REMOTE PROVIDER (myuid "
12017 + (r != null ? r.uid : null) + " pruid " + cpr.appInfo.uid + "): "
12018 + cpr.info.name + " callers=" + Debug.getCallers(6));
12019
12020 // This is single process, and our app is now connecting to it.
12021 // See if we are already in the process of launching this
12022 // provider.
12023 final int N = mLaunchingProviders.size();
12024 int i;
12025 for (i = 0; i < N; i++) {
12026 if (mLaunchingProviders.get(i) == cpr) {
12027 break;//从mLaunchingProviders中查询是否存在该cpr
12028 }
12029 }
12030
12031 // If the provider is not already being launched, then get it
12032 // started.
//当provider并没有处于mLaunchingProviders队列,则启动它
12033 if (i >= N) {
12034 final long origId = Binder.clearCallingIdentity();
12035
12036 try {
12037 // Content provider is now in use, its package can't be stopped.
12038 try {
12039 checkTime(startTime, "getContentProviderImpl: before set stopped state");
12040 AppGlobals.getPackageManager().setPackageStoppedState(
12041 cpr.appInfo.packageName, false, userId);
12042 checkTime(startTime, "getContentProviderImpl: after set stopped state");
12043 } catch (RemoteException e) {
12044 } catch (IllegalArgumentException e) {
12045 Slog.w(TAG, "Failed trying to unstop package "
12046 + cpr.appInfo.packageName + ": " + e);
12047 }
12048
12049 // Use existing process if already started
12050 checkTime(startTime, "getContentProviderImpl: looking for process record");
12051 ProcessRecord proc = getProcessRecordLocked(
12052 cpi.processName, cpr.appInfo.uid, false);
12053 if (proc != null && proc.thread != null && !proc.killed) {
//当ProcessRecord不为空,则加入到pubProviders,并开始安装provider
12054 if (DEBUG_PROVIDER) Slog.d(TAG_PROVIDER,
12055 "Installing in existing process " + proc);
12056 if (!proc.pubProviders.containsKey(cpi.name)) {
12057 checkTime(startTime, "getContentProviderImpl: scheduling install");
//服务端进程保存相应的ContentProviderRecord
12058 proc.pubProviders.put(cpi.name, cpr);
12059 try {
12060 proc.thread.scheduleInstallProvider(cpi); //包括ContentProvider的install和publish,此时proc代表服务端(宿主进程的ProcessRecord)
12061 } catch (RemoteException e) {
12062 }
12063 }
12064 } else {
12066 Binder.restoreCallingIdentity(origId);
12067 String callerPackage;
12068 if (r != null && r.info != null) {
12069 callerPackage = r.info.packageName;
12070 } else {
12071 int callingPid = Binder.getCallingPid();
12072 callerPackage = ExtraActivityManagerService.getPackageNameByPid(callingPid);
12073 }
12074 try {
12075 if (!ExtraActivityManagerService.checkRunningCompatibility(mContext, this, caller, cpr, userId, mSystemReady)) {
12076 return null;
12077 }
12078 } finally {
12079 // Notice: assert origId == Binder.clearCallingIdentity()
12080 Binder.clearCallingIdentity();
12081 }
12083 checkTime(startTime, "getContentProviderImpl: before start process");
//否则启动ContentProvider所在进程
//进程启动完毕后,创建provider的操作将会在ActivityThread初始化时进行
12084 proc = startProcessLocked(cpi.processName,
12085 cpr.appInfo, false, 0, "content provider",
12086 new ComponentName(cpi.applicationInfo.packageName,
12088 //cpi.name), false, false, false);
12089 cpi.name), false, false, false, callerPackage);
12090 checkTime(startTime, "getContentProviderImpl: after start process");
12091 if (proc == null) {
12092 Slog.w(TAG, "Unable to launch app "
12093 + cpi.applicationInfo.packageName + "/"
12094 + cpi.applicationInfo.uid + " for provider "
12095 + name + ": process is bad");
12096 return null;
12097 }
12098 }
12099 cpr.launchingApp = proc;
12100 mLaunchingProviders.add(cpr);
//启动进程时将ContentProviderRecord放在mLaunchingProviders队列中,类似bringUpServiceLocked中的mPendingServices
12101 } finally {
12102 Binder.restoreCallingIdentity(origId);
12103 }
12104 }
12105
12106 checkTime(startTime, "getContentProviderImpl: updating data structures");
12107
12108 // Make sure the provider is published (the same provider class
12109 // may be published under multiple names).
12110 if (firstClass) {
12111 mProviderMap.putProviderByClass(comp, cpr);
12112 }
12113
12114 mProviderMap.putProviderByName(name, cpr);
//保存创建的ContentProviderRecord
12115 conn = incProviderCountLocked(r, cpr, token, stable);
//对相应的代表客户端+查询provider的结构ContentProviderConnection增加引用计数并保存
12116 if (conn != null) {
12117 conn.waiting = true;
12118 }
12119 }
12120 checkTime(startTime, "getContentProviderImpl: done!");
12121
12122 grantEphemeralAccessLocked(userId, null /*intent*/,
12123 cpi.applicationInfo.uid, UserHandle.getAppId(Binder.getCallingUid()));
12124 }
12125
12126 // Wait for the provider to be published...
12127 synchronized (cpr) {
12128 while (cpr.provider == null) {
12129 if (cpr.launchingApp == null) {
12130 Slog.w(TAG, "Unable to launch app "
12131 + cpi.applicationInfo.packageName + "/"
12132 + cpi.applicationInfo.uid + " for provider "
12133 + name + ": launching app became null");
12134 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
12135 UserHandle.getUserId(cpi.applicationInfo.uid),
12136 cpi.applicationInfo.packageName,
12137 cpi.applicationInfo.uid, name);
12138 return null;
12139 }
12140 try {
12141 if (DEBUG_MU) Slog.v(TAG_MU,
12142 "Waiting to start provider " + cpr
12143 + " launchingApp=" + cpr.launchingApp);
12144 if (conn != null) {
12145 conn.waiting = true;
12146 }
//等待provider发布完成,客户端进程的操作ContentProvider的查询线程,一直在wait,等待
provider被publish或者由于进程被杀/启动超时等原因被remove掉
12147 cpr.wait();
12148 } catch (InterruptedException ex) {
12149 } finally {
12150 if (conn != null) {
12151 conn.waiting = false;
12152 }
12153 }
12154 }
12155 }
12156 return cpr != null ? cpr.newHolder(conn) : null;
12157 }
主要也是启动宿主进程中的ContentProvider,并将其binder proxy传递AMS中保存,这样后续客户端进程进行重复操作时,就可以
通过binder proxy(binder驱动)直接调用ContentProvider实例的override方法,类似与bindService,ServiceConnection中的onServiceConnected
中通过Service的Ibinder来调用Service实例的override方法
同样也有三种情况(类似于bringUpServiceLocked)
1.目标ContentProvider已经运行的情况,只增加AMS中ContentProviderConnection的引用计数
2.目标ContentProvider尚未启动,但所在进程已启动(类似realStartServiceLocked),在宿主进程中创建ContentProvider实例,并将binder proxy publish
3.目标宿主进程尚未启动,启动该进程,将代表ContentProvider的数据结构ContentProviderRecord添加到 mLaunchingProviders.add(cpr);中,进程启动
完成后再走install Provider的逻辑,startProcessLocked到 ActivityThread.main再到bindApplication,最后到install Provider
参考:
从源码角度看AMS.startProcessLocked
Application创建流程分析
理解ContentProvider原理
4.等待ContentProvider publish完成
ActivityManagerService#incProviderCountLocked
11659 ContentProviderConnection incProviderCountLocked(ProcessRecord r,
11660 final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
11661 if (r != null) {
11662 for (int i=0; i<r.conProviders.size(); i++) {
//final ArrayList<ContentProviderConnection> conProviders = new ArrayList<>(); 客户端保存的 ContentProviderConnection序列
11663 ContentProviderConnection conn = r.conProviders.get(i);
11664 if (conn.provider == cpr) {
//取出provider符合ContentProviderConnection,增加其中的引用计数
11665 if (DEBUG_PROVIDER) Slog.v(TAG_PROVIDER,
11666 "Adding provider requested by "
11667 + r.processName + " from process "
11668 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
11669 + " scnt=" + conn.stableCount + " uscnt=" + conn.unstableCount);
11670 if (stable) {
11671 conn.stableCount++;
11672 conn.numStableIncs++;
11673 } else {
11674 conn.unstableCount++;
11675 conn.numUnstableIncs++;
11676 }
11677 return conn;
11678 }
11679 }
//首次,还没有在ProcessRecord中保存相应的ContentProviderConnection,创建一个
11680 ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
//引用计数赋初始值
11681 if (stable) {
11682 conn.stableCount = 1;
11683 conn.numStableIncs = 1;
11684 } else {
11685 conn.unstableCount = 1;
11686 conn.numUnstableIncs = 1;
11687 }
11688 cpr.connections.add(conn);
11689 r.conProviders.add(conn);
//将创建的ContentProviderConnection添加到代表客户端的ProcessRecord,以及代表服务端的ContentProviderRecord.connections中
11690 startAssociationLocked(r.uid, r.processName, r.curProcState,
11691 cpr.uid, cpr.name, cpr.info.processName);
11692 return conn;
11693 }
11694 cpr.addExternalProcessHandleLocked(externalProcessToken);
11695 return null;
11696 }
更新content provider的宿主进程时,若其被杀,返回false
23124 private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
23125 ProcessRecord TOP_APP, boolean doingAll, long now) {
23126 if (app.thread == null) {
23127 return false;
23128 }
23129
23130 computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
23131
23132 return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
23133 }
当更新宿主进程失败时,宿主进程被杀,则要做相应的清理工作
清理相应的ContentProviderConnection中的引用计数,引用计数-1,当stable和unstable的引用计数均为0时,将ContentProviderConnection也从服务端和客户端的AMS数据结构中清理掉
ActivityManagerService#decProviderCountLocked
11698 boolean decProviderCountLocked(ContentProviderConnection conn,
11699 ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
11700 if (conn != null) {
11701 cpr = conn.provider;
11702 if (DEBUG_PROVIDER) Slog.v(TAG_PROVIDER,
11703 "Removing provider requested by "
11704 + conn.client.processName + " from process "
11705 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
11706 + " scnt=" + conn.stableCount + " uscnt=" + conn.unstableCount);
11707 if (stable) {
11708 conn.stableCount--;
11709 } else {
11710 conn.unstableCount--;
11711 }
//减少引用计数
11712 if (conn.stableCount == 0 && conn.unstableCount == 0) {
//当stable和unstable的引用计数都为0时,remove相应的ContentProviderConnection
11713 cpr.connections.remove(conn);
11714 conn.client.conProviders.remove(conn);
11715 if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
11716 // The client is more important than last activity -- note the time this
11717 // is happening, so we keep the old provider process around a bit as last
11718 // activity to avoid thrashing it.
11719 if (cpr.proc != null) {
11720 cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
11721 }
11722 }
11723 stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name);
11724 return true;
11725 }
11726 return false;
11727 }
11728 cpr.removeExternalProcessHandleLocked(externalProcessToken);
11729 return false;
11730 }
ContentProvider_query.png