Android AOSP 6.0.1 内容提供者 acquireProvider 流程分析

508 阅读19分钟

内容提供者是 Android 应用程序的主要构建模块之一,可为应用程序提供内容。它们封装数据并通过单个 ContentResolver 接口将其提供给应用程序。 仅当您需要在多个应用程序之间共享数据时,才需要内容提供者。例如,联系人数据由多个应用程序使用,并且必须存储在内容提供者中。 如果您不需要在多个应用程序之间共享数据,则可以直接通过 SQLiteDatabase 使用数据库。
在这里插入图片描述
如果您计划共享数据,请使用内容提供者。如果您不打算共享数据,您可能仍然会使用它们,因为它们提供了一个很好的抽象,但是您不必这样做。这种抽象允许您对应用程序数据存储实现进行修改,而不会影响其他依赖于对数据访问的现有应用程序。在这种情况下,只有内容提供者受到影响,而访问它的应用程序不受影响。例如,您可以将 SQLite 数据库替换为其他存储,如下图所示。
在这里插入图片描述
通过 ContentResolver 发出请求时,系统将检查给定 URI 的权限,并将请求传递给在该权限下注册的内容提供者。内容提供者可以根据需要解释 URI 中其他部分。 UriMatcher 类有助于解析 URI。

需要实现的主要方法是:

onCreate() 用于初始化内容提供者

query(Uri, String[], Bundle, CancellationSignal) 将数据返回给调用方

insert(Uri, ContentValues) 将新数据插入内容提供者

update(Uri, ContentValues, Bundle) 更新内容提供者中的现有数据

delete(Uri, Bundle) 从内容提供者删除数据

getType(Uri) 返回内容提供者中数据的 MIME 类型

数据访问方法(如 insert(Uri,ContentValues) 和 update(Uri,ContentValues,Bundle))可以同时从多个线程调用,并且必须是线程安全的。其他方法(如 onCreate())只能从应用程序主线程中调用,必须避免执行冗长的操作。

对 ContentResolver 的请求会自动转发给合适的 ContentProvider 实例,所以子类不必担心跨进程调用的细节。

Android Framework 包括管理音频、视频、图像和个人联系人信息等数据的内容提供者。您可以在 android.provider 软件包的参考文档中看到其中的一些内容。在某些限制下,所有 Android 应用程序都可以访问这些内容提供者。

内容提供者可用于管理对各种数据存储源的访问,包括结构化数据(例如 SQLite 关系数据库)或非结构化数据(例如图像文件)。

内容提供者对访问数据的权限提供细粒度控制。您可以选择仅在应用程序中限制内容提供者的访问,授予从其他应用程序访问数据的综合权限,或者配置不同的读写数据的权限。

您可以使用内容提供者来抽象出访问应用程序中不同数据源的细节。例如,您的应用程序可能在 SQLite 数据库中存储结构化的记录,以及视频和音频文件。如果在应用程序中实现相应的内容提供者,则可以使用内容提供者访问所有这些数据。

一、使用 ContentProvider

先定义一个数据库辅助类,它负责创建用户表。

class DBHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {

    override fun onCreate(db: SQLiteDatabase) {

        db.execSQL("CREATE TABLE IF NOT EXISTS $USER_TABLE_NAME(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {

    }

    companion object {
        private const val DATABASE_NAME = "user.db"
        const val USER_TABLE_NAME = "user"
        private const val DATABASE_VERSION = 1
    }
}

定义内容提供者,在 onCreate 方法中向表中添加了两个用户,并实现了 insert 和 query 方法。

class DemoProvider : ContentProvider() {

    companion object {
        private const val TAG = "DemoProvider"
        private const val AUTHORITY = "com.demo.framework"
        private const val USER_CODE = 1

        private val mMatcher: UriMatcher = UriMatcher(UriMatcher.NO_MATCH)

        init {
            mMatcher.addURI(AUTHORITY, "user", USER_CODE)
        }
    }

    private var mContext: Context? = null
    private var mDbHelper: DBHelper? = null
    private var mDb: SQLiteDatabase? = null

    override fun onCreate(): Boolean {

        mContext = context!!

        mDbHelper = DBHelper(context!!)

        mDb = mDbHelper?.writableDatabase

        mDb?.execSQL("delete from ${DBHelper.USER_TABLE_NAME}")
        mDb?.execSQL("insert into ${DBHelper.USER_TABLE_NAME} values(0,'Peter');")
        mDb?.execSQL("insert into ${DBHelper.USER_TABLE_NAME} values(1,'Justin');")

        Log.d(TAG, "------onCreate------")

        return true
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri {
        Log.d(TAG, "------insert------")
        Log.d(TAG, "values=$values")
        val table = getTableName(uri)
        mDb?.insert(table, null, values)
        // 当该 URI 的 ContentProvider 数据发生变化时,通知访问该 ContentProvider 数据的访问者
        mContext?.contentResolver?.notifyChange(uri, null)
        return uri
    }

    override fun query(
        uri: Uri, projection: Array<String>?, selection: String?,
        selectionArgs: Array<String>?, sortOrder: String?
    ): Cursor {
        Log.d(TAG, "------query------")
        val table = getTableName(uri)
        return mDb!!.query(table, projection, selection, selectionArgs, null, null, sortOrder, null)
    }

    override fun update(
        uri: Uri, values: ContentValues?, selection: String?,
        selectionArgs: Array<String>?
    ): Int {
        return 0
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
        return 0
    }

    override fun getType(uri: Uri): String? {
        return null
    }

    private fun getTableName(uri: Uri): String? {
        var tableName: String? = null
        when (mMatcher.match(uri)) {
            USER_CODE -> tableName = DBHelper.USER_TABLE_NAME
        }
        return tableName
    }
}

最后在 AndroidManifest.xml 中注册 DemoProvider。

            <provider
                android:exported="true"
                android:authorities="com.demo.framework"
                android:name=".DemoProvider"/>

在另一个 APP 中使用我们自定义的内容提供者。

class MainActivity : AppCompatActivity() {

    companion object {
        private const val TAG = "MainActivity"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val uriUser = Uri.parse("content://com.demo.framework/user")

        val values = ContentValues()
        values.put("_id", 2)
        values.put("name", "Bob")

        val resolver = contentResolver

        resolver.insert(uriUser, values)

        val cursor = resolver.query(uriUser, arrayOf("_id", "name"), null, null, null)
        var index = 0
        while (cursor.moveToNext()) {
            index++
            Log.d(TAG, "index=$index id=${cursor.getInt(0)} name=${cursor.getString(1)}")
        }
        cursor.close()

    }
}

运行以上 Demo 代码就可以打印出用户表的全部内容了。

二、getContentResolver 流程分析

在 Demo 中,我们首先获取 ContentResolver 对象。然后调用 insert 插入数据,接下来调用 query 方法查询 DemoProvider 提供的数据。

frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {
    Context mBase;
    ......
    @Override
    public ContentResolver getContentResolver() {
        return mBase.getContentResolver();
    }
    ......
}

根据前几节的分析,mBase 是一个 ContextImpl 类型的对象。

frameworks/base/core/java/android/app/ContextImpl.java

class ContextImpl extends Context {
    ......
    private final ApplicationContentResolver mContentResolver;
    ......
    @Override
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }
    ......
}

mContentResolver 是一个 ApplicationContentResolver 类型,它继承自 ContentResolver。

frameworks/base/core/java/android/app/ContextImpl.java

    private static final class ApplicationContentResolver extends ContentResolver {
        private final ActivityThread mMainThread;
        private final UserHandle mUser;

        public ApplicationContentResolver(
                Context context, ActivityThread mainThread, UserHandle user) {
            super(context);
            mMainThread = Preconditions.checkNotNull(mainThread);
            mUser = Preconditions.checkNotNull(user);
        }
        ......
    }

ContentResolver 提供对内容模型的应用程序访问。 首先调用 acquireProvider 查询对应的远程代理类。

frameworks/base/core/java/android/content/ContentResolver.java

public abstract class ContentResolver {
    ......
    public final @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues values) {
        Preconditions.checkNotNull(url, "url");
        // 1.获取远程代理类 
        IContentProvider provider = acquireProvider(url);
        if (provider == null) {
            throw new IllegalArgumentException("Unknown URL " + url);
        }
        try {
            long startTime = SystemClock.uptimeMillis();
            // 2.插入数据
            Uri createdRow = provider.insert(mPackageName, url, values);
            long durationMillis = SystemClock.uptimeMillis() - startTime;
            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
            return createdRow;
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
            return null;
        } finally {
            releaseProvider(provider);
        }
    }
    ......
}

先来看获取远程代理类的流程,先判断 scheme 是否等于 content,如果不等于直接返回 null,接下来判断 Authority 是否为空,不为空的话,调用它入参为 context 和 Authority 的重载版本函数。

frameworks/base/core/java/android/content/ContentResolver.java

public abstract class ContentResolver {
    ......
    public static final String SCHEME_CONTENT = "content";
    ......
    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;
    }
    ......
}

acquireProvider(Context c, String name) 函数是一个抽象函数,因此最终需要继承自抽象类 ContentResolver 的子类实现。

frameworks/base/core/java/android/content/ContentResolver.java

public abstract class ContentResolver {
    ......
    protected abstract IContentProvider acquireProvider(Context c, String name);
    ......
}

在 ApplicationContentResolver 类中,acquireProvider 函数实际上调用了 ActivityThread 的 acquireProvider 函数。

frameworks/base/core/java/android/app/ContextImpl.java

    private static final class ApplicationContentResolver extends ContentResolver {
        ......
        private final ActivityThread mMainThread;
        ......
        @Override
        protected IContentProvider acquireProvider(Context context, String auth) {
            return mMainThread.acquireProvider(context,
                    ContentProvider.getAuthorityWithoutUserId(auth),
                    resolveUserIdFromAuthority(auth), true);
        }
        ......
    }

入参分别是 Context 上下文、Authority、userId 和 stable flag。首先调用 acquireExistingProvider 查询存在的 provider,如果不存在则通过调用 ActivityManagerProxy 的 getContentProvider 函数从远程 ActivityManagerService 获取 IActivityManager.ContentProviderHolder 对象。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    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;
        }

        // 这里可能存在竞争。 另一个线程可能会尝试同时获取同一 provider。 
        // 发生这种情况时,我们要确保第一个获胜。 
        // 请注意,在获取和安装 provider 时,我们无法持有该锁,因为它可能需要很长时间才能运行,
        // 并且在 provider 处于同一进程中的情况下,也有可能重新进入这种情况。
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), auth, userId, stable);
        } catch (RemoteException ex) {
        }
        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + auth);
            return null;
        }

        // 安装 provider 将增加我们的引用计数,并打破竞争中的任何平局。
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }
    ......
}

acquireExistingProvider 函数中:

1.构建 ProviderKey;

2.通过上一步的 key 在 ArrayMap<ProviderKey, ProviderClientRecord> 中获取对应的 ProviderClientRecord;

由于是首次调用则 mProviderMap 并不存在对应的 ProviderClientRecord 对象。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    private static final class ProviderKey {
        final String authority;
        final int userId;

        public ProviderKey(String authority, int userId) {
            this.authority = authority;
            this.userId = userId;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof ProviderKey) {
                final ProviderKey other = (ProviderKey) o;
                return Objects.equals(authority, other.authority) && userId == other.userId;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return ((authority != null) ? authority.hashCode() : 0) ^ userId;
        }
    }
    
    final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
        = new ArrayMap<ProviderKey, ProviderClientRecord>();
    ......
    final class ProviderClientRecord {
        final String[] mNames;
        final IContentProvider mProvider;
        final ContentProvider mLocalProvider;
        final IActivityManager.ContentProviderHolder mHolder;

        ProviderClientRecord(String[] names, IContentProvider provider,
                ContentProvider localProvider,
                IActivityManager.ContentProviderHolder holder) {
            mNames = names;
            mProvider = provider;
            mLocalProvider = localProvider;
            mHolder = holder;
        }
    }
    ......
    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 的宿主进程已死,我们不能用这个。
                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
                        + ": existing object's process dead");
                handleUnstableProviderDiedLocked(jBinder, true);
                return null;
            }

            // 增加引用计数,如果我们不这样做,那么该 provider 就不会被引用计数,并且永远不需要释放。
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
            if (prc != null) {
                incProviderRefLocked(prc, stable);
            }
            return provider;
        }
    }
    ......
}

转到调用 ActivityManagerProxy 的 getContentProvider 函数从远程 ActivityManagerService 获取 IActivityManager.ContentProviderHolder 对象这部分。ActivityManagerProxy 的 getContentProvider 方法最终是调用其内部的一个 Binder 代理对象 mRemote 向 ActivityManagerService 发送一个类型为 GET_CONTENT_PROVIDER_TRANSACTION 的进程间通信请求。

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager
{
    ......
    public ContentProviderHolder getContentProvider(IApplicationThread caller,
            String name, int userId, boolean stable) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(name);
        data.writeInt(userId);
        data.writeInt(stable ? 1 : 0);
        mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        ContentProviderHolder cph = null;
        if (res != 0) {
            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
        }
        data.recycle();
        reply.recycle();
        return cph;
    }
    ......
}

ActivityManagerService getContentProvider 函数中实际调用 getContentProviderImpl。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    @Override
    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);
        }
        // 现在,在checkContentProviderPermissionLocked() 函数中处理传入的用户检查,以处理跨用户授予。
        return getContentProviderImpl(caller, name, null, stable, userId);
    }
    ......
    
    private final 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.elapsedRealtime();

            ProcessRecord r = null;
            if (caller != null) {
                // 获取 ProcessRecord 对象
                r = getRecordForAppLocked(caller);
                if (r == null) {
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                          + " (pid=" + Binder.getCallingPid()
                          + ") when getting content provider " + name);
                }
            }

            boolean checkCrossUser = true;
            // 如果超过一秒打印一条警告 log
            checkTime(startTime, "getContentProviderImpl: getProviderByName");

            // 首先检查这个内容提供者是否已经发布…
            cpr = mProviderMap.getProviderByName(name, userId);
            // 如果这不起作用,检查它是否为 user 0 存在,然后在使用它之前验证它是否是单例提供者。
            if (cpr == null && userId != UserHandle.USER_OWNER) {
                cpr = mProviderMap.getProviderByName(name, UserHandle.USER_OWNER);
                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_OWNER;
                        checkCrossUser = false;
                    } else {
                        cpr = null;
                        cpi = null;
                    }
                }
            }

            boolean providerRunning = cpr != null;
            ......

            boolean singleton;
            if (!providerRunning) {
                try {
                    checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
                    cpi = AppGlobals.getPackageManager().
                        resolveContentProvider(name,
                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
                    checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");
                } catch (RemoteException ex) {
                }
                if (cpi == null) {
                    return null;
                }
                // 如果提供者是单例的,并且(它被同一个用户调用,或者提供者是一个特权应用程序),那么允许连接到单例提供者
                singleton = isSingleton(cpi.processName, cpi.applicationInfo,
                        cpi.name, cpi.flags)
                        && isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
                if (singleton) {
                    userId = UserHandle.USER_OWNER;
                }
                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 && !mDidUpdate && !mWaitingUpdate
                        && !cpi.processName.equals("system")) {
                    // 如果这个内容提供者没有在系统进程中运行,并且系统还没有准备好运行其他进程,那么将快速失败而不是挂起。
                    throw new IllegalArgumentException(
                            "Attempt to launch content provider before system ready");
                }

                // 确保拥有此提供者的用户正在运行。如果没有,我们不想让它运行。
                if (!isUserRunningLocked(userId, false)) {
                    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);
                checkTime(startTime, "getContentProviderImpl: after getProviderByClass");
                final boolean firstClass = cpr == null;
                if (firstClass) {
                    final long ident = Binder.clearCallingIdentity();
                    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);
                    } catch (RemoteException ex) {
                        // pm是在相同的进程中,这永远不会发生。
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }

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

                if (r != null && cpr.canRunHere(r)) {
                    // 如果这是一个多进程提供者,那么只需返回它的信息并允许调用者实例化它。
                    // 只有在提供者与调用者的进程是同一用户,或者可以作为 root用户 (可以在任何进程)的情况下才这样做。
                    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));

                // 这是单个进程,我们的应用程序现在正在连接它。看看我们是否已经在启动这个提供者的进程中。
                final int N = mLaunchingProviders.size();
                int i;
                for (i = 0; i < N; i++) {
                    if (mLaunchingProviders.get(i) == cpr) {
                        break;
                    }
                }

                // 如果提供者尚未启动,则启动它。
                if (i >= N) {
                    final long origId = Binder.clearCallingIdentity();

                    try {
                        // 内容提供者现在正在使用,它的包不能被停止。
                        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);
                        }

                        // 如果已经启动,则使用现有的进程
                        checkTime(startTime, "getContentProviderImpl: looking for process record");
                        ProcessRecord proc = getProcessRecordLocked(
                                cpi.processName, cpr.appInfo.uid, false);
                        if (proc != null && proc.thread != null) {
                            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");
                            // 1.需要启动新进程
                            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");

                // 确保发布了提供者(相同的提供者类可能以多个名称发布)。
                if (firstClass) {
                    mProviderMap.putProviderByClass(comp, cpr);
                }

                mProviderMap.putProviderByName(name, cpr);
                // 2.增加提供者计数
                conn = incProviderCountLocked(r, cpr, token, stable);
                if (conn != null) {
                    conn.waiting = true;
                }
            }
            checkTime(startTime, "getContentProviderImpl: done!");
        }

        // 等待提供者发布…
        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;
    }
    ......
}

我们的 Demo 中属于首次调用 insert 方法,不难知道最终走到“1.需要启动新进程”处,接下来分析 startProcessLocked 方法流程。另外由于 ContentProviderRecord 对象持有的 provider 为 null,因此这里将一直等待提供者发布。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }
    
    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            checkTime(startTime, "startProcess: after getProcessRecord");

            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                // 如果我们在后台,那么检查一下这个进程是否糟糕。如果是这样,我们只会默默地失败。
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                            + "/" + info.processName);
                    return null;
                }
            } else {
                // 当用户显式地启动一个进程时,清除它的崩溃计数,
                // 这样我们就不会让它变坏,直到他们再次看到至少一个崩溃对话框,
                // 如果它是坏的,则让进程再次变好。
                if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                        + "/" + info.processName);
                mProcessCrashTimes.remove(info.processName, info.uid);
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                            UserHandle.getUserId(info.uid), info.uid,
                            info.processName);
                    mBadProcesses.remove(info.processName, info.uid);
                    if (app != null) {
                        app.bad = false;
                    }
                }
            }
        } else {
            // 如果这是一个独立的进程,它就不能重用现有的进程。
            app = null;
        }

        ......

        String hostingNameStr = hostingName != null
                ? hostingName.flattenToShortString() : null;

        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            // 1
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            app.crashHandler = crashHandler;
            checkTime(startTime, "startProcess: done creating new process record");
        } else {
            // 如果这是进程中的一个新包,则将该包添加到列表中
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: added package to existing proc");
        }

        // 如果系统还没有准备好,那么在它准备好之前不要启动这个进程。
        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            if (!mProcessesOnHold.contains(app)) {
                mProcessesOnHold.add(app);
            }
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                    "System not ready, putting on hold: " + app);
            checkTime(startTime, "startProcess: returning with proc on hold");
            return app;
        }

        checkTime(startTime, "startProcess: stepping in to startProcess");
        // 2
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");
        return (app.pid != 0) ? app : null;
    }
    ......
}

下面来分析1和2处的代码流程,1处返回了 ProcessRecord 对象;2处真正启动进程。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
            boolean isolated, int isolatedUid) {
        String proc = customProcess != null ? customProcess : info.processName;
        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
        final int userId = UserHandle.getUserId(info.uid);
        int uid = info.uid;
        ......
        final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
        if (!mBooted && !mBooting
                && userId == UserHandle.USER_OWNER
                && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
            r.persistent = true;
        }
        addProcessNameLocked(r);
        return r;
    }
    ......
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        long startTime = SystemClock.elapsedRealtime();
        ......

        try {
            ......

            int uid = app.uid;
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            if (!app.isolated) {
                int[] permGids = null;
                try {
                    checkTime(startTime, "startProcess: getting gids from package manager");
                    final IPackageManager pm = AppGlobals.getPackageManager();
                    permGids = pm.getPackageGids(app.info.packageName, app.userId);
                    MountServiceInternal mountServiceInternal = LocalServices.getService(
                            MountServiceInternal.class);
                    mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
                            app.info.packageName);
                } catch (RemoteException e) {
                    throw e.rethrowAsRuntimeException();
                }

                /*
                 * 添加共享应用程序和配置文件 GID,以便应用程序可以共享一些资源,如共享库和访问用户范围的资源。
                 */
                if (ArrayUtils.isEmpty(permGids)) {
                    gids = new int[2];
                } else {
                    gids = new int[permGids.length + 2];
                    System.arraycopy(permGids, 0, gids, 2, permGids.length);
                }
                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
                gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
            }
            ......

            app.gids = gids;
            app.requiredAbi = requiredAbi;
            app.instructionSet = instructionSet;

            // 启动进程。它要么成功并返回一个包含新进程的 PID 的结果,要么抛出一个 RuntimeException。
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, "startProcess: returned from zygote!");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

            ......
        } catch (RuntimeException e) {
            ......
        }
    }
    ......
}

最终调用了 Process 类的静态方法 start 启动新进程。下面是 start 函数的作用:

启动一个新进程。

如果启用了进程,就会创建一个新进程,并在那里执行 processClass 的静态 main() 函数。该函数返回后,进程将继续运行。

如果没有启用进程,则在调用者的进程中创建一个新线程,并在那里调用 processClass 的 main()。

如果不是空字符串,则 niceName 参数是要提供给进程的自定义名称,而不是使用 processClass。这允许您轻松地创建可标识的进程,即使您使用相同的基本 processClass 来启动它们。

frameworks/base/core/java/android/os/Process.java

public class Process {
    ......
    public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }
    ......
}

对于创建新进程的流程不再继续跟下去,android 使用 Linux 内核,所以最终新的进程创建要使用相应的系统调用去创建。由于传入的 processClass 为 “android.app.ActivityThread”,所以最后会执行 ActivityThread 静态 main() 函数。

main() 方法中调用了 attach,入参 system 为 false,接下来通过代理对象 ActivityManagerProxy 调用远程 ActivityManagerService 的 attachApplication 方法,入参是 ApplicationThread 对象。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ......
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            ......
        } else {
            ......
        }
        ......
    }
    ......
    public static void main(String[] args) {
        ......
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ......
    }
}

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager
{
    ......
    public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app.asBinder());
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
    ......
}

ActivityManagerService 中 attachApplication 方法,实际调用了 attachApplicationLocked 函数,generateApplicationProvidersLocked 方法生成 List,这代表了 APP 包含的内容提供者信息列表,最后它会调用 ApplicationThread bindApplication 方法。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ......
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;

        if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
        }
        ......
        try {
            ......
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            ......
        } catch (Exception e) {
            ......
        }
        ......
    }
    ......
    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
    ......
}

下面是 generateApplicationProvidersLocked 函数的详细代码,首先获取进程对应的所有内容提供者 ProviderInfo 列表,接着遍历 ProviderInfo 列表,还记得前面 ActivityManagerService getContentProviderImpl 方法中向 mProviderMap 添加了 ContentProviderRecord 对象,这时把它取出来,同时将它添加到 ProcessRecord 成员 pubProviders Map 中。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
        List<ProviderInfo> providers = null;
        try {
            ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager().
                queryContentProviders(app.processName, app.uid,
                        STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
            providers = slice != null ? slice.getList() : null;
        } catch (RemoteException ex) {
        }
        if (DEBUG_MU) Slog.v(TAG_MU,
                "generateApplicationProvidersLocked, app.info.uid = " + app.uid);
        int userId = app.userId;
        if (providers != null) {
            int N = providers.size();
            app.pubProviders.ensureCapacity(N + app.pubProviders.size());
            for (int i=0; i<N; i++) {
                ProviderInfo cpi =
                    (ProviderInfo)providers.get(i);
                ......

                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
                if (cpr == null) {
                    cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
                    mProviderMap.putProviderByClass(comp, cpr);
                }
                if (DEBUG_MU) Slog.v(TAG_MU,
                        "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
                // 此处要注意,接下来的流程中会从 ProcessRecord pubProviders Map 取出 ContentProviderRecord 对象处理
                app.pubProviders.put(cpi.name, cpr);
                if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
                    // 如果它是一个被标记为在多个进程中运行的平台组件,那么不要添加它,
                    // 因为它实际上是框架的一部分,所以作为一个单独的apk在进程中进行跟踪是没有意义的。
                    app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode,
                            mProcessStats);
                }
                ensurePackageDexOpt(cpi.applicationInfo.packageName);
            }
        }
        return providers;
    }
    ......
}

在 ApplicationThread bindApplication 方法中,创建了一个 AppBindData 对象,然后通过 mH 对象将其发送进入消息队列。最终会调用 H 对象的 handleMessage 处理消息。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    private class ApplicationThread extends ApplicationThreadNative {
        ......
        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
                Bundle coreSettings) {
            ......
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableOpenGlTrace = enableOpenGlTrace;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            sendMessage(H.BIND_APPLICATION, data);                
        }
        ......
    }
    ......
    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }
    ......
}

handleMessage 方法中首先从消息取出 AppBindData 对象,接着调用 ActivityThread handleBindApplication 方法。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    private class H extends Handler {
        ......
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {    
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                ......
            }
        }
        ......
    }
    ......
}

handleBindApplication 方法中从入参 AppBindData 中获取 List,接着调用 installContentProviders 方法。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    private void handleBindApplication(AppBindData data) {
        ......
        // 在应用程序和内容提供者设置期间允许磁盘访问。这可能会阻止处理已排序的广播,但以后的处理可能最终会执行相同的磁盘访问。
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        try {
            // 如果启动应用程序进行完全备份或恢复,请在受限制的环境中使用基本 application 类将其调出。
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

            // 不要在受限模式下调出提供者;它们可能依赖于应用程序的自定义 Application 类
            if (!data.restrictedBackupMode) {
                List<ProviderInfo> providers = data.providers;
                if (providers != null) {
                    installContentProviders(app, providers);
                    // 对于包含内容提供者的进程,我们希望确保在“某个时间点”启用了 JIT。
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            ......
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }
    ......
}

installContentProviders 方法中,首先遍历所有的 ProviderInfo,然后调用 installProvider 处理,最后调用 publishContentProviders 发布内容提供者。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    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());
            }
            // 1.装载内容提供者
            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }

        try {
            // 2.发布内容提供者
            ActivityManagerNative.getDefault().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
        }
    }
    ......
}

先来看 1.装载内容提供者。此函数首先获取了类加载器,通过反射的方式创建了 ContentProvider,然后给 ContentProviderHolder 对象 provider 成员赋值。最后返回 ContentProviderHolder 对象。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    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) {   
            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
                }
            }
            if (c == null) {
                Slog.w(TAG, "Unable to get context for package " +
                      ai.packageName +
                      " while loading content provider " +
                      info.name);
                return null;
            }
            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                // 创建 ContentProvider 实例
                localProvider = (ContentProvider)cl.
                    loadClass(info.name).newInstance();
                provider = localProvider.getIContentProvider();
                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);
                // 需要为此提供者创建正确的上下文。这里会调用 ContentProvider 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;
            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
                    + info.name);
        }
        
        IActivityManager.ContentProviderHolder retHolder;

        synchronized (mProviderMap) {
            if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
                    + " / " + info.name);
            IBinder jBinder = provider.asBinder();
            if (localProvider != null) {
                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);
                    // 此处 ContentProviderHolder 对象 provider 成员已赋值
                    holder.provider = provider;
                    holder.noReleaseNeeded = true;
                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                    mLocalProviders.put(jBinder, pr);
                    mLocalProvidersByName.put(cname, pr);
                }
                retHolder = pr.mHolder;
            } else {
                ......
            }
        }

        return retHolder;
    }
    ......
}

ContentProvider attachInfo 函数最终调用了 onCreate 方法,在 Demo 中将会执行 DemoProvider onCreate 方法。

frameworks/base/core/java/android/content/ContentProvider.java

public abstract class ContentProvider implements ComponentCallbacks2 {
    ......
    public void attachInfo(Context context, ProviderInfo info) {
        attachInfo(context, info, false);
    }

    private void attachInfo(Context context, ProviderInfo info, boolean testing) {
        mNoPerms = testing;

        /*
         * 只允许它被设置一次,所以在内容服务把这个给我们的客户端之后,不能改变它。
         */
        if (mContext == null) {
            mContext = context;
            if (context != null) {
                mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
                        Context.APP_OPS_SERVICE);
            }
            mMyUid = Process.myUid();
            if (info != null) {
                setReadPermission(info.readPermission);
                setWritePermission(info.writePermission);
                setPathPermissions(info.pathPermissions);
                mExported = info.exported;
                mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;
                setAuthorities(info.authority);
            }
            ContentProvider.this.onCreate();
        }
    }
    ......
}

再来看 2.发布内容提供者,使用 ActivityManagerProxy 代理对象调用远程 ActivityManagerService publishContentProviders 方法发布内容提供者。

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager
{
    ......
    public void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeTypedList(providers);
        mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
    ......
}

ActivityManagerService publishContentProviders 方法理解起来并不复杂。

1.遍历 List 列表,取出 ProcessRecord 对象 pubProviders 成员对应 key 的 value,也就是 ContentProviderRecord 对象,这个在前面的步骤中被加入到此 Map 中;

2.mLaunchingProviders 中表示正在启动的内容提供者列表,这里移除对应项;

3.对 ContentProviderRecord 对象设置 provider 成员,并调用 notifyAll 唤醒之前在 ActivityManagerService getContentProviderImpl 方法中等待内容提供者发布的线程,此时 getContentProviderImpl 方法可正常返回。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    public final void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) {
        if (providers == null) {
            return;
        }

        enforceNotIsolatedCaller("publishContentProviders");
        synchronized (this) {
            final ProcessRecord r = getRecordForAppLocked(caller);
            if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid);
            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();
            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 (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);
                    }

                    int launchingCount = mLaunchingProviders.size();
                    int j;
                    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);
                    }
                    synchronized (dst) {
                        dst.provider = src.provider;
                        dst.proc = r;
                        dst.notifyAll();
                    }
                    updateOomAdjLocked(r);
                    maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
                            src.info.authority);
                }
            }

            Binder.restoreCallingIdentity(origId);
        }
    }
    ......
}

最终回到 ActivityManagerService getContentProviderImpl 方法,现在来分析“2.增加提供者计数”流程。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    ContentProviderConnection incProviderCountLocked(ProcessRecord r,
            final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
        if (r != null) {
            ......
            ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
            if (stable) {
                conn.stableCount = 1;
                conn.numStableIncs = 1;
            } else {
                ......
            }
            cpr.connections.add(conn);
            r.conProviders.add(conn);
            startAssociationLocked(r.uid, r.processName, cpr.uid, cpr.name, cpr.info.processName);
            return conn;
        }
        cpr.addExternalProcessHandleLocked(externalProcessToken);
        return null;
    }
    ......
}

incProviderCountLocked 中创建 ContentProviderConnection 对象,并赋值 conn.stableCount 和 conn.numStableIncs 均为 1,然后将其添加到对应的列表中(包括 ContentProviderRecord 持有的所有连接客户端列表和 ProcessRecord 持有的所有 ContentProviderRecord 进程正在使用的 ContentProviderConnection 列表)。最后调用了 startAssociationLocked 函数,该函数将当前 Association 对象添加到相应的关联表。

最后 ActivityManagerService getContentProviderImpl 会返回 ContentProviderHolder 对象, 也就是执行了 cpr.newHolder(conn) 函数并返回 ContentProviderHolder 对象。

frameworks/base/services/core/java/com/android/server/am/ContentProviderRecord.java

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

ContentProviderRecord newHolder 函数中创建了 ContentProviderHolder 对象,并为其成员变量 provider、noReleaseNeeded 和 connection 赋值。

frameworks/base/core/java/android/app/IActivityManager.java

public interface IActivityManager extends IInterface {
    ......
    /** 您可以检索关于特定应用程序的信息。 */
    public static class ContentProviderHolder implements Parcelable {
        public final ProviderInfo info;
        public IContentProvider provider;
        public IBinder connection;
        public boolean noReleaseNeeded;

        public ContentProviderHolder(ProviderInfo _info) {
            info = _info;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            info.writeToParcel(dest, 0);
            if (provider != null) {
                dest.writeStrongBinder(provider.asBinder());
            } else {
                dest.writeStrongBinder(null);
            }
            dest.writeStrongBinder(connection);
            dest.writeInt(noReleaseNeeded ? 1 : 0);
        }

        public static final Parcelable.Creator<ContentProviderHolder> CREATOR
                = new Parcelable.Creator<ContentProviderHolder>() {
            @Override
            public ContentProviderHolder createFromParcel(Parcel source) {
                return new ContentProviderHolder(source);
            }

            @Override
            public ContentProviderHolder[] newArray(int size) {
                return new ContentProviderHolder[size];
            }
        };

        private ContentProviderHolder(Parcel source) {
            info = ProviderInfo.CREATOR.createFromParcel(source);
            provider = ContentProviderNative.asInterface(
                    source.readStrongBinder());
            connection = source.readStrongBinder();
            noReleaseNeeded = source.readInt() != 0;
        }
    }
    ......
}

从 ActivityManagerService getContentProviderImpl 方法返回 ContentProviderHolder 对象最终在 ActivityManagerProxy getContentProvider 函数中反序列化得到 ContentProviderHolder 对象。这里要特别关注序列化和反序列化中对 provider 成员的处理,序列化时候调用了 provider.asBinder() ,反序列化的时候 ContentProviderNative.asInterface 得到是一个 ContentProviderProxy 代理对象。

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager
{
    ......
    public ContentProviderHolder getContentProvider(IApplicationThread caller,
            String name, int userId, boolean stable) throws RemoteException {
        ......
        ContentProviderHolder cph = null;
        if (res != 0) {
            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
        }
        ......
        return cph;
    }
    ......
}

现在 ActivityThread acquireProvider 方法中拿到了 IActivityManager.ContentProviderHolder 对象,最后返回实现 IContentProvider 接口的代理对象 ContentProviderProxy。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {
    ......
    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        ......
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), auth, userId, stable);
        } catch (RemoteException ex) {
        }
        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + auth);
            return null;
        }

        ......
        return holder.provider;
    }
    ......
}

最后画流程图作为总结。
在这里插入图片描述