美文网首页
Android 获取Provider对象的过程分析

Android 获取Provider对象的过程分析

作者: 一个要长胖的瘦子 | 来源:发表于2018-04-28 17:46 被阅读0次

本文是目的是在记录自己查找Provider的执行过程的分析过程,方便后续查阅

通常我们使用Provider的方式,都是通过getContentResolver().call(Uri ...) 这个种方式,Uri 去索引所查找的Provider,执行对应的Provider.

那我们先从getContentResolver.call看起,为什么能找到Provider.
getContentResolverm()返回的是mContentResolver对象。这mContentResolver实际上是 ApplicationContentResolver实例。所以call方法也就是ApplicationContentResolver的call方法。继续搜索 ApplicationContentResolver extends ContentResolver,所以Call来自ContentResolver。

public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
        @Nullable String arg, @Nullable Bundle extras) {
    Preconditions.checkNotNull(uri, "uri");
    Preconditions.checkNotNull(method, "method");
    IContentProvider provider = acquireProvider(uri);
    if (provider == null) {
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
    try {
        final Bundle res = provider.call(mPackageName, method, arg, extras);
        Bundle.setDefusable(res, true);
        return res;
    } catch (RemoteException e) {
        // Arbitrary and not worth documenting, as Activity
        // Manager will kill this process shortly anyway.
        return null;
    } finally {
        releaseProvider(provider);
    }
}

看call方法中首先通过acquireProvider(uri)获得了一个Provider对象。分析acquireProvider方法。在ApplicationContentResolver的acquireProvider方法如下

    @Override
    protected IContentProvider acquireProvider(Context context, String auth) {
        return mMainThread.acquireProvider(context,
                ContentProvider.getAuthorityWithoutUserId(auth),
                resolveUserIdFromAuthority(auth), true);
    }

继续查找ActivityThread的acquireProvider。

public final IContentProvider acquireProvider(
        Context c, String auth, int userId, boolean stable) {
    final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
    if (provider != null) {
        return provider;
    }

    // There is a possible race here.  Another thread may try to acquire
    // the same provider at the same time.  When this happens, we want to ensure
    // that the first one wins.
    // Note that we cannot hold the lock while acquiring and installing the
    // provider since it might take a long time to run and it could also potentially
    // be re-entrant in the case where the provider is in the same process.
    IActivityManager.ContentProviderHolder holder = null;
    try {
        holder = ActivityManagerNative.getDefault().getContentProvider(
                getApplicationThread(), auth, userId, stable);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    if (holder == null) {
        Slog.e(TAG, "Failed to find provider info for " + auth);
        return null;
    }

    // Install provider will increment the reference count for us, and break
    // any ties in the race.
    holder = installProvider(c, holder, holder.info,
            true /*noisy*/, holder.noReleaseNeeded, stable);
    return holder.provider;
}

首先调用acquireExistingProvider去根据uri查询已存在的provider.

public final IContentProvider acquireExistingProvider(
        Context c, String auth, int userId, boolean stable) {
    synchronized (mProviderMap) {
        final ProviderKey key = new ProviderKey(auth, userId);
        final ProviderClientRecord pr = mProviderMap.get(key);
        if (pr == null) {
            return null;
        }

        IContentProvider provider = pr.mProvider;
        IBinder jBinder = provider.asBinder();
        //.....

        // Only increment the ref count if we have one.  If we don't then the
        // provider is not reference counted and never needs to be released.
        ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
        if (prc != null) {
            incProviderRefLocked(prc, stable);
        }
        return provider;
    }
}

从这里看到有一个缓存mProviderMap,查看缓存Map是否保存已经有的Provider对象。
下面mProviderRefCountMap保存着Provider 的引用计数(个人理解)
之后会分析mProviderMap是如何添加的。

如果查找的Provider没在Map中,会ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable)。 会通过进程间通信,去通过AMS服务查找。AMS的getContentProviderImpl方法非常长,我只记录重点。

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId) {
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;

    synchronized(this) {
        long startTime = SystemClock.uptimeMillis();

        //调用Check略过...

        // First check if this content provider has been published...
        cpr = mProviderMap.getProviderByName(name, userId);
        //同样有个Map保存Provider对象,且通过authority查找。
        
        
        // If that didn't work, check if it exists for user 0 and then
        // verify that it's a singleton provider before using it.
        if (cpr == null && userId != UserHandle.USER_SYSTEM) {
            cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
            if (cpr != null) {
                cpi = cpr.info;
                if (isSingleton(cpi.processName, cpi.applicationInfo,
                        cpi.name, cpi.flags)
                        && isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
                    userId = UserHandle.USER_SYSTEM;
                    checkCrossUser = false;
                } else {
                    cpr = null;
                    cpi = null;
                }
            }
        }

        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
        if (providerRunning) {
            cpi = cpr.info;
            String msg;
            checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
            if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
                    != null) {
                throw new SecurityException(msg);
            }
            checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");

            if (r != null && cpr.canRunHere(r)) {
                // This provider has been published or is in the process
                // of being published...  but it is also allowed to run
                // in the caller's process, so don't make a connection
                // and just let the caller instantiate its own instance.
                ContentProviderHolder holder = cpr.newHolder(null);
                // don't give caller the provider object, it needs
                // to make its own.
                holder.provider = null;
                return holder;
            }

            final long origId = Binder.clearCallingIdentity();

            checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");

            // In this case the provider instance already exists, so we can
            // return it right away.
            conn = incProviderCountLocked(r, cpr, token, stable);
            if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
                if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                    // If this is a perceptible app accessing the provider,
                    // make sure to count it as being accessed and thus
                    // back up on the LRU list.  This is good because
                    // content providers are often expensive to start.
                    checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
                    updateLruProcessLocked(cpr.proc, false, null);
                    checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
                }
            }

            checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
            final int verifiedAdj = cpr.proc.verifiedAdj;
            boolean success = updateOomAdjLocked(cpr.proc);
            // XXX things have changed so updateOomAdjLocked doesn't actually tell us
            // if the process has been successfully adjusted.  So to reduce races with
            // it, we will check whether the process still exists.  Note that this doesn't
            // completely get rid of races with LMK killing the process, but should make
            // them much smaller.
            if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
                success = false;
            }
            maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
            checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
            if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
            // NOTE: there is still a race here where a signal could be
            // pending on the process even though we managed to update its
            // adj level.  Not sure what to do about this, but at least
            // the race is now smaller.
            if (!success) {
                // Uh oh...  it looks like the provider's process
                // has been killed on us.  We need to wait for a new
                // process to be started, and make sure its death
                // doesn't kill our process.
                Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
                        + " is crashing; detaching " + r);
                boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
                checkTime(startTime, "getContentProviderImpl: before appDied");
                appDiedLocked(cpr.proc);
                checkTime(startTime, "getContentProviderImpl: after appDied");
                if (!lastRef) {
                    // This wasn't the last ref our process had on
                    // the provider...  we have now been killed, bail.
                    return null;
                }
                providerRunning = false;
                conn = null;
            } else {
                cpr.proc.verifiedAdj = cpr.proc.setAdj;
            }

            Binder.restoreCallingIdentity(origId);
        }

        if (!providerRunning) {
            try {
                checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
                cpi = AppGlobals.getPackageManager().
                    resolveContentProvider(name,
                        STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
                //如果Provider上面没有查到,会通过PMS去查找ProviderInfo        
                        
                checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");
            } catch (RemoteException ex) {
            }
            if (cpi == null) {
                return null;
            }
            // If the provider is a singleton AND
            // (it's a call within the same user || the provider is a
            // privileged app)
            // Then allow connecting to the singleton provider
            boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
                    cpi.name, cpi.flags)
                    && isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
            if (singleton) {
                userId = UserHandle.USER_SYSTEM;
            }
            cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
            checkTime(startTime, "getContentProviderImpl: got app info for user");

            String msg;
            checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
            if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
                    != null) {
                throw new SecurityException(msg);
            }
            checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");

            if (!mProcessesReady
                    && !cpi.processName.equals("system")) {
                // If this content provider does not run in the system
                // process, and the system is not yet ready to run other
                // processes, then fail fast instead of hanging.
                throw new IllegalArgumentException(
                        "Attempt to launch content provider before system ready");
            }

            // Make sure that the user who owns this provider is running.  If not,
            // we don't want to allow it to run.
            if (!mUserController.isUserRunningLocked(userId, 0)) {
                Slog.w(TAG, "Unable to launch app "
                        + cpi.applicationInfo.packageName + "/"
                        + cpi.applicationInfo.uid + " for provider "
                        + name + ": user " + userId + " is stopped");
                return null;
            }

            ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
            checkTime(startTime, "getContentProviderImpl: before getProviderByClass");
            cpr = mProviderMap.getProviderByClass(comp, userId);
            //根据上面查找到Provider组件信息,去找Provider对象。
            checkTime(startTime, "getContentProviderImpl: after getProviderByClass");
            final boolean firstClass = cpr == null;
            //没找到说明第一次启动
            if (firstClass) {
                final long ident = Binder.clearCallingIdentity();

                // If permissions need a review before any of the app components can run,
                // we return no provider and launch a review activity if the calling app
                // is in the foreground.
                if (Build.PERMISSIONS_REVIEW_REQUIRED) {
                    if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
                        return null;
                    }
                }

                try {
                    checkTime(startTime, "getContentProviderImpl: before getApplicationInfo");
                    ApplicationInfo ai =
                        AppGlobals.getPackageManager().
                            getApplicationInfo(
                                    cpi.applicationInfo.packageName,
                                    STOCK_PM_FLAGS, userId);
                    checkTime(startTime, "getContentProviderImpl: after getApplicationInfo");
                    if (ai == null) {
                        Slog.w(TAG, "No package info for content provider "
                                + cpi.name);
                        return null;
                    }
                    ai = getAppInfoForUser(ai, userId);
                    cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton); //创建ContentProviderRecord对象
                } catch (RemoteException ex) {
                    // pm is in same process, this will never happen.
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }

            checkTime(startTime, "getContentProviderImpl: now have ContentProviderRecord");

            if (r != null && cpr.canRunHere(r)) {
                // If this is a multiprocess provider, then just return its
                // info and allow the caller to instantiate it.  Only do
                // this if the provider is the same user as the caller's
                // process, or can run as root (so can be in any process).
                return cpr.newHolder(null);
            }

            if (DEBUG_PROVIDER) Slog.w(TAG_PROVIDER, "LAUNCHING REMOTE PROVIDER (myuid "
                        + (r != null ? r.uid : null) + " pruid " + cpr.appInfo.uid + "): "
                        + cpr.info.name + " callers=" + Debug.getCallers(6));

            // This is single process, and our app is now connecting to it.
            // See if we are already in the process of launching this
            // provider.
            final int N = mLaunchingProviders.size();
            int i;
            for (i = 0; i < N; i++) {
                if (mLaunchingProviders.get(i) == cpr) {
                    break;
                }
            }

            // If the provider is not already being launched, then get it
            // started.
            if (i >= N) {
                final long origId = Binder.clearCallingIdentity();

                try {
                    // Content provider is now in use, its package can't be stopped.
                    try {
                        checkTime(startTime, "getContentProviderImpl: before set stopped state");
                        AppGlobals.getPackageManager().setPackageStoppedState(
                                cpr.appInfo.packageName, false, userId);
                        checkTime(startTime, "getContentProviderImpl: after set stopped state");
                    } catch (RemoteException e) {
                    } catch (IllegalArgumentException e) {
                        Slog.w(TAG, "Failed trying to unstop package "
                                + cpr.appInfo.packageName + ": " + e);
                    }

                    // Use existing process if already started
                    checkTime(startTime, "getContentProviderImpl: looking for process record");
                    ProcessRecord proc = getProcessRecordLocked(
                            cpi.processName, cpr.appInfo.uid, false);
                    if (proc != null && proc.thread != null && !proc.killed) {
                        if (DEBUG_PROVIDER) Slog.d(TAG_PROVIDER,
                                "Installing in existing process " + proc);
                        if (!proc.pubProviders.containsKey(cpi.name)) {
                            checkTime(startTime, "getContentProviderImpl: scheduling install");
                            proc.pubProviders.put(cpi.name, cpr);
                            try {
                                proc.thread.scheduleInstallProvider(cpi);
                            } catch (RemoteException e) {
                            }
                        }
                    } else {
                        checkTime(startTime, "getContentProviderImpl: before start process");
                        proc = startProcessLocked(cpi.processName,
                                cpr.appInfo, false, 0, "content provider",
                                new ComponentName(cpi.applicationInfo.packageName,
                                        cpi.name), false, false, false);
                        checkTime(startTime, "getContentProviderImpl: after start process");
                        if (proc == null) {
                            Slog.w(TAG, "Unable to launch app "
                                    + cpi.applicationInfo.packageName + "/"
                                    + cpi.applicationInfo.uid + " for provider "
                                    + name + ": process is bad");
                            return null;
                        }
                    }
                    cpr.launchingApp = proc;
                    mLaunchingProviders.add(cpr);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
            }

            checkTime(startTime, "getContentProviderImpl: updating data structures");

            // Make sure the provider is published (the same provider class
            // may be published under multiple names).
            if (firstClass) {
                mProviderMap.putProviderByClass(comp, cpr);
            }

            mProviderMap.putProviderByName(name, cpr);
            //把刚才Provider保存到Map中。
            conn = incProviderCountLocked(r, cpr, token, stable);
            if (conn != null) {
                conn.waiting = true;
            }
        }
        checkTime(startTime, "getContentProviderImpl: done!");
    }

    // Wait for the provider to be published...
    synchronized (cpr) {
        while (cpr.provider == null) {
            if (cpr.launchingApp == null) {
                Slog.w(TAG, "Unable to launch app "
                        + cpi.applicationInfo.packageName + "/"
                        + cpi.applicationInfo.uid + " for provider "
                        + name + ": launching app became null");
                EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
                        UserHandle.getUserId(cpi.applicationInfo.uid),
                        cpi.applicationInfo.packageName,
                        cpi.applicationInfo.uid, name);
                return null;
            }
            try {
                if (DEBUG_MU) Slog.v(TAG_MU,
                        "Waiting to start provider " + cpr
                        + " launchingApp=" + cpr.launchingApp);
                if (conn != null) {
                    conn.waiting = true;
                }
                cpr.wait();
            } catch (InterruptedException ex) {
            } finally {
                if (conn != null) {
                    conn.waiting = false;
                }
            }
        }
    }
    return cpr != null ? cpr.newHolder(conn) : null;
}

则返回ContentResolver的acquireProvider中执行installProvider。

private IActivityManager.ContentProviderHolder installProvider(Context context,
            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
        boolean noisy, boolean noReleaseNeeded, boolean stable) {
    ContentProvider localProvider = null;
    IContentProvider provider;
    if (holder == null || holder.provider == null) {
        //...
        //当Holder为空时,意味着要从本地创建Holder
        Context c = null;
        ApplicationInfo ai = info.applicationInfo;
        if (context.getPackageName().equals(ai.packageName)) {
            c = context;
        } else if (mInitialApplication != null &&
                mInitialApplication.getPackageName().equals(ai.packageName)) {
            c = mInitialApplication;
        } else {
            try {
                c = context.createPackageContext(ai.packageName,
                        Context.CONTEXT_INCLUDE_CODE);
            } catch (PackageManager.NameNotFoundException e) {
                // Ignore
            }
        }
        //...
        try {
            final java.lang.ClassLoader cl = c.getClassLoader();
            localProvider = (ContentProvider)cl.
                loadClass(info.name).newInstance();
            provider = localProvider.getIContentProvider();//拿到Provider对象
            if (provider == null) {
                Slog.e(TAG, "Failed to instantiate class " +
                      info.name + " from sourceDir " +
                      info.applicationInfo.sourceDir);
                return null;
            }
            if (DEBUG_PROVIDER) Slog.v(
                TAG, "Instantiating local provider " + info.name);
            // XXX Need to create the correct context for this provider.
            localProvider.attachInfo(c, info);
        } catch (java.lang.Exception e) {
            return null;
        }
    } else {
        provider = holder.provider; //我们从AMS中已经拿到holder,且带有Provider对象
        //上面是Application启动时安装Provider
    }

    IActivityManager.ContentProviderHolder retHolder;

    synchronized (mProviderMap) {
        if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
                + " / " + info.name);
        IBinder jBinder = provider.asBinder();
        if (localProvider != null) {
            //如果从本地创建Provider对象情况
            ComponentName cname = new ComponentName(info.packageName, info.name);
            ProviderClientRecord pr = mLocalProvidersByName.get(cname);
            if (pr != null) {
                if (DEBUG_PROVIDER) {
                    Slog.v(TAG, "installProvider: lost the race, "
                            + "using existing local provider");
                }
                provider = pr.mProvider;
            } else {
                holder = new IActivityManager.ContentProviderHolder(info);
                holder.provider = provider;
                holder.noReleaseNeeded = true;
                //生成Holder对象
                pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                // 生成Recoard对象
                mLocalProviders.put(jBinder, pr);
                mLocalProvidersByName.put(cname, pr);
            }
            retHolder = pr.mHolder;
        } else {
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
            if (prc != null) {
                if (DEBUG_PROVIDER) {
                    Slog.v(TAG, "installProvider: lost the race, updating ref count");
                }
                // We need to transfer our new reference to the existing
                // ref count, releasing the old one...  but only if
                // release is needed (that is, it is not running in the
                // system process).
                if (!noReleaseNeeded) {
                    incProviderRefLocked(prc, stable);
                    try {
                        ActivityManagerNative.getDefault().removeContentProvider(
                                holder.connection, stable);
                    } catch (RemoteException e) {
                        //do nothing content provider object is dead any way
                    }
                }
            } else {
                //不是本地对象,只需要创建Record对象。
                ProviderClientRecord client = installProviderAuthoritiesLocked(
                        provider, localProvider, holder);
                if (noReleaseNeeded) {
                    prc = new ProviderRefCount(holder, client, 1000, 1000);
                } else {
                    prc = stable
                            ? new ProviderRefCount(holder, client, 1, 0)
                            : new ProviderRefCount(holder, client, 0, 1);
                }
                mProviderRefCountMap.put(jBinder, prc);
            }
            retHolder = prc.holder;
        }
    }

    return retHolder;
}


private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
        ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
    final String auths[] = holder.info.authority.split(";");
    final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);

    final ProviderClientRecord pcr = new ProviderClientRecord(
            auths, provider, localProvider, holder);
    for (String auth : auths) {
        final ProviderKey key = new ProviderKey(auth, userId);
        final ProviderClientRecord existing = mProviderMap.get(key);
        if (existing != null) {
            Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
                    + " already published as " + auth);
        } else {
            mProviderMap.put(key, pcr); //保存ProviderClientRecord对象
        }
    }
    return pcr;
}

acquireProvider函数在最后返回Provider的对象。
则在Call方法中可以调用对应Provider的Call.

回想之前ProviderMap是何时保存的。

我们从应用启动时的installProvider说起。
在应用创建Application时,handleApplication中,创建完Application对象之后会进行Provider的install 过程。

installContentProviders(app, data.providers);

private void installContentProviders(
        Context context, List<ProviderInfo> providers) {
    final ArrayList<IActivityManager.ContentProviderHolder> results =
        new ArrayList<IActivityManager.ContentProviderHolder>();

    for (ProviderInfo cpi : providers) {
        if (DEBUG_PROVIDER) {
            StringBuilder buf = new StringBuilder(128);
            buf.append("Pub ");
            buf.append(cpi.authority);
            buf.append(": ");
            buf.append(cpi.name);
            Log.i(TAG, buf.toString());
        }
        IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
                //上面已经分析过installProvider
        if (cph != null) {
            cph.noReleaseNeeded = true;
            results.add(cph);
        }
    }

    try {
        ActivityManagerNative.getDefault().publishContentProviders(
            getApplicationThread(), results);
            //向系统中注册自己的Provider
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

分析publishContentProviders,参数results存放上面Holder对象。

public final void publishContentProviders(IApplicationThread caller,
        List<ContentProviderHolder> providers) {
    if (providers == null) {
        return;
    }

    enforceNotIsolatedCaller("publishContentProviders");
    synchronized (this) {
        //ProcessRecord里保存着一些组件信息
        final ProcessRecord r = getRecordForAppLocked(caller);
        //...

        final long origId = Binder.clearCallingIdentity();

        final int N = providers.size();
        for (int i = 0; i < N; i++) {
            ContentProviderHolder src = providers.get(i);
            if (src == null || src.info == null || src.provider == null) {
                continue;
            }
            //这个地方很关键,根据src.info.name也就是传入Provider的名字拿到cpr
            //下面是根据cpr的相关信息创建索引值来保存dst
            ContentProviderRecord dst = r.pubProviders.get(src.info.name);
            if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
            if (dst != null) {
                ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                mProviderMap.putProviderByClass(comp, dst);
                String names[] = dst.info.authority.split(";");
                for (int j = 0; j < names.length; j++) {
                    mProviderMap.putProviderByName(names[j], dst);
                }
                //mProviderMap 这里的map也就是之前查询时候的Map
                //.....
            }
        }

        Binder.restoreCallingIdentity(origId);
    }
}

由以上过程分析:
1.在应用启动过程中会将自己的provider进行install.
install会将Provider的Record和Holder会保存在本进程一份,然后还会发布到系统AMS去保存。
2.执行ContentResolver的方法时,先是通过查询本进程ProviderMap是否已经保存了Provider对象。查不到则通过AMS服务去获得Provider.

相关文章

网友评论

      本文标题:Android 获取Provider对象的过程分析

      本文链接:https://www.haomeiwen.com/subject/cbxnlftx.html