android之基础学习攻克

ContentProvider相关学习(1)-客户端query相

2018-12-12  本文已影响0人  weiinter105

以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

参考 从源码角度看ContentProvider

上一篇下一篇

猜你喜欢

热点阅读