推广

08 Content Provider的启动过程

iseeyu2年前 (2024-02-22)推广130

image.png

2.AMS启动Content Provider的过程

我们接着来查看AMS的attachApplication方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

attachApplication方法中又调用了attachApplicationLocked方法:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

     private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
   ...
   thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
...
}

attachApplicationLocked方法中调用了thread的bindApplication方法,thread是IApplicationThread类型的,从类型名字就可以看出来是用于进程间通信,这里实现bindApplication方法的是ApplicationThreadProxy类,它实现了IApplicationThread接口。
frameworks/base/core/java/android/app/ApplicationThreadNative.java

class ApplicationThreadProxy implements IApplicationThread {
...
    @Override
    public final void bindApplication(String packageName, ApplicationInfo info,
            List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
            Bundle testArgs, IInstrumentationWatcher testWatcher,
            IUiAutomationConnection uiAutomationConnection, int debugMode,
            boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode,
            boolean persistent, Configuration config, CompatibilityInfo compatInfo,
            Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
      ...
        mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
...
}

到目前为止,上面的调用过程还是在AMS进程中执行的,因此,需要通过IBinder类型的mRemote对象向新创建的应用程序进程(目标Content Provider所在的进程)发送BIND_APPLICATION_TRANSACTION类型的通信请求。处理这个通信请求的是在新创建的应用程序进程中执行的ApplicationThread的bindApplication方法,如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

public final void bindApplication(String processName, ApplicationInfo appInfo,
               List<ProviderInfo> providers, ComponentName instrumentationName,
               ProfilerInfo profilerInfo, Bundle instrumentationArgs,
               IInstrumentationWatcher instrumentationWatcher,
               IUiAutomationConnection instrumentationUiConnection, int debugMode,
               boolean enableBinderTracking, boolean trackAllocation,
               boolean isRestrictedBackupMode, boolean persistent, Configuration config,
               CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
               ...
               sendMessage(H.BIND_APPLICATION, data);
       }

调用sendMessage方法像H发送BIND_APPLICATION类型消息,H的handleMessage方法如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

   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方法:
frameworks/base/core/java/android/app/ActivityThread.java

private void handleBindApplication(AppBindData data) {
 ...
      final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);//1
       try {
              final ClassLoader cl = instrContext.getClassLoader();
              mInstrumentation = (Instrumentation)
                  cl.loadClass(data.instrumentationName.getClassName()).newInstance();//2
          } catch (Exception e) {
           ...
          }
          final ComponentName component = new ComponentName(ii.packageName, ii.name);
          mInstrumentation.init(this, instrContext, appContext, component,
                  data.instrumentationWatcher, data.instrumentationUiAutomationConnection);//3
         ...
          Application app = data.info.makeApplication(data.restrictedBackupMode, null);//4
          mInitialApplication = app;
          if (!data.restrictedBackupMode) {
              if (!ArrayUtils.isEmpty(data.providers)) {
                  installContentProviders(app, data.providers);//5
                  mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
              }
          }
        ...
         mInstrumentation.callApplicationOnCreate(app);//6
        ... 
}

handleBindApplication方法的代码很长,这里截取了主要的部分。注释1处创建了ContextImpl 。注释2处通过反射创建Instrumentation并在注释3处初始化Instrumentation。注释4处创建Application并且在注释6处调用Application的onCreate方法,这意味着Content Provider所在的应用程序进程已经启动完毕,在这之前,注释5处调用installContentProviders方法来启动Content Provider,代码如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

private void installContentProviders(
        Context context, List<ProviderInfo> providers) {
    final ArrayList<IActivityManager.ContentProviderHolder> results =
        new ArrayList<IActivityManager.ContentProviderHolder>();

    for (ProviderInfo cpi : providers) {//1
        ...
        IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);//2
      ...
    }

    try {
        ActivityManagerNative.getDefault().publishContentProviders(
            getApplicationThread(), results);//3
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

注释1处遍历当前应用程序进程的ProviderInfo列表,得到每个Content Provider的ProviderInfo(存储Content Provider的信息),并在注释2处调用installProvider方法来启动这些Content Provider。在注释3处通过AMS的publishContentProviders方法将这些Content Provider存储在AMS的mProviderMap中,这个mProviderMap在前面提到过,起到缓存的作用,防止每次使用相同的Content Provider时都会调用AMS的getContentProvider方法。来查看installProvider方法时如何启动Content Provider的,installProvider方法如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

private IActivityManager.ContentProviderHolder installProvider(Context context,
           IActivityManager.ContentProviderHolder holder, ProviderInfo info,
           boolean noisy, boolean noReleaseNeeded, boolean stable) {
       ContentProvider localProvider = null;
  ...
               final java.lang.ClassLoader cl = c.getClassLoader();
               localProvider = (ContentProvider)cl.
                   loadClass(info.name).newInstance();//1
               provider = localProvider.getIContentProvider();
               if (provider == null) {
                 ...
                   return null;
               }
               if (DEBUG_PROVIDER) Slog.v(
                   TAG, "Instantiating local provider " + info.name);
               localProvider.attachInfo(c, info);//2
           } catch (java.lang.Exception e) {
              ...
               }
               return null;
           }
       }
          ...
       return retHolder;
   }

在注释1处通过反射来创建ContentProvider类型的localProvider对象,并在注释2处调用了它的attachInfo方法:
frameworks/base/core/java/android/content/ContentProvider.java

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
     ...
          ContentProvider.this.onCreate();
      }
  }

在attachInfo方法中调用了onCreate方法,它是一个抽象方法。这样Content Provider就启动完毕。
最后给出AMS启动Content Provider的时序图。

image.png

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/55929.html

相关文章

直通车推广的算法逻辑是什么(直通车是拥有多种推广)

直通车推广的算法逻辑是什么(直通车是拥有多种推广)

直通车扣费公式:实际扣费=下一名出价X下一名质量得分/您的质量得分+0.01元,流量价值计算公式:流量价值=成交一笔的利润/成交一笔所需流量。...

淘宝引力魔方效果怎么样

淘宝引力魔方效果怎么样

阿里妈妈引力魔方,是超级推荐的全新升级版本,是融合了才能喜欢信息流和焦点图的全新推广产品,原生的信息流模式是唤醒消费者需求的重要入口。全面覆盖了消费者购买前、购买中、购买后的消费全链路。...

公众号排名如何快速进前三 随便一蹭引流几千粉丝不难。

公众号排名如何快速进前三 随便一蹭引流几千粉丝不难。

但凡想网络的人,至少要有一点点自学能力,一点点自学能力都没有的人,我建议好好去上班。 自媒体时代,有点类似春秋战国,诸子百家百家争鸣,发表什么观点的人都有,信什么观点的人也都有。 能走出来的只有少数观点。 很多人之所以不赚钱,思维上自我**,自己认为自己没有赚钱的可能性,已经自我放弃努...

小编分享别再说全网推广无效那是你不会玩。

小编分享别再说全网推广无效那是你不会玩。

互联网时代是大数据时代,要想成事,网络平台的运营是必经之路,不管是新媒体营销还是全网推广都一样,被大部分人说无效的原因基本可以概括如下三点: 一.盲目跟风,急于求成 人云亦云,见效益就上是大众都爱干的事。但是网络推广并非小事,很多企业商家自己做都没做过就盲目跟风,做不了多长时间,看不到...

百度、360、搜狗、UC竞价推广方法!

百度、360、搜狗、UC竞价推广方法!

  百度/360/搜狗/UC竞价推广,都是从推广策划开始的,策划如果做不好,效果肯定也出不来。那竞价推广策划要怎么做呢? 1、人群分析 找到精准的客户定位是第一要务,人群分析9要素分别是:性别、年龄、爱好、学历、职业、收入、地区、上网设备和上网时段。分析完用户人群,便可以对...

内容营销的七个技巧

内容营销的七个技巧

俗话说得好,为王,要是是以内容挂帅的,便是内容,它可说基本上是广告词的反过来,并不追求完美短期内或马上性的不客观的立即的个人行为更改,只是客观的、趋向长期性的这些内容教育,互联网营销中内容要确实,要真正触动客户,目地取决于在客户心里塑造一个最该信赖的形象,在容许的状况下对于...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片