• 0

  • 491

Android-ContentProvider源码解读

概述

博客链接

ContentProvider用于提供数据的统一访问格式,封装了底层的具体实现。对于数据的使用者来说,无需知晓数据的来源是数据库、本地文件或者网络等,使用者只需简单地使用ContentProvider提供的数据增删查改操作接口即可,基本使用可参考Android四大组件之ContentProvider

注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。

注:下面使用CR代表ContentResolver,CP代表ContentProvider,CPR代表ContentProviderRecord,AT代表ActivityThread,AMS代表ActivityManagerService。

ContextImpl.getContentResolver

class ContextImpl extends Context {
    private final ApplicationContentResolver mContentResolver;

    private ContextImpl(@NonNull ActivityThread mainThread/*...*/) {
        mContentResolver = new ApplicationContentResolver(this, mainThread);
    }

    @Override
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }
}
复制代码

CR.insert/delete/query/update

CR.insert

public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, @Nullable ContentValues values) {
    Preconditions.checkNotNull(url, "url");
    IContentProvider provider = acquireProvider(url);
    if (provider == null) {
        throw new IllegalArgumentException("Unknown URL " + url);
    }
    try {
        long startTime = SystemClock.uptimeMillis();
        Uri createdRow = provider.insert(mPackageName, url, values);
        long durationMillis = SystemClock.uptimeMillis() - startTime;
        return createdRow;
    } catch (RemoteException e) {
        return null;
    } finally {
        releaseProvider(provider);
    }
}
复制代码

通过调用acquireProvider()方法尝试获取provider,然后执行insert操作。

CR.delete

public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where, @Nullable String[] selectionArgs) {
    Preconditions.checkNotNull(url, "url");
    IContentProvider provider = acquireProvider(url);
    if (provider == null) {
        throw new IllegalArgumentException("Unknown URL " + url);
    }
    try {
        long startTime = SystemClock.uptimeMillis();
        int rowsDeleted = provider.delete(mPackageName, url, where, selectionArgs);
        long durationMillis = SystemClock.uptimeMillis() - startTime;
        return rowsDeleted;
    } catch (RemoteException e) {
        return -1;
    } finally {
        releaseProvider(provider);
    }
}
复制代码

通过调用acquireProvider()方法尝试获取provider,然后执行delete操作。

CR.query

ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(uri, null, null, null, null);

public abstract class ContentResolver {
    public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
            @Nullable String[] projection, @Nullable String selection,
            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return query(uri, projection, selection, selectionArgs, sortOrder, null);
    }

    public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
            @Nullable String[] projection, @Nullable String selection,
            @Nullable String[] selectionArgs, @Nullable String sortOrder,
            @Nullable CancellationSignal cancellationSignal) {
        Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder);
        return query(uri, projection, queryArgs, cancellationSignal);
    }

    public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
            @Nullable String[] projection, @Nullable Bundle queryArgs,
            @Nullable CancellationSignal cancellationSignal) {
        Preconditions.checkNotNull(uri, "uri");
        // 获取unstableProvider
        IContentProvider unstableProvider = acquireUnstableProvider(uri);
        if (unstableProvider == null) {
            return null;
        }
        IContentProvider stableProvider = null;
        Cursor qCursor = null;
        try {
            long startTime = SystemClock.uptimeMillis();
            try {
                // 执行查询
                qCursor = unstableProvider.query(mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
            } catch (DeadObjectException e) {
                // 远程进程死亡,处理unstableProvider死亡过程
                unstableProviderDied(unstableProvider);
                // unstableProvider死亡后,再创建stable类型的provider
                stableProvider = acquireProvider(uri);
                if (stableProvider == null) {
                    return null;
                }
                // 再次执行查询操作
                qCursor = stableProvider.query(mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
            }
            if (qCursor == null) {
                return null;
            }

            // 强制执行查询操作,可能会失败并抛出RuntimeException异常
            qCursor.getCount();
            // Wrap the cursor object into CursorWrapperInner object.
            final IContentProvider provider = (stableProvider != null) ? stableProvider : acquireProvider(uri);
            final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
            stableProvider = null;
            qCursor = null;
            return wrapper;
        } catch (RemoteException e) {
            return null;
        } finally {
            if (qCursor != null) {
                qCursor.close();
            }
            if (unstableProvider != null) {
                releaseUnstableProvider(unstableProvider);
            }
            if (stableProvider != null) {
                releaseProvider(stableProvider);
            }
        }
    }
}
复制代码

首先调用acquireUnstableProvider()方法尝试获取unstable的ContentProvider,然后执行query操作,如果query过程抛出DeadObjectException异常,即代表ContentProvider所在进程死亡,则通过acquireProvider()方法尝试获取stable的ContentProvider,然后接着执行query操作。

CR.update

public final int update(@RequiresPermission.Write @NonNull Uri uri, @Nullable ContentValues values,
        @Nullable String where, @Nullable String[] selectionArgs) {
    Preconditions.checkNotNull(uri, "uri");
    IContentProvider provider = acquireProvider(uri);
    if (provider == null) {
        throw new IllegalArgumentException("Unknown URI " + uri);
    }
    try {
        long startTime = SystemClock.uptimeMillis();
        int rowsUpdated = provider.update(mPackageName, uri, values, where, selectionArgs);
        long durationMillis = SystemClock.uptimeMillis() - startTime;
        return rowsUpdated;
    } catch (RemoteException e) {
        return -1;
    } finally {
        releaseProvider(provider);
    }
}
复制代码

通过调用acquireProvider()方法尝试获取provider,然后执行update操作。

CR.acquire(Unstable)Provider

public final IContentProvider acquireUnstableProvider(Uri uri) {
    if (!SCHEME_CONTENT.equals(uri.getScheme())) {
        return null;
    }
    String auth = uri.getAuthority();
    if (auth != null) {
        return acquireUnstableProvider(mContext, uri.getAuthority());
    }
    return null;
}

public final IContentProvider acquireProvider(Uri uri) {
    if (!SCHEME_CONTENT.equals(uri.getScheme())) {
        return null;
    }
    final String auth = uri.getAuthority();
    if (auth != null) {
        return acquireProvider(mContext, auth);
    }
    return null;
}

protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
protected abstract IContentProvider acquireProvider(Context c, String name);
复制代码

acquireProvider和acquireUnstableProvider都是抽象方法,具体看看ApplicationContentResolver中的实现:

private static final class ApplicationContentResolver extends ContentResolver {

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

    @Override
    protected IContentProvider acquireUnstableProvider(Context c, String auth) {
        return mMainThread.acquireProvider(c, ContentProvider.getAuthorityWithoutUserId(auth),
                resolveUserIdFromAuthority(auth), false);
    }
}
复制代码

可以看到不论是acquireUnstableProvider还是acquireProvider方法,最终都会调用ActivityThread的acquireProvider()方法。

AT.acquireProvider

// ActivityThread
public final IContentProvider acquireProvider(
        Context c, String auth, int userId, boolean stable) {
    final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
    if (provider != null) {
        // 成功获取到已存储的CP则直接返回
        return provider;
    }

    // 这里可能会存在问题。当另一个线程同时尝试获取同一个provider时,保证第一个尝试获取的线程成功。
    // 我们不能在获取和安装provider的时候持有锁,因为这个过程可能很长
    // it could also potentially be re-entrant in the case where the provider is in the same process.
    ContentProviderHolder holder = null;
    try {
        synchronized (getGetProviderLock(auth, userId)) {
            holder = ActivityManager.getService().getContentProvider(getApplicationThread(), auth, userId, stable);
        }
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    if (holder == null) {
        return null;
    }
    // 安装provider将会增加引用计数
    holder = installProvider(c, holder, holder.info, true /*noisy*/, holder.noReleaseNeeded, stable);
    return holder.provider;
}
复制代码

该方法过程:

  • 首先通过acquireExistingProvider()方法尝试获取已存储的provider,获取成功则直接返回,否则继续执行;
  • 通过AMS.getContentProvider()方法来获取provider,当无法获取对应的provider则直接返回,否则继续执行;
  • 采用installProvider()安装provider,并该provider的增加引用计数。

AT.acquireExistingProvider

final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<>();

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();
        if (!jBinder.isBinderAlive()) {
            // 当provider所在进程已经死亡则返回
            handleUnstableProviderDiedLocked(jBinder, true);
            return null;
        }
        ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
        if (prc != null) {
            // 增加引用计数
            incProviderRefLocked(prc, stable);
        }
        return provider;
    }
}
复制代码

AMS.getContentProvider

public final ContentProviderHolder getContentProvider(
        IApplicationThread caller, String name, int userId, boolean stable) {
    enforceNotIsolatedCaller("getContentProvider");
    if (caller == null) {
        throw new SecurityException(msg);
    }
    return getContentProviderImpl(caller, name, null, stable, userId);
}

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId) {
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;
    synchronized(this) {
        // 获取调用者所在进程的ProcessRecord
        ProcessRecord r = getRecordForAppLocked(caller);
        // 从AMS中查询相应的ContentProviderRecord
        cpr = mProviderMap.getProviderByName(name, userId);
        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;

        // 目标provider进程已存在
        if (providerRunning) {
            // ...
        }

        // 目标provider进程不存在
        if (!providerRunning) {
            // ...
        }
    }

    // 等待目标provider发布
    synchronized (cpr) {
        while (cpr.provider == null) {
            // ...
        }
    }
    return cpr != null ? cpr.newHolder(conn) : null;
}
复制代码

该方法是获取provider的核心代码,可以分成以下3部分:

  1. 目标provider进程已存在;
  2. 目标provider进程不存在;
  3. 循环等待provider发布完成。

该方法的name参数就是前面的auth,即provider标签里面的android:authorities值。

目标provider已存在

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId) {
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;
    synchronized(this) {
        // 获取调用者所在进程的ProcessRecord
        ProcessRecord r = getRecordForAppLocked(caller);
        // 从AMS中查询相应的ContentProviderRecord
        cpr = mProviderMap.getProviderByName(name, userId);
        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;

        // 目标provider进程已存在
        if (providerRunning) {
            cpi = cpr.info;
            String msg;
            // 检查该ProcessRecord是否有权限访问给定的ProviderInfo
            if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser)) != null) {
                throw new SecurityException(msg);
            }
            if (r != null && cpr.canRunHere(r)) {
                // 当provider已经发布,且它允许运行在调用者进程,则直接返回
                ContentProviderHolder holder = cpr.newHolder(null);
                // don't give caller the provider object, it needs to make its own.
                holder.provider = null;
                return holder;
            }
            // 不要在常规app和instant app之间暴露provider
            if (AppGlobals.getPackageManager().resolveContentProvider(name, 0 /*flags*/, userId) == null) {
                return null;
            }

            final long origId = Binder.clearCallingIdentity();

            // 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) {
                    // 更新进程LRU队列
                    updateLruProcessLocked(cpr.proc, false, null);
                }
            }
            final int verifiedAdj = cpr.proc.verifiedAdj;
            // 更新进程adj
            boolean success = updateOomAdjLocked(cpr.proc, true);
            if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
                success = false;
            }
            if (!success) {
                // provider进程被杀,减少引用计数
                boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
                appDiedLocked(cpr.proc);
                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);
        }
        // ...
    }
    // ...
    return cpr != null ? cpr.newHolder(conn) : null;
}
复制代码

目标provider不存在

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId) {
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;
    synchronized(this) {
        // 获取调用者所在进程的ProcessRecord
        ProcessRecord r = getRecordForAppLocked(caller);
        // 从AMS中查询相应的ContentProviderRecord
        cpr = mProviderMap.getProviderByName(name, userId);
        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
        
        // ...

        // 目标provider不存在
        if (!providerRunning) {
            // 根据authority,获取ProviderInfo对象
            cpi = AppGlobals.getPackageManager().resolveContentProvider(name, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
            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);
            String msg;
            // 做一些检查
            if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton)) != null) {
                throw new SecurityException(msg);
            }
            if (!mProcessesReady && !cpi.processName.equals("system")) {
                throw new IllegalArgumentException("Attempt to launch content provider before system ready");
            }
            if (!mSystemProvidersInstalled && cpi.applicationInfo.isSystemApp() && "system".equals(cpi.processName)) {
                throw new IllegalStateException("Cannot access system provider: '" + cpi.authority + "' before system providers are installed!");
            }
            // 当拥有该provider的用户并没有运行,则直接返回
            if (!mUserController.isUserRunning(userId, 0)) {
                return null;
            }

            ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
            cpr = mProviderMap.getProviderByClass(comp, userId);
            final boolean firstClass = cpr == null;
            if (firstClass) {
                final long ident = Binder.clearCallingIdentity();
                try {
                    ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(cpi.applicationInfo.packageName, STOCK_PM_FLAGS, userId);
                    if (ai == null) {
                        return null;
                    }
                    ai = getAppInfoForUser(ai, userId);
                    cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
                } catch (RemoteException ex) {
                    // pm is in same process, this will never happen.
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }

            if (r != null && cpr.canRunHere(r)) {
                return cpr.newHolder(null);
            }

            // 从mLaunchingProviders中查询是否存在该cpr
            final int N = mLaunchingProviders.size();
            int i;
            for (i = 0; i < N; i++) {
                if (mLaunchingProviders.get(i) == cpr) {
                    break;
                }
            }
            // 当provider并没有处于mLaunchingProviders队列,则启动它
            if (i >= N) {
                final long origId = Binder.clearCallingIdentity();
                try {
                    // Content provider is now in use, its package can't be stopped.
                    AppGlobals.getPackageManager().setPackageStoppedState(cpr.appInfo.packageName, false, userId);

                    // Use existing process if already started
                    ProcessRecord proc = getProcessRecordLocked(cpi.processName, cpr.appInfo.uid, false);
                    if (proc != null && proc.thread != null && !proc.killed) {
                        if (!proc.pubProviders.containsKey(cpi.name)) {
                            proc.pubProviders.put(cpi.name, cpr);
                            proc.thread.scheduleInstallProvider(cpi);
                        }
                    } else {
                        // 启动进程
                        proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, "content provider",
                                new ComponentName(cpi.applicationInfo.packageName, cpi.name), false, false, false);
                        if (proc == null) {
                            return null;
                        }
                    }
                    cpr.launchingApp = proc;
                    // 将cpr添加到mLaunchingProviders
                    mLaunchingProviders.add(cpr);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
            }

            if (firstClass) {
                mProviderMap.putProviderByClass(comp, cpr);
            }
            mProviderMap.putProviderByName(name, cpr);
            // 增加引用计数
            conn = incProviderCountLocked(r, cpr, token, stable);
            if (conn != null) {
                conn.waiting = true;
            }
        }
    }
    // ...
    return cpr != null ? cpr.newHolder(conn) : null;
}
复制代码

当进程没有启动时,调用startProcessLocked方法启动目标provider进程,由Android-Application启动原理可知,AMS的attachApplicationLocked方法会调用IApplicationThread.bindApplication方法,即通过Binder的方式调用到目标进程的ActivityThread会执行handleBindApplication方法:

private void handleBindApplication(AppBindData data) {
    // ...
    if (!ArrayUtils.isEmpty(data.providers)) {
        installContentProviders(app, data.providers);
    }
    // ...
}
复制代码

当目标进程已经启动时,则调用proc.thread.scheduleInstallProvider方法通过Binder调用到目标进程:

private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public void scheduleInstallProvider(ProviderInfo provider) {
        sendMessage(H.INSTALL_PROVIDER, provider);
    }
}

// ActivityThread
case INSTALL_PROVIDER:
    handleInstallProvider((ProviderInfo) msg.obj);
    break;

public void handleInstallProvider(ProviderInfo info) {
    final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
    try {
        installContentProviders(mInitialApplication, Arrays.asList(info));
    } finally {
        StrictMode.setThreadPolicy(oldPolicy);
    }
}
复制代码

可知无论目标进程启动与否,最终都会调用到installContentProviders方法。

等待目标provider发布

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId) {
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;
    // ...
    // 等待目标provider发布
    synchronized (cpr) {
        while (cpr.provider == null) {
            if (cpr.launchingApp == null) {
                return null;
            }
            try {
                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;
}
复制代码

CPR.newHolder

// ContentProviderRecord.java
public ContentProviderHolder newHolder(ContentProviderConnection conn) {
    ContentProviderHolder holder = new ContentProviderHolder(info);
    holder.provider = provider;
    holder.noReleaseNeeded = noReleaseNeeded;
    holder.connection = conn;
    return holder;
}

public class ContentProviderHolder implements Parcelable {
    public final ProviderInfo info;
    public IContentProvider provider;
    public IBinder connection;
    public boolean noReleaseNeeded;
}
复制代码

CPR.canRunHere

// ContentProviderRecord.java
public boolean canRunHere(ProcessRecord app) {
    return (info.multiprocess || info.processName.equals(app.processName))
            && uid == app.info.uid;
}
复制代码

该ContentProvider是否能运行在调用者所在进程需要满足以下条件:

  1. ContentProvider在AndroidManifest.xml文件配置multiprocess=true或调用者进程与ContentProvider在同一个进程
  2. ContentProvider进程跟调用者所在进程是同一个uid

AT.installContentProviders

该方法会先调用installProvider函数安装provider,然后通过Binder调用AMS的publishContentProviders方法来发布provider。

private void installContentProviders(Context context, List<ProviderInfo> providers) {
    final ArrayList<ContentProviderHolder> results = new ArrayList<>();
    for (ProviderInfo cpi : providers) {
        ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
        if (cph != null) {
            cph.noReleaseNeeded = true;
            results.add(cph);
        }
    }

    try {
        ActivityManager.getService().publishContentProviders(getApplicationThread(), results);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}
复制代码

AMS.publishContentProviders

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

    enforceNotIsolatedCaller("publishContentProviders");
    synchronized (this) {
        final ProcessRecord r = getRecordForAppLocked(caller);
        if (r == null) {
            throw new SecurityException();
        }

        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;
            }
            ContentProviderRecord dst = r.pubProviders.get(src.info.name);
            if (dst != null) {
                ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                // 将该provider添加到mProviderMap
                mProviderMap.putProviderByClass(comp, dst);
                String names[] = dst.info.authority.split(";");
                for (int j = 0; j < names.length; j++) {
                    // 将该provider添加到mProviderMap
                    mProviderMap.putProviderByName(names[j], dst);
                }

                int launchingCount = mLaunchingProviders.size();
                int j;
                boolean wasInLaunchingProviders = false;
                for (j = 0; j < launchingCount; j++) {
                    if (mLaunchingProviders.get(j) == dst) {
                        // 将该provider移除mLaunchingProviders队列
                        mLaunchingProviders.remove(j);
                        wasInLaunchingProviders = true;
                        j--;
                        launchingCount--;
                    }
                }
                if (wasInLaunchingProviders) {
                    // 移除provider发布超时的消息
                    // 该超时消息在AMS的attachApplicationLocked方法中发送
                    mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
                }
                synchronized (dst) {
                    dst.provider = src.provider;
                    dst.proc = r;
                    // 唤醒所有等待的Client端进程,通知发布完成
                    dst.notifyAll();
                }
                updateOomAdjLocked(r, true);
                maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }
}
复制代码

AT.installProvider

private ContentProviderHolder installProvider(Context context,
        ContentProviderHolder holder, ProviderInfo info,
        boolean noisy, boolean noReleaseNeeded, boolean stable) {
    ContentProvider localProvider = null;
    IContentProvider provider;
    if (holder == null || holder.provider == null) {
        Context c = null;
        ApplicationInfo ai = info.applicationInfo;
        if (context.getPackageName().equals(ai.packageName)) {
            c = context;
        } else if (mInitialApplication != null &&
                mInitialApplication.getPackageName().equals(ai.packageName)) {
            c = mInitialApplication;
        } else {
            c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE);
        }
        // 无法获取context则直接返回
        if (c == null) {
            return null;
        }

        if (info.splitName != null) {
            try {
                c = c.createContextForSplit(info.splitName);
            } catch (NameNotFoundException e) {
                throw new RuntimeException(e);
            }
        }

        try {
            final java.lang.ClassLoader cl = c.getClassLoader();
            LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
            if (packageInfo == null) {
                // System startup case.
                packageInfo = getSystemContext().mPackageInfo;
            }
            // 通过反射,创建目标ContentProvider对象
            localProvider = packageInfo.getAppFactory().instantiateProvider(cl, info.name);
            provider = localProvider.getIContentProvider();
            if (provider == null) {
                return null;
            }
            // 回调目标ContentProvider.onCreate方法
            localProvider.attachInfo(c, info);
        } catch (java.lang.Exception e) {
            return null;
        }
    } else {
        provider = holder.provider;
    }

    ContentProviderHolder retHolder;

    synchronized (mProviderMap) {
        IBinder jBinder = provider.asBinder();
        if (localProvider != null) {
            ComponentName cname = new ComponentName(info.packageName, info.name);
            ProviderClientRecord pr = mLocalProvidersByName.get(cname);
            if (pr != null) {
                provider = pr.mProvider;
            } else {
                holder = new ContentProviderHolder(info);
                holder.provider = provider;
                holder.noReleaseNeeded = true;
                pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                mLocalProviders.put(jBinder, pr);
                mLocalProvidersByName.put(cname, pr);
            }
            retHolder = pr.mHolder;
        } else {
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
            if (prc != null) {
                // 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);
                    ActivityManager.getService().removeContentProvider(holder.connection, stable);
                }
            } else {
                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;
}
复制代码

CP.getIContentProvider

public abstract class ContentProvider implements ComponentCallbacks2 {
    public IContentProvider getIContentProvider() {
        return mTransport;
    }

    class Transport extends ContentProviderNative {
    }
}

abstract public class ContentProviderNative extends Binder implements IContentProvider {
}
复制代码

AMS.removeContentProvider

public void removeContentProvider(IBinder connection, boolean stable) {
    enforceNotIsolatedCaller("removeContentProvider");
    long ident = Binder.clearCallingIdentity();
    try {
        synchronized (this) {
            ContentProviderConnection conn;
            try {
                conn = (ContentProviderConnection)connection;
            } catch (ClassCastException e) {
                throw new IllegalArgumentException(msg);
            }
            if (conn == null) {
                throw new NullPointerException("connection is null");
            }
            if (decProviderCountLocked(conn, null, null, stable)) {
                updateOomAdjLocked();
            }
        }
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}
复制代码

AT.installProviderAuthoritiesLocked

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

    if (provider != null) {
        // If this provider is hosted by the core OS and cannot be upgraded, then I guess we're okay doing blocking calls to it.
        for (String auth : auths) {
            switch (auth) {
                case ContactsContract.AUTHORITY:
                case CallLog.AUTHORITY:
                case CallLog.SHADOW_AUTHORITY:
                case BlockedNumberContract.AUTHORITY:
                case CalendarContract.AUTHORITY:
                case Downloads.Impl.AUTHORITY:
                case "telephony":
                    Binder.allowBlocking(provider.asBinder());
            }
        }
    }

    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);
        }
    }
    return pcr;
}
复制代码

调用进程: insert/delete/query/update

在获取了ContentProvider后,调用进程(客户端)接着开始远程调用目标进程的ContentProvider(服务端)相对应的接口。由上面AMS的代码可知,服务端的Binder实例是Transport对象,Transport继承自ContentProviderNative:

abstract public class ContentProviderNative extends Binder implements IContentProvider {
    public ContentProviderNative()
    {
        attachInterface(this, descriptor);
    }

    static public IContentProvider asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IContentProvider in = (IContentProvider)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ContentProviderProxy(obj);
    }
}
复制代码

因此客户端的Binder代理是ContentProviderProxy对象,调用进程调用增删查改方法时,会通过Binder远程调用到目标ContentProvider进程的onTransact方法。

final class ContentProviderProxy implements IContentProvider
{
    public ContentProviderProxy(IBinder remote) {
        mRemote = remote;
    }

    @Override
    public IBinder asBinder() {
        return mRemote;
    }

    @Override
    public Uri insert(String callingPkg, Uri url, ContentValues values) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        try {
            data.writeInterfaceToken(IContentProvider.descriptor);

            data.writeString(callingPkg);
            url.writeToParcel(data, 0);
            values.writeToParcel(data, 0);

            mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);

            DatabaseUtils.readExceptionFromParcel(reply);
            Uri out = Uri.CREATOR.createFromParcel(reply);
            return out;
        } finally {
            data.recycle();
            reply.recycle();
        }
    }

    // 其它方法类似,都是通过mRemote来调用服务端接口
}
复制代码

目标进程: insert/delete/query/update

abstract public class ContentProviderNative extends Binder implements IContentProvider {
    @Override
    public IBinder asBinder() {
        return this;
    }

    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        try {
            switch (code) {
                case QUERY_TRANSACTION:
                {
                    // 处理参数
                    Cursor cursor = query(callingPkg, url, projection, queryArgs, cancellationSignal);
                    if (cursor != null) {
                        CursorToBulkCursorAdaptor adaptor = null;
                        try {
                            adaptor = new CursorToBulkCursorAdaptor(cursor, observer, getProviderName());
                            cursor = null;
                            BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();
                            adaptor = null;
                            reply.writeNoException();
                            reply.writeInt(1);
                            d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                        } finally {
                            // Close cursor if an exception was thrown while constructing the adaptor.
                            if (adaptor != null) {
                                adaptor.close();
                            }
                            if (cursor != null) {
                                cursor.close();
                            }
                        }
                    } else {
                        reply.writeNoException();
                        reply.writeInt(0);
                    }
                    return true;
                }
                // 其它类似
            }
        } catch (Exception e) {
            DatabaseUtils.writeExceptionToParcel(reply, e);
            return true;
        }
        return super.onTransact(code, data, reply, flags);
    }
}
复制代码

上面onTransact方法中都是调用的子类Transport中对应的方法:

class Transport extends ContentProviderNative {

    @Override
    public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
            @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
        validateIncomingUri(uri);
        uri = maybeGetUriWithoutUserId(uri);
        if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
            if (projection != null) {
                return new MatrixCursor(projection, 0);
            }
            Cursor cursor = ContentProvider.this.query(uri, projection, queryArgs,
                    CancellationSignal.fromTransport(cancellationSignal));
            if (cursor == null) {
                return null;
            }
            // Return an empty cursor for all columns.
            return new MatrixCursor(cursor.getColumnNames(), 0);
        }
        final String original = setCallingPackage(callingPkg);
        try {
            // 回调自定义ContentProvider中的query方法
            return ContentProvider.this.query(uri, projection, queryArgs, CancellationSignal.fromTransport(cancellationSignal));
        } finally {
            setCallingPackage(original);
        }
    }

    // 其它方法也是类似回调到自定义ContentProvider中的相应方法
}
复制代码

ContentProvider引用计数

这里将ContentProvider引用计数单独作为一节进行解析。

相关类

// ContentProvider与Client之间的连接对象,存于system_server进程的AMS中
public final class ContentProviderConnection extends Binder {
    public final ContentProviderRecord provider; // ContentProvider进程
    public final ProcessRecord client;           // 客户端进程
    public final long createTime; // 创建时间
    public int stableCount;       // stable引用次数
    public int unstableCount;     // unstable引用次数
    public boolean waiting;       // 该连接的client正在等待provider发布
    public boolean dead;          // 该连接的provider已处于死亡状态

    // For debugging.
    public int numStableIncs;     // stable计数总的增加次数
    public int numUnstableIncs;   // unstable计数总的增加次数
}

// ActivityThread的内部类,该引用保存到Client端
private static final class ProviderRefCount {
    public final ContentProviderHolder holder;
    public final ProviderClientRecord client;
    public int stableCount;
    public int unstableCount;
    // 当此选项为ture时,stable和unstable的引用计数为0,且将会执行一项待处理操作,以从activity manager中删除引用计数。
    // 在activity manager上仍保留unstable引用,尽管它并不反映该引用数目。
    public boolean removePending;
}
复制代码

AMS.incProviderCountLocked

incProviderCountLocked方法运行在system_server进程,增加引用成功后,返回一个表示与客户端连接的ContentProviderConnection对象。

ContentProviderConnection incProviderCountLocked(ProcessRecord r,
        final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
    if (r != null) {
        for (int i=0; i<r.conProviders.size(); i++) {
            // 从当前进程的provider中查询与目标provider一致的信息
            ContentProviderConnection conn = r.conProviders.get(i);
            if (conn.provider == cpr) {
                if (stable) {
                    conn.stableCount++;
                    conn.numStableIncs++;
                } else {
                    conn.unstableCount++;
                    conn.numUnstableIncs++;
                }
                return conn;
            }
        }
        // 查询不到则新建provider连接对象
        ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
        if (stable) {
            conn.stableCount = 1;
            conn.numStableIncs = 1;
        } else {
            conn.unstableCount = 1;
            conn.numUnstableIncs = 1;
        }
        cpr.connections.add(conn);
        r.conProviders.add(conn);
        startAssociationLocked(r.uid, r.processName, r.curProcState, cpr.uid, cpr.name, cpr.info.processName);
        return conn;
    }
    cpr.addExternalProcessHandleLocked(externalProcessToken);
    return null;
}
复制代码

AMS.decProviderCountLocked

decProviderCountLocked运行在system_server进程,引用减小成功后,当provider连接的stable和unstable引用次数都为0时移除该连接对象信息。

boolean decProviderCountLocked(ContentProviderConnection conn,
        ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
    if (conn != null) {
        cpr = conn.provider;
        if (stable) {
            conn.stableCount--;
        } else {
            conn.unstableCount--;
        }
        // 当provider连接的stable和unstable引用次数都为0时移除该连接对象信息
        if (conn.stableCount == 0 && conn.unstableCount == 0) {
            cpr.connections.remove(conn);
            conn.client.conProviders.remove(conn);
            if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                if (cpr.proc != null) {
                    cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
                }
            }
            stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name);
            return true;
        }
        return false;
    }
    cpr.removeExternalProcessHandleLocked(externalProcessToken);
    return false;
}
复制代码

AT.incProviderRefLocked

incProviderRefLocked运行在客户端。

private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
    if (stable) {
        prc.stableCount += 1;
        if (prc.stableCount == 1) {
            // We are acquiring a new stable reference on the provider.
            int unstableDelta;
            if (prc.removePending) {
                // We have a pending remove operation, which is holding the last unstable reference.
                // At this point we are converting that unstable reference to our new stable reference.
                unstableDelta = -1;
                // Cancel the removal of the provider.
                prc.removePending = false;
                mH.removeMessages(H.REMOVE_PROVIDER, prc);
            } else {
                unstableDelta = 0;
            }
            ActivityManager.getService().refContentProvider(prc.holder.connection, 1, unstableDelta);
        }
    } else {
        prc.unstableCount += 1;
        if (prc.unstableCount == 1) {
            // We are acquiring a new unstable reference on the provider.
            if (prc.removePending) {
                // Oh look, we actually have a remove pending for the provider,
                // which is still holding the last unstable reference.
                // We just need to cancel that to take new ownership of the reference.
                prc.removePending = false;
                mH.removeMessages(H.REMOVE_PROVIDER, prc);
            } else {
                // First unstable ref, increment our count in the activity manager.
                ActivityManager.getService().refContentProvider(prc.holder.connection, 0, 1);
            }
        }
    }
}
复制代码

removePending是指当前正在处于移除引用计数的过程,当removePending=true代表正处于移除最后引用的情况。而此时有需要增加引用计数,所以会抵消一次unstableCount加1的操作。

AT.releaseProvider

CR.releaseProvider跟CR.releaseUnstableProvider都会调用到AT.releaseProvider方法,releaseProvider运行在客户端,会减小引用计数。

public final boolean releaseProvider(IContentProvider provider, boolean stable) {
    IBinder jBinder = provider.asBinder();
    synchronized (mProviderMap) {
        ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
        if (prc == null) {
            // The provider has no ref count, no release is needed.
            return false;
        }

        boolean lastRef = false;
        if (stable) {
            if (prc.stableCount == 0) {
                return false; // 引用次数为0则直接返回
            }
            prc.stableCount -= 1;
            if (prc.stableCount == 0) {
                // What we do at this point depends on whether there are any unstable refs left:
                // if there are, we just tell the activity manager to decrement its stable count;
                // if there aren't, we need to enqueue this provider to be removed,
                // and convert to holding a single unstable ref while doing so.
                lastRef = prc.unstableCount == 0;
                ActivityManager.getService().refContentProvider(prc.holder.connection, -1, lastRef ? 1 : 0);
            }
        } else {
            if (prc.unstableCount == 0) {
                return false;
            }
            prc.unstableCount -= 1;
            if (prc.unstableCount == 0) {
                // If this is the last reference, we need to enqueue this provider to be 
                // removed instead of telling the activity manager to remove it at this point.
                lastRef = prc.stableCount == 0;
                if (!lastRef) {
                    ActivityManager.getService().refContentProvider(prc.holder.connection, 0, -1);
                }
            }
        }

        if (lastRef) {
            // 当执行完该方法,引用技术变成0时,则发送REMOVE_PROVIDER消息
            if (!prc.removePending) {
                prc.removePending = true;
                Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
                mH.sendMessage(msg);
            }
        }
        return true;
    }
}
复制代码

该方法先减小ProviderRefCount对象的引用,再通过Binder调用AMS.refContentProvider来减小ContentProviderConnection的引用。

主线程收到REMOVE_PROVIDER消息后会调用AT.completeRemoveProvider方法。

AMS.refContentProvider

public boolean refContentProvider(IBinder connection, int stable, int unstable) {
    ContentProviderConnection conn;
    conn = (ContentProviderConnection)connection;

    synchronized (this) {
        if (stable > 0) {
            conn.numStableIncs += stable;
        }
        stable = conn.stableCount + stable;
        if (stable < 0) {
            throw new IllegalStateException("stableCount < 0: " + stable);
        }

        if (unstable > 0) {
            conn.numUnstableIncs += unstable;
        }
        unstable = conn.unstableCount + unstable;
        if (unstable < 0) {
            throw new IllegalStateException("unstableCount < 0: " + unstable);
        }

        if ((stable+unstable) <= 0) {
            throw new IllegalStateException("ref counts can't go to zero here: stable="
                    + stable + " unstable=" + unstable);
        }
        conn.stableCount = stable;
        conn.unstableCount = unstable;
        return !conn.dead;
    }
}
复制代码

该方法修改了conn的stable和unstable引用次数并返回connection是否存活,修改后的stable和unstable值都必须大于或等于0,且其和必须大于0。

AT.completeRemoveProvider

final void completeRemoveProvider(ProviderRefCount prc) {
    synchronized (mProviderMap) {
        if (!prc.removePending) {
            return;
        }
        prc.removePending = false;

        final IBinder jBinder = prc.holder.provider.asBinder();
        ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
        if (existingPrc == prc) {
            mProviderRefCountMap.remove(jBinder);
        }

        for (int i=mProviderMap.size()-1; i>=0; i--) {
            ProviderClientRecord pr = mProviderMap.valueAt(i);
            IBinder myBinder = pr.mProvider.asBinder();
            if (myBinder == jBinder) {
                mProviderMap.removeAt(i);
            }
        }
    }

    ActivityManager.getService().removeContentProvider(prc.holder.connection, false);
}

// AMS.java
public void removeContentProvider(IBinder connection, boolean stable) {
    enforceNotIsolatedCaller("removeContentProvider");
    long ident = Binder.clearCallingIdentity();
    try {
        synchronized (this) {
            ContentProviderConnection conn;
            conn = (ContentProviderConnection)connection;
            if (conn == null) {
                throw new NullPointerException("connection is null");
            }
            if (decProviderCountLocked(conn, null, null, stable)) {
                updateOomAdjLocked();
            }
        }
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}
复制代码

Provider死亡

AMS.appDiedLocked

当provider进程死亡时,对于unstable的provider可直接调用unstableProviderDied,或者是当provider进程死亡后会有死亡回调binderDied,这两个方法最终都会调用到AMS.appDiedLocked()。

final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread, boolean fromBinderDied) {
    synchronized (mPidsSelfLocked) {
        ProcessRecord curProc = mPidsSelfLocked.get(pid);
        if (curProc != app) {
            return;
        }
    }
    if (!app.killed) {
        if (!fromBinderDied) {
            killProcessQuiet(pid);
        }
        killProcessGroup(app.uid, pid);
        app.killed = true;
    }

    // Clean up already done if the process has been re-started.
    if (app.pid == pid && app.thread != null && app.thread.asBinder() == thread.asBinder()) {
        handleAppDiedLocked(app, false, true);
        if (doOomAdj) {
            updateOomAdjLocked();
        }
        if (doLowMem) {
            doLowMemReportIfNeededLocked(app);
        }
    }
}

private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) {
    int pid = app.pid;
    boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, false /*replacingPid*/);
    // ...
}
复制代码

AMS.cleanUpApplicationRecordLocked

private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
        boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
    // ...
    for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
        // 获取该进程已发布的ContentProvider
        ContentProviderRecord cpr = app.pubProviders.valueAt(i);
        final boolean always = app.bad || !allowRestart;
        boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
        if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
            // We left the provider in the launching list, need to restart it.
            restart = true;
        }
        cpr.provider = null;
        cpr.proc = null;
    }
    app.pubProviders.clear();

    // 处理正在启动并且有client端正在等待的ContentProvider
    if (cleanupAppInLaunchingProvidersLocked(app, false)) {
        restart = true;
    }
    // ...
    return false;
}
复制代码

AMS.removeDyingProviderLocked

private final boolean removeDyingProviderLocked(ProcessRecord proc, ContentProviderRecord cpr, boolean always) {
    final boolean inLaunching = mLaunchingProviders.contains(cpr);

    if (!inLaunching || always) {
        synchronized (cpr) {
            cpr.launchingApp = null;
            cpr.notifyAll(); // 通知处于等待状态的进程
        }
        mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
        String names[] = cpr.info.authority.split(";");
        for (int j = 0; j < names.length; j++) {
            mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
        }
    }

    for (int i = cpr.connections.size() - 1; i >= 0; i--) {
        ContentProviderConnection conn = cpr.connections.get(i);
        if (conn.waiting) {
            // If this connection is waiting for the provider, then we don't need to mess with its process
            // unless we are always removing or for some reason the provider is not currently launching.
            if (inLaunching && !always) {
                continue;
            }
        }
        ProcessRecord capp = conn.client;
        conn.dead = true;
        if (conn.stableCount > 0) {
            if (!capp.persistent && capp.thread != null && capp.pid != 0 && capp.pid != MY_PID) {
                // 非persistent进程,则杀掉跟provider具有依赖关系的进程
                capp.kill("depends on provider " + cpr.name.flattenToShortString()
                        + " in dying proc " + (proc != null ? proc.processName : "??")
                        + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true);
            }
        } else if (capp.thread != null && conn.provider.provider != null) {
            // unstable的类型则不会被杀,也会调用到
            try {
                capp.thread.unstableProviderDied(conn.provider.provider.asBinder());
            } catch (RemoteException e) {
            }
            cpr.connections.remove(i);
            if (conn.client.conProviders.remove(conn)) {
                stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
            }
        }
    }

    if (inLaunching && always) {
        mLaunchingProviders.remove(cpr);
    }
    return inLaunching;
}
复制代码

小结

removePending是指即将被移除的引用,lastRef是指当前引用为0。

当Provider进程死亡后,当Client进程存在对某个provider的引用时,则会根据provider类型进行不同的处理:

  • 对于stable provider(即conn.stableCount > 0): 会杀掉所有跟该provider建立stable连接的非persistent进程。
  • 对于unstable provider(即conn.unstableCount > 0): 不会导致client进程被级联所杀,只会回调unstableProviderDied来清理相关信息。

当stable和unstable引用计数都为0时则移除connection信息。

FileProvider

这部分原理可见Android-FileProvider源码解读

总结

ContentProvider
免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

android

491

相关文章推荐

未登录头像

暂无评论