内容提供者是 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;
}
......
}
最后画流程图作为总结。