ContentProvider发布过程

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初始化:当应用程序启动时,ActivityThreadhandleBindApplication()方法会被调用,这期间会解析AndroidManifest.xml,并创建所有已声明的ContentProvider实例。每个ContentProvideronCreate()方法会被调用,用于初始化工作,如数据库打开等。

2. 注册至AMS

  • ProviderInfo收集:系统通过PackageManagerService收集所有应用声明的ContentProvider信息,生成ProviderInfo对象,该对象包含了ContentProvider的详细配置信息。

  • AMS注册ActivityManagerService(AMS)是系统服务的核心,负责管理所有应用的生命周期,包括ContentProviderProviderMap是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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值