01-05 22:14:31.926 971 1179 I ActivityManager: Killing 13708:com.android.bluetooth/1002 (adj -700): depends on provider com.android.providers.contacts/.CallLogProvider in dying proc android.process.acore (adj 700)
01-05 22:14:31.926 971 1179 I am_kill : [0,13708,com.android.bluetooth,-700,depends on provider com.android.providers.contacts/.CallLogProvider in dying proc android.process.acore (adj 700)]
01-05 22:14:31.928 971 1179 D ActivityManager_Processes: Force removing proc 13928:android.process.acore/u0a18 (android.process.acore/10018)
01-05 22:14:31.929 971 1179 I ActivityManager: Killing 13928:android.process.acore/u0a18 (adj 700): timeout publishing content providers
01-05 22:14:31.929 971 1179 I am_kill : [0,13928,android.process.acore,700,timeout publishing content providers]
com.android.bluetooth进程被kill是因为它依赖的android.process.acore进程也被kill了,android.process.acore被kill 的原因是timeout publishing content providers
在Android源码中,ContentProvider
的发布过程主要涉及以下几个核心步骤:
1. 声明与初始化
-
AndroidManifest.xml:首先,在应用的
AndroidManifest.xml
文件中,开发者需声明ContentProvider
,指定其名称(即类路径)和权限(authorities
)。权限是唯一标识ContentProvider
的字符串,用于构建与之交互的URI。 -
ActivityThread初始化:当应用程序启动时,
ActivityThread
的handleBindApplication()
方法会被调用,这期间会解析AndroidManifest.xml
,并创建所有已声明的ContentProvider
实例。每个ContentProvider
的onCreate()
方法会被调用,用于初始化工作,如数据库打开等。
2. 注册至AMS
-
ProviderInfo收集:系统通过
PackageManagerService
收集所有应用声明的ContentProvider
信息,生成ProviderInfo
对象,该对象包含了ContentProvider
的详细配置信息。 -
AMS注册:
ActivityManagerService
(AMS)是系统服务的核心,负责管理所有应用的生命周期,包括ContentProvider
。ProviderMap
是AMS内部用于管理ContentProvider
的一个重要数据结构,它会根据ProviderInfo
中的authorities
注册所有的ContentProvider
。
3. Binder机制与跨进程通信
-
Binder接口:
ContentProvider
通过IBinder
接口与外界通信,具体实现为IContentProvider
。当客户端通过ContentResolver
请求数据时,会通过Binder机制将请求跨进程传递给服务端的ContentProvider
。 -
跨进程调用处理:服务端的
ContentProvider
收到请求后,会通过自己的ContentProviderNative.onTransact()
方法处理跨进程调用。这些调用会被封装成事务,包括查询(query)、插入(insert)、更新(update)、删除(delete)等操作。
借用一张概括图
system_server在启动进程时如果目标进程有需要注册的ContentProvider,就会发送一个10s的超时信息;如果目标进程的ContentProvider在十秒内加载完成,system_server就会移除这个超时信息;如果没有注册完成,system_server就会处理这个信息,最终就会调用到removeDyingProviderLocked()方法。
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);
}
// Make sure the package is associated with the process.
// XXX We shouldn't need to do this, since we have added the package
// when we generated the providers in generateApplicationProvidersLocked().
// But for some reason in some cases we get here with the package no longer
// added... for now just patch it in to make things happy.
r.addPackage(dst.info.applicationInfo.packageName,
dst.info.applicationInfo.longVersionCode, mProcessStats);
synchronized (dst) {
dst.provider = src.provider;
dst.setProcess(r);
dst.notifyAll();
}
dst.mRestartCount = 0;
updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
src.info.authority);
}
}
Binder.restoreCallingIdentity(origId);
}
}
01-05 22:08:02.122 971 1845 V ActivityManager_MU: getContentProviderImpl cpr.wait -- cpr = ContentProviderRecord{44ca099 u0 com.android.providers.contacts/.CallLogProvider}
01-05 22:08:02.167 971 12381 V ActivityManager_MU: attachApplicationLocked send CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG
01-05 22:08:02.247 971 12381 V ActivityManager_MU: publishContentProviders mLaunchingProviders.get(j) = ContentProviderRecord{44ca099 u0 com.android.providers.contacts/.CallLogProvider}, dst = ContentProviderRecord{2b7ff3f u0 com.android.providers.contacts/.debug.DumpFileProvider}
01-05 22:08:02.248 971 12381 V ActivityManager_MU: publishContentProviders mLaunchingProviders.get(j) = ContentProviderRecord{44ca099 u0 com.android.providers.contacts/.CallLogProvider}, dst = ContentProviderRecord{44ca099 u0 com.android.providers.contacts/.CallLogProvider}
01-05 22:08:02.248 971 12381 V ActivityManager_MU: publishContentProviders remove CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG