当前位置:   article > 正文

Android ContentProvider初始化流程简化分析_合规 bindapplication

合规 bindapplication

系列目录

前言

上一篇文章通过日志发现有这个循序
Application#attachBaseContext() → ContentProvider#attachInfo() → ContentProvider#onCreate() → Application#onCreate()

源码简化分析

Android Code Search android官方在线阅读源码神器
此处分析android-12.0.0_r32源码

入口

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

public static void main(String[] args) {
	Looper.prepareMainLooper();
	...
	//创建ActivityThread
	ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    ...
	Looper.loop();    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

main函数中的重点是创建主线程Looper,事件循环。并创建ActivityThread来初始化程序。

ActivityThread.attach

final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system, long startSeq) {
	final IActivityManager mgr = ActivityManager.getService();
	try {
		mgr.attachApplication(mAppThread, startSeq);
	} catch (RemoteException ex) {
		throw ex.rethrowFromSystemServer();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
private class ApplicationThread extends IApplicationThread.Stub {
}

public interface IApplicationThread extends android.os.IInterface{
	// 静态内部类
	public static abstract class Stub extends android.os.Binder implements android.app.IApplicationThread{
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

mAppThread = new ApplicationThread()非要重要,ApplicationThread属于ActivityThread的内部类,实现了IApplicationThread.Stub,也就是具备了Binder跨进程通信能力。

ActivityManager.getService方法获取ActivityManagerService简称AMS,调用了AMS的attachApplication方法,并把ApplicationThread作为参数传递过去。
AMS位于Framework层,android系统的一个系统服务,Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作。

ActivityManagerService.attachApplication

文件路径:out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/xref26/srcjars.xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
	attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {

	List<ProviderInfo> providers = 
		normalMode?	mCpHelper.generateApplicationProvidersLocked(app): null;
	final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
	//providerList是重点
	thread.bindApplication(processName, appInfo, providerList,
	    instr2.mClass,
	    profilerInfo, instr2.mArguments,
	    instr2.mWatcher,
	    instr2.mUiAutomationConnection, testMode,
	    mBinderTransactionTrackingEnabled, enableTrackAllocation,
	    isRestrictedBackupMode || !normalMode, app.isPersistent(),
	    new Configuration(app.getWindowProcessController().getConfiguration()),
	    app.getCompat(), getCommonServicesLocked(app.isolated),
	    mCoreSettingsObserver.getCoreSettingsLocked(),
	    buildSerial, autofillOptions, contentCaptureOptions,
	    app.getDisabledCompatChanges(), serializedSystemFontMap);
            
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

上一步mgr.attachApplication进入framework层,在attachApplicationLocked中进行很多的操作,比如判断进程pid,是否具备拉起的条件,解析app中的用到的provider,进入ApplicationThread的bindApplication方法中。

ApplicationThread.bindApplication

路径:frameworks/base/core/java/android/app/ActivityThread.java

public final void bindApplication(String processName, ApplicationInfo appInfo, ProviderInfoList providerList, ComponentName instrumentationName, ...)
	...
	//构造需要的数据
	AppBindData data = new AppBindData();
	//后面初始化会用到providers
	data.providers = providerList.getList();
	data.instrumentationName = instrumentationName;
	//省略其他参数赋值
	sendMessage(H.BIND_APPLICATION, data);
}

void sendMessage(int what, Object obj) {
	sendMessage(what, obj, 0, 0, false);
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
	mH.sendMessage(msg);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在AMS中调用thread.bindApplication,相当于又回到了应用的ActivityThread中,最终调用了mH.sendMessage方法。mH是在ActivityThread中初始化的Handler,最终又回到了ActivityThread中。

ActivityThread#mH.handleMessage

public void handleMessage(Message msg) {
	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;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Handler收到BIND_APPLICATION消息,开始执行handleBindApplication。

ActivityThread#handleBindApplication

private void handleBindApplication(AppBindData data) {
	final InstrumentationInfo ii;
	if (data.instrumentationName != null) {
		ii = prepareInstrumentation(data);
	} else {
		ii = null;
	}
	
	//创建ContextImpl
	final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

	if (ii != null) {
		//实际会走这里,在里面初始化mInstrumentation
		initInstrumentation(ii, data, appContext);
	} else {
		mInstrumentation = new Instrumentation();
		mInstrumentation.basicInit(this);
	}
	
	//创建Application对象,会执行attachBaseContext(context);
    Application app;
	app = data.info.makeApplication(data.restrictedBackupMode, null);

	// 初始化Provider
	installContentProviders(app, data.providers);

	// 执行Application的OnCreate
	mInstrumentation.callApplicationOnCreate(app);
}

// 文件路径frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

ContextImpl继承Context,是Context API 的通用实现,它提供了基础Activity 和其他应用程序组件的上下文对象。

Instrumentation 是一个可以在任何application执行代码之前,可以监视app和系统的交互。并且可以在AndroidManifest中配置。也由它执行执行Application的OnCreate。

// 注意这个context,是从上面传递下来的app,也就是application
private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
	for (ProviderInfo cpi : providers) {
		ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
	}
}

private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
	ContentProvider localProvider = null;
	final java.lang.ClassLoader cl = c.getClassLoader();
	// 通过ClassLoader 反射构建ContentProvider
	localProvider = packageInfo.getAppFactory().instantiateProvider(cl, info.name);
	// 
	localProvider.attachInfo(c, info);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  1. makeApplication创建application中会执行attachBaseContext(context);

  2. installContentProviders第一个参数context,是从上面传递下来的app,也就是application。
    遍历providers列表,初始化每一个provider,都是用application的context。构造出ContentProvider然后执行attachInfo() 方法,attachInfo()执行完毕会执行onCreate()

  3. 最后再mInstrumentation.callApplicationOnCreate(app);执行Application的OnCreate方法。

总结

从流程上来看,符合日志打印的流程Application#attachBaseContext() → ContentProvider#attachInfo() → ContentProvider#onCreate() → Application#onCreate()
ContentProvider持有的Context也是application,具备给SDK初始化使用。

源码分析参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/993177
推荐阅读
相关标签
  

闽ICP备14008679号