目录

  • ContentProvider概述
  • 类图
  • 时序图
  • 源码解析
    • installProvider
    • ContentResolver中的CURD
    • acquireProvider
    • 到AMS获取ContentProvider
    • publishContentProvider
    • removeDyingProvider
  • 总结

1. ContentProvider概述

ContentProvider作为Android四大组件之一,重要性肯定是不言而喻的,顾名思义,内容提供者,其最重要的作用就在于提供了一种跨进程获取数据的方式,provider组件不仅可以自己的进程使用,还可以提供给其他的进程使用,大大方便了不同进程之间的数据交换,本文将详细介绍provider运行的原理。
:本文基于Android 8.1

2. 类图

Android ContentProvider原理分析_第1张图片
看起来涉及到的类非常多,一下有种不知道从何看起的感觉,所以这里对于其中的重点关注部分加上了颜色:
白色:provider运行过程中涉及到的内部类或私有类,一般APP开发过程中不太会涉及
蓝色:APP开发过程中经常会接触到的类
紫色:在system server进程中provider相关的类

3. 时序图

Android ContentProvider原理分析_第2张图片
其中白色部分:发起获取provider的client进程
红色部分:systemserver进程
蓝色部分:提供provider的server进程
时序图解读:

  1. 1~4流程是在APP自己的进程(进程A)中,一般来讲APP在进程启动之后初始化时,就会installProvider(流程7~10),如果APP请求的provider在自己进程,那么到4就能获取到。
  2. 如果请求的provider另外一个进程(进程B)中,则会触发进程5~6
  3. 如果进程B不存在则先启动进程B并installprovider(7~10),告诉AMS之后,由AMS返回给进程A对方的provider信息(此过程中由进程A发起的请求provider的线程会一直等待)
  4. 如果进程B存在则AMS直接返回给进程A对方的provider信息
  5. 查询到provider信息之后,如果需要跨进程调用,则通过ContentProviderProxy发起binder call到对端进程执行query
    在这其中,AMS充当一个中间管理员的角色,每个进程在启动之后需要把自己应该install的providerinstall之后告诉AMS,这样后面有其他进程请求这个provider的话,AMS可以告诉你所请求的对端的信息。

4. 源码解析

4.1 ActivityThread.installProvider

installProvider,顾名思义就是安装provider,说的通俗一点就是把APP进程中的provider组件封装成对象保存起来,方便使用
在APP的进程启动的时候,handleBindApplication中会触发installProvider:

    private void installContentProviders(            Context context, List providers) {        // 此处的provider信息是在AMS启动进程时        // 从manifest收集到的需要install的provider信息        final ArrayList results = new ArrayList<>();        for (ProviderInfo cpi : providers) {            // 执行installProvider,注意此处的stable参数默认为true            ContentProviderHolder cph = installProvider(context, null, cpi,                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);            if (cph != null) {                cph.noReleaseNeeded = true;                results.add(cph);            }        }        try {            // install完成之后,要告诉AMS            ActivityManager.getService().publishContentProviders(                getApplicationThread(), results);        } catch (RemoteException ex) {            throw ex.rethrowFromSystemServer();        }    }

进一步看一下ActivityThread.installProvider的具体实现

    private ContentProviderHolder installProvider(Context context,            ContentProviderHolder holder, ProviderInfo info,            boolean noisy, boolean noReleaseNeeded, boolean stable) {        ContentProvider localProvider = null;        IContentProvider provider;        // holder为null表示还没有install过        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 {                try {                // 创建context                    c = context.createPackageContext(ai.packageName,                            Context.CONTEXT_INCLUDE_CODE);                } catch (PackageManager.NameNotFoundException e) {                    // Ignore                }            }            ...            try {                final java.lang.ClassLoader cl = c.getClassLoader();                // 通过反射创建provider对象                localProvider = (ContentProvider)cl.                    loadClass(info.name).newInstance();                // 获取IContentProvider对象,用于跨进程binder call                provider = localProvider.getIContentProvider();                if (provider == null) {                    Slog.e(TAG, "Failed to instantiate class " +                          info.name + " from sourceDir " +                          info.applicationInfo.sourceDir);                    return null;                }                // provider的attach,其中最重要的是会执行provider的onCreate                localProvider.attachInfo(c, info);            } catch (java.lang.Exception e) {                if (!mInstrumentation.onException(null, e)) {                    throw new RuntimeException(                            "Unable to get provider " + info.name                            + ": " + e.toString(), e);                }                return null;            }        } else {            provider = holder.provider;        }        // 到这里,provider的对象创建好了,那么接下来需要做的就是数据结构的封装        // 把provider相关信息保存起来        ContentProviderHolder retHolder;        // mProviderMap的key时providerKey,value是ProviderClientReocrd        // 这两个类主要是封装了一些provider的基本信息,可以到上面看一下类图        synchronized (mProviderMap) {            IBinder jBinder = provider.asBinder();            if (localProvider != null) {                ComponentName cname = new ComponentName(info.packageName, info.name);                // mLocalProvidersByName的key是component信息,value是对应的ProviderClientReocrd                ProviderClientRecord pr = mLocalProvidersByName.get(cname);                if (pr != null) {                    // 不为空代表install过                    provider = pr.mProvider;                } else {                    // 对于新创建的provider,创建其对应的ContentProviderHolder对象                    holder = new ContentProviderHolder(info);                    holder.provider = provider;                    holder.noReleaseNeeded = true;                    // install Authorities                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);                    // mLocalProviders的key是IContentProvider的binder对象,value是ProviderClientRecord                    // 将封装好的provider放入map中                    mLocalProviders.put(jBinder, pr);                    mLocalProvidersByName.put(cname, pr);                }                retHolder = pr.mHolder;            } else {                // mProviderRefCountMap的key是binder对象,value是ProviderRefCount                // ProviderRefCount中记录了这个provider的stable和unstable的数量                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);                if (prc != null) {                    if (!noReleaseNeeded) {                        incProviderRefLocked(prc, stable);                        try {                            ActivityManager.getService().removeContentProvider(                                    holder.connection, stable);                        } catch (RemoteException e) {                        }                    }                } else {                    ProviderClientRecord client = installProviderAuthoritiesLocked(                            provider, localProvider, holder);                    if (noReleaseNeeded) {                        // 创建ProviderRefCount                        prc = new ProviderRefCount(holder, client, 1000, 1000);                    } else {                        // 根据参数中的stable和unstable创建对象                        prc = stable                                ? new ProviderRefCount(holder, client, 1, 0)                                : new ProviderRefCount(holder, client, 0, 1);                    }                    // 放入map                    mProviderRefCountMap.put(jBinder, prc);                }                retHolder = prc.holder;            }        }        return retHolder;    }

这里需要提一下其中的getIContentProvider:
返回的是一个Transport对象,而这又是ContentProviderNative的子类,主要作用就是用来binder通信的
它的创建:在ContentProvider类中
private Transport mTransport = new Transport();
也就是说在对象创建的时候就默认创建了
然后是ActivityThread.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) {            for (String auth : auths) {                // 对于一些特殊的auth,允许跨进程binder call                // Binder.allowBlocking代表允许执行同步的binder call                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());                }            }        }        // 创建ProviderClientRecord        final ProviderClientRecord pcr = new ProviderClientRecord(                auths, provider, localProvider, holder);        for (String auth : auths) {            // 根据auth和userId创建ProviderKey,放入mProviderMap            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;    }

小结:

  1. 创建了provider对象,其中也创建了IContentProvider对象(Transport)
  2. 创建ContentProviderHolder
  3. 创建ProviderKey
  4. 创建ProviderClientRecord,这是一个provider在client进程中对应的对象
  5. 分别放入mProviderMap/mLocalProviders/mLocalProvidersByName
  6. 创建ProviderRefCount,放入mProviderRefCountMap

这里先说一下stableunstable

  1. 代表的是client和server的链接,主要取决于获取provider的传参,默认情况下,insert/update/delete建立的链接都是stable,而query则是unstable,不过在query的时候如果失败,还会重新创建stable
  2. stable和unstable最重大的差别在于unstable的情况下,即使对端挂掉了,client也没关系,但是stable的话,如果对端进程挂掉了,client也会被跟着级联kill掉。(后面会介绍)

4.2 ContentResolver中的CURD

4.2.1 ContentResolver.insert

    public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,                @Nullable ContentValues values) {        Preconditions.checkNotNull(url, "url");        // 请求provider,经过调用之后,最终传参获取的是stable类型provider        IContentProvider provider = acquireProvider(url);        if (provider == null) {            throw new IllegalArgumentException("Unknown URL " + url);        }        try {            long startTime = SystemClock.uptimeMillis();            // 执行通过IContentProvider执行insert,其实是发起了binder call到了provider所在进程执行            Uri createdRow = provider.insert(mPackageName, url, values);            long durationMillis = SystemClock.uptimeMillis() - startTime;            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);            return createdRow;        } catch (RemoteException e) {            return null;        } finally {            releaseProvider(provider);        }    }

ContentResolver.delete:执行provider的delete
ContentResolver.update:执行provider的update
ContentResolver.call:执行provider的call,这个比较灵活,传递的参数比较多,不固定于某一个
这三个方法的实现都跟instert基本类似,此处不再罗列
下面需要重点说一下query:

4.2.2 query

    public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,            @Nullable String[] projection, @Nullable Bundle queryArgs,            @Nullable CancellationSignal cancellationSignal) {        Preconditions.checkNotNull(uri, "uri");        // 这里执行的方法是acquireUnstableProvider        // 也就是说建立的链接是unstable类型        IContentProvider unstableProvider = acquireUnstableProvider(uri);        if (unstableProvider == null) {            return null;        }        IContentProvider stableProvider = null;        Cursor qCursor = null;        try {            long startTime = SystemClock.uptimeMillis();            ICancellationSignal remoteCancellationSignal = null;            if (cancellationSignal != null) {                cancellationSignal.throwIfCanceled();                remoteCancellationSignal = unstableProvider.createCancellationSignal();                cancellationSignal.setRemote(remoteCancellationSignal);            }            try {                // 执行query                qCursor = unstableProvider.query(mPackageName, uri, projection,                        queryArgs, remoteCancellationSignal);            } catch (DeadObjectException e) {                // 如果query失败                // 因为unstable类型,失败代表对端挂掉了,那么重新请求stable类型链接                unstableProviderDied(unstableProvider);                stableProvider = acquireProvider(uri);                if (stableProvider == null) {                    return null;                }                // 再次query                qCursor = stableProvider.query(                        mPackageName, uri, projection, queryArgs, remoteCancellationSignal);            }            if (qCursor == null) {                return null;            }            qCursor.getCount();            long durationMillis = SystemClock.uptimeMillis() - startTime;            final IContentProvider provider = (stableProvider != null) ? stableProvider                    : acquireProvider(uri);            final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);            stableProvider = null;            qCursor = null;            return wrapper;        } catch (RemoteException e) {            ...        }    }
  1. query的时候先建立的unstable链接,然后发起了binder call
  2. 如果catchRemoteException,那说明对段进程挂了,此时重新请求stable类型链接把对方进程拉起来,再执行query

4.3 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;        }        ContentProviderHolder holder = null;        // 如果不存在则需要向AMS查询        try {            holder = ActivityManager.getService().getContentProvider(                    getApplicationThread(), auth, userId, stable);        } catch (RemoteException ex) {            throw ex.rethrowFromSystemServer();        }        if (holder == null) {            Slog.e(TAG, "Failed to find provider info for " + auth);            return null;        }        // 在本进程中installProvider        holder = installProvider(c, holder, holder.info,                true /*noisy*/, holder.noReleaseNeeded, stable);        return holder.provider;    }

到这里可能有有一些迷糊,前面已经installProvider过了,为什么acquireProvider的时候需要再install一次呢?
答案是因为这是两个不同的进程

  1. 在bindApplication的时候执行的installProvider是提供provider的进程,也就是server进程
  2. 而在此处查询的则是需要获取provider的进程,也就是client进程
  3. server进程installProvider的作用是为了自己进程内使用的话在acquireExistingProvider的时候就能查到了,不需要在跨进程到AMS去查询
  4. client进程installProvider的作用是经过了一次向AMS的查询之后,客户端就可以缓存起来,这样就不用每次都向AMS查询

4.3.1 ActivityThread.acquireExistingProvider

    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()) {                // 对端进程挂掉了                handleUnstableProviderDiedLocked(jBinder, true);                return null;            }            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);            if (prc != null) {                // 增加引用计数                incProviderRefLocked(prc, stable);            }            return provider;        }    }

4.4 ActivityManagerService.getContentProvider

    public final ContentProviderHolder getContentProvider(            IApplicationThread caller, String name, int userId, boolean stable) {        enforceNotIsolatedCaller("getContentProvider");        if (caller == null) {            String msg = "null IApplicationThread when getting content provider "                    + name;            Slog.w(TAG, msg);            throw new SecurityException(msg);        }        return getContentProviderImpl(caller, name, null, stable, userId);    }

简单对caller进行了判断,重点在getContentProviderImpl

4.4.1 getContentProviderImpl

方法比较长,删除了其中一些无用的log以及checkTime

    private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,            String name, IBinder token, boolean stable, int userId) {        ContentProviderRecord cpr;        ContentProviderConnection conn = null;        ProviderInfo cpi = null;        synchronized(this) {            // 对caller判断            boolean checkCrossUser = true;            // 在AMS的providermap中先看看是不是已经存在了            cpr = mProviderMap.getProviderByName(name, userId);            // 如果不存在且system,校验Singleton,也就是只能有一个            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;                    }                }            }            // 看看这个provider当前是不是已经在运行了            boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;            // 如果已经在运行了,也就说明各个数据结构都已经添加过了,进程也都已经存在了            if (providerRunning) {                cpi = cpr.info;                if (r != null && cpr.canRunHere(r)) {                    // canRunHere主要针对自己请求的provider在自己进程中的情况,一般不会遇到                    ContentProviderHolder holder = cpr.newHolder(null);                    holder.provider = null;                    return holder;                }                ...                final long origId = Binder.clearCallingIdentity();                // 建立provider之间的链接                conn = incProviderCountLocked(r, cpr, token, stable);                // 需要更新lru队列                if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {                    if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {                        updateLruProcessLocked(cpr.proc, false, null);                    }                }                final int verifiedAdj = cpr.proc.verifiedAdj;                // 更新进程优先级                boolean success = updateOomAdjLocked(cpr.proc, true);                if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {                    success = false;                }                // 记录usageStates                maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);                if (!success) {                    // 更新lru失败代表那个进程挂掉了                    boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);                    // 需要处理进程挂掉的流程                    // 并且标志provider当前不在运行状态,这样会走进下面的provider不在运行的流程中                    appDiedLocked(cpr.proc);                    if (!lastRef) {                        return null;                    }                    providerRunning = false;                    conn = null;                } else {                    cpr.proc.verifiedAdj = cpr.proc.setAdj;                }                Binder.restoreCallingIdentity(origId);            }            // 如果provider当前不在运行            if (!providerRunning) {                try {                    // 先从packageManager那边查询到相关的信息                    cpi = AppGlobals.getPackageManager().                        resolveContentProvider(name,                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);                } catch (RemoteException ex) {                }                // 没查到的话那就说明这个是一个无效的provider                if (cpi == null) {                    return null;                }                boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,                        cpi.name, cpi.flags)                        && isValidSingletonCall(r.uid, cpi.applicationInfo.uid);                if (singleton) {                    userId = UserHandle.USER_SYSTEM;                }                // 获取applicationInfo                cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);                String msg;                if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))                        != null) {                    throw new SecurityException(msg);                }                // 在system启动之前不允许非system的进程获取provider                if (!mProcessesReady                        && !cpi.processName.equals("system")) {                    throw new IllegalArgumentException(                            "Attempt to launch content provider before system ready");                }                // 校验user是否正在运行中                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);                // 从getProviderByClass中获取,看看这个provider是不是AMS这边已经有保存了                // 如果没有,代表这个provider从来没有向AMS注册过                // 此时需要创建一个新的ContentProviderRecord                cpr = mProviderMap.getProviderByClass(comp, userId);                final boolean firstClass = cpr == null;                if (firstClass) {                    final long ident = Binder.clearCallingIdentity();                    if (mPermissionReviewRequired) {                        if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {                            return null;                        }                    }                    try {                        ApplicationInfo ai =                            AppGlobals.getPackageManager().                                getApplicationInfo(                                        cpi.applicationInfo.packageName,                                        STOCK_PM_FLAGS, userId);                        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);                    } catch (RemoteException ex) {                        // pm is in same process, this will never happen.                    } finally {                        Binder.restoreCallingIdentity(ident);                    }                }                ...                // 看看当前请求的provider是不是在mLaunchingProviders                // 如果一个 provider被请求过,但是因为对方进程没有启动没有publishProvider                // 则会加入mLaunchingProviders中                final int N = mLaunchingProviders.size();                int i;                for (i = 0; i < N; i++) {                    if (mLaunchingProviders.get(i) == cpr) {                        break;                    }                }                // launching中没有                if (i >= N) {                    final long origId = Binder.clearCallingIdentity();                    try {                        try {                            AppGlobals.getPackageManager().setPackageStoppedState(                                    cpr.appInfo.packageName, false, userId);                        } catch (RemoteException e) {                        } catch (IllegalArgumentException e) {                            Slog.w(TAG, "Failed trying to unstop package "                                    + cpr.appInfo.packageName + ": " + e);                        }                        // 看看这个进程是不是存在                        ProcessRecord proc = getProcessRecordLocked(                                cpi.processName, cpr.appInfo.uid, false);                        if (proc != null && proc.thread != null && !proc.killed) {                        // 如果进程已经存在,那么就让这个进程去installProvider即可                            if (!proc.pubProviders.containsKey(cpi.name)) {                                proc.pubProviders.put(cpi.name, cpr);                                try {                                    proc.thread.scheduleInstallProvider(cpi);                                } catch (RemoteException e) {                                }                            }                        } else {                            // 如果进程不存在,那就得先启动进程                            // 因为provider必然运行在某一个进程中,对端进程不在肯定无法获取provider                            proc = startProcessLocked(cpi.processName,                                    cpr.appInfo, false, 0, "content provider",                                    new ComponentName(cpi.applicationInfo.packageName,                                            cpi.name), false, false, false);                            if (proc == null) {                                Slog.w(TAG, "Unable to launch app "                                        + cpi.applicationInfo.packageName + "/"                                        + cpi.applicationInfo.uid + " for provider "                                        + name + ": process is bad");                                return null;                            }                        }                        // 因为需要启动进程,记录这个provider的launchingApp                        // 并把这个provider加入到mLaunchingProviders中,等待对方publish之后                        // 再从mLaunchingProviders中移除                        cpr.launchingApp = proc;                        mLaunchingProviders.add(cpr);                    } finally {                        Binder.restoreCallingIdentity(origId);                    }                }                // 如果是第一次创建的provider,还需要放入mProviderMap                if (firstClass) {                    mProviderMap.putProviderByClass(comp, cpr);                }                mProviderMap.putProviderByName(name, cpr);                // 建立privier之间的链接                conn = incProviderCountLocked(r, cpr, token, stable);                if (conn != null) {                    conn.waiting = true;                }            }            grantEphemeralAccessLocked(userId, null /*intent*/,                    cpi.applicationInfo.uid, UserHandle.getAppId(Binder.getCallingUid()));        }        // 代码执行到这里就说明当前的provider不存在,需要等待对端publish        synchronized (cpr) {            while (cpr.provider == null) {                ...                try {                    if (conn != null) {                        conn.waiting = true;                    }                    // 在需要获取的provider上wait                    // 直到对端provider被publish之后,方可notify                    cpr.wait();                } catch (InterruptedException ex) {                } finally {                    if (conn != null) {                        conn.waiting = false;                    }                }            }        }        return cpr != null ? cpr.newHolder(conn) : null;    }

这段逻辑比较长,总结来说流程如下:

  1. 校验caller/权限等
  2. 如果provider已经在运行,那么建立连接
  3. 更新进程优先级,如果更新失败则代表进程被kill了,标记provider不在运行状态
  4. provider不在运行状态,则需要看一下provider是否mProviderMap中曾经有记录
  5. 如果没有需要创建新的ContentProviderRecord对象,并加到mProviderMap
  6. 判断进程是否存在
  7. 如果进程存在则直接调度进程installProvider
  8. 如果进程不存在则需要先启动进程
  9. 添加mProviderMap以及mLaunchingProviders
  10. 在需要获取的provider上等待对方notify

4.4.2 incProviderCountLocked

    ContentProviderConnection incProviderCountLocked(ProcessRecord r,            final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {        if (r != null) {            for (int i=0; i

这个方法相对简单,所以没有写太多注释,就是根绝provider是否存在以及是否stable,记录stable和unstable的数量

4.5 ActivityManagerService.publishContentProviders

上面的流程中多次提到进程启动的时候会installProvider以及publishContentProviders,接下来就来看一下到底是怎么回事,在前面4.1节中也有提到,在installProvider之后,会通过binder call告诉AMS,publishContentProvider:

    public final void publishContentProviders(IApplicationThread caller,            List providers) {        if (providers == null) {            return;        }        enforceNotIsolatedCaller("publishContentProviders");        synchronized (this) {            final ProcessRecord r = getRecordForAppLocked(caller);            if (r == null) {                throw new SecurityException(                        "Unable to find app for caller " + caller                      + " (pid=" + Binder.getCallingPid()                      + ") when publishing content providers");            }            final long origId = Binder.clearCallingIdentity();            final int N = providers.size();            // 遍历所有已经安装的provider            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) {                    // 将这个providerRecord放入到mProviderMap中                    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);                    }                    int launchingCount = mLaunchingProviders.size();                    int j;                    // 从mLaunchingProviders中移除                    boolean wasInLaunchingProviders = false;                    for (j = 0; j < launchingCount; j++) {                        if (mLaunchingProviders.get(j) == dst) {                            mLaunchingProviders.remove(j);                            wasInLaunchingProviders = true;                            j--;                            launchingCount--;                        }                    }                    if (wasInLaunchingProviders) {                        mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);                    }                    // notify当前正在等待这个provider呗publish的所有的binder线程                    synchronized (dst) {                        dst.provider = src.provider;                        dst.proc = r;                        dst.notifyAll();                    }                    // 更新进程优先级                    updateOomAdjLocked(r, true);                    maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,                            src.info.authority);                }            }            Binder.restoreCallingIdentity(origId);        }    }
  1. 把所有的已经install的Provider放入到mProviderMap,简而言之相当于是注册,让AMS知道这个provider已经在运行了
  2. 把provider从从mLaunchingProviders中移除
  3. 通知等待在这个provider上的binder线程,那些binder线程就可以拿到provider信息返回各自进程继续干活了

4.6 removeDyingProvider

前面多次说了stable与unstable,而且前面基本都是在操作计数,那么到底什么时候会用到这个计数呢?
重点就在这个removeDyingProviderLocked,这个方法作用是当一个进程死亡之后,把其中的所有的provider也remove掉:

    private final boolean removeDyingProviderLocked(ProcessRecord proc,            ContentProviderRecord cpr, boolean always) {        final boolean inLaunching = mLaunchingProviders.contains(cpr);        // 如果这个provider还在等待launching就被remove了        // 需要把当前等待这个provider的线程都notifyAll,否则就再也没有机会notify了        if (!inLaunching || always) {            synchronized (cpr) {                cpr.launchingApp = null;                cpr.notifyAll();            }            // 从mProviderMap中移除            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));            }        }        // 判断这个provider上的所有链接        for (int i = cpr.connections.size() - 1; i >= 0; i--) {            ContentProviderConnection conn = cpr.connections.get(i);            if (conn.waiting) {                if (inLaunching && !always) {                    continue;                }            }            ProcessRecord capp = conn.client;            conn.dead = true;            // 如果stableCount大于0,也就是说存在stable的链接            // server挂掉了,那么就会把client也给kill掉            // 这正是我们前面提到的stable和unstable的重大区别            if (conn.stableCount > 0) {                if (!capp.persistent && capp.thread != null                        && capp.pid != 0                        && capp.pid != MY_PID) {                    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) {                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;    }

5. 总结

经过上面的解读,主要需要了解到的有以下几点:

  1. application初始化的时候会installProvider
  2. 向AMS请求provider的时候如果对端进程不存在则请求的那个线程需要一直等待
  3. 当对方的进程启动之后并publish之后,请求provider的线程才可返回,所以尽量不要在主线程请求provider
  4. 请求provider分为stable以及unsbale,stable类型链接在server进程挂掉之后,client进程会跟着被株连kill
  5. insert/delete/update默认建立stable链接,query默认建立unstable链接,如果失败会重新建立stable链接
  6. AMS作为一个中间管理员的身份,所有的provider会向它注册
  7. 向AMS请求到provider之后,就可以在client和server之间自行binder通信,不需要再经过systemserver

更多相关文章

  1. android超链接
  2. android中将静态库链接进动态库成功的例子
  3. 在android中获取系统正在运行的进程
  4. Android Audio代码分析21 - 创建AudioEffect对象
  5. Android Training精要(六)如何防止Bitmap对象出现OOM
  6. android textView加载html 解决a标签链接无效
  7. android 获取当前运行进程的名称
  8. 《Android开发艺术探索》读书笔记--part2 IPC进程间通信机制

随机推荐

  1. Android将应用log信息保存文件
  2. Android(安卓)汉字转拼音
  3. 网络请求工具类HttpUtils
  4. Android笔记之使用Toast
  5. Android(安卓)Studio “Cannot create di
  6. android 运用百度地图画轨迹
  7. Android编译问题
  8. 广播机制 笔记
  9. adb使用wifi无线连接调试Android设备
  10. Android(安卓)图片添加水印