文章目录

  • 一、 ContentProvider 创建过程分析
  • 二、 ActivityThread 中的 H 处理 BIND_APPLICATION 消息
  • 三、 ActivityThread 中的 handleBindApplication 方法
  • 四、 ActivityThread 中的 installContentProviders 方法 ( 创建 ContentProvider 内容提供者 )
  • 五、 ActivityThread 中的 installProvider 方法 ( 创建 ContentProvider 内容提供者 )
  • 六、 ContentProvider 中的 attachInfo 方法
  • 六、 LoadedApk 中的 mApplication 成员
  • 七、 ActivityThread 涉及源码
  • 八、 Instrumentation 涉及源码
  • 九、 LoadedApk 涉及源码

一、 ContentProvider 创建过程分析


​创建 自定义 ContentProvider , 并在其 onCreate 方法中打印上下文信息 :​

package kim.hsl.dex;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {
/*
验证 Application 是否替换成功
打印 Application , ApplicationContext , ApplicationInfo
*/
Log.i("octopus.MyProvider", "Application : " + getContext());
Log.i("octopus.MyProvider", "ApplicationContext : " + getContext().getApplicationContext());
Log.i("octopus.MyProvider", "ApplicationInfo.className : " + getContext().getApplicationInfo().className);
return true;
}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}

@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.e("octopus.MyProvider", "MyProvider delete : " + getContext());
return 0;
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}

​清单文件配置 :​

<provider
android:exported="true"
android:name=".MyProvider"
android:authorities="kim.hsl.dex.myprovider" />

​在 Activity 中使用 ContentProvider :​

contentResolver.delete(
Uri.parse("content://kim.hsl.dex.myprovider"),
null,
null
)

根据打印出来的日志文件分析 , ContentProvider 的 onCreate 方法调用 , 在代理 Application 类 ProxyApplication 的 onCreat 方法之后 , 在 真实 Application 类 MyApplication 的 onCreate 方法之前 ;

下图的日志中 , 分别在 ProxyApplication ( 蓝色部分 ) , MyApplication ( 红色部分 ) , ContentProvider ( 红色部分 ) 中打印的日志 ;

【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application )_Android 安全

在 ContentProvider 中使用的 Application 仍然是代理 Application , 并不是真实应用的 Application ;

二、 ActivityThread 中的 H 处理 BIND_APPLICATION 消息


Activity , Service , BroadcastReceiver 组件 , 创建时 , 都是在 Application 的 onCreate 方法完成之后进行创建 ;

ContentProvider 组件的创建比较特殊 , 当系统发现该应用在 AndroidManifest.xml 中注册了 ContentProvider 组件时 , 会安装该 ContentProvider ;

在 ActivityThread 中 , H ( Handler 子类 ) 接收到 BIND_APPLICATION 消息时 , 进行初始化 ContentProvider 组件的操作 , 调用 handleBindApplication() 方法 , 进行相关操作 ;

public final class ActivityThread {

private class H extends Handler {
public static final int BIND_APPLICATION = 110;

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;

} // switch
} // handleMessage
} // private class H extends Handler

}

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

三、 ActivityThread 中的 handleBindApplication 方法


在 handleBindApplication 方法中 , 先创建了 Application , 此时调用了 Application 的 attachBaseContext 方法 ,

// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
// ★ 创建 Application
// ★ 此时调用 Application 的 attachBaseContext 方法
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

在这之后马上创建 ContentProvider , 此时还没有调用 Application 的 onCreate 方法 ,

// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
// ★ 在此处创建 ContentProvider
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
// ★ 安装 ContentProvider
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}

在创建了 ContentProvider 之后 , 才调用的 Application 的 onCreate 方法 ;

// ★ 此处调用 Application 的 onCreate 方法
mInstrumentation.onCreate(data.instrumentationArgs);

ContentProvider 组件在代理 Application 类 ProxyApplication 的 attachBaseContext 方法之后 , onCreate 方法之前就创建了 , 而 代理 Application 类 ProxyApplication 替换为真实的 Application 类 MyApplication 是在 ProxyApplication 的 onCreate 方法中进行的 , 也就是说 ContentProvider 在 Application 替换之前就创建完成了 ;

因此打印的日志中 , ContentProvider 的 onCreate 方法在 ProxyApplication 的 attachBaseContext 方法之后调用 , 在 ProxyApplication 的 onCreate 方法之前调用 ;

​主要源码 :​

public final class ActivityThread {

private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int BIND_APPLICATION = 110;
public static final int CREATE_SERVICE = 114;
public static final int RECEIVER = 113;

public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);

// ★ 调用 handleLaunchActivity 方法处理该消息
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
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;
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;

} // switch
} // handleMessage
} // private class H extends Handler


private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

// ★ 此处创建了一个 Activity
Activity a = performLaunchActivity(r, customIntent);

}


private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

ActivityInfo aInfo = r.activityInfo;

ContextImpl appContext = createBaseContextForActivity(r);
// ★ 声明 Activity
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();

// ★ 创建 Activity , 与创建 Application 类似
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
} catch (Exception e) {
}

try {
// ★ 这里是传入 Activity attach 方法中的 Application , 赋值给 Activity 中的 mApplication 成员
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

if (activity != null) {
appContext.setOuterContext(activity);

// ★ 此处调用了 Activity 的 attach 方法 , 给 Activity 中的 mApplication 成员赋值
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);

return activity;
}

// ★ 创建 Service 组件
private void handleCreateService(CreateServiceData data) {

LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();

// ★ 创建 Service
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {}

try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);

Application app = packageInfo.makeApplication(false, mInstrumentation);

// ★ 调用了 Service 的 attach 方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
} catch (Exception e) {}
}

private void handleReceiver(ReceiverData data) {
Application app;

// ★ 声明 BroadcastReceiver
BroadcastReceiver receiver;
ContextImpl context;
try {
app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();

// ★ 创建 BroadcastReceiver 对象
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {}

try {

// ★ 调用 BroadcastReceiver 广播接收者的 onReceive 方法
// 这里注意传入的参数就是 context.getReceiverRestrictedContext()
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {} finally {
}
}


private void handleBindApplication(AppBindData data) {

// Allow disk access during application and provider setup. This could
// block processing ordered broadcasts, but later processing would
// probably end up doing the same disk access.
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
// ★ 创建 Application
// ★ 此时调用 Application 的 attachBaseContext 方法
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
// ★ 在此处创建 ContentProvider
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
// ★ 安装 ContentProvider
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}

// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
// ★ 此处调用 Application 的 onCreate 方法
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}

try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}

}


}

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

四、 ActivityThread 中的 installContentProviders 方法 ( 创建 ContentProvider 内容提供者 )


ActivityThread 中的 installContentProviders 方法 , 传入两个参数 :

​Context context 参数 :​ 之前创建的 Application 上下文对象 , 这个 Application 对象是替换前的 代理 Application 对象 , 是在 AndroidManifest.xml 中的 application 节点信息 ;

​List<ProviderInfo> providers 参数 :​ ProviderInfo 集合 , 是为生成多个 ContentProvider 准备的 , ProviderInfo 与 ApplicationInfo 是相同的 , ApplicationInfo 是 AndroidManifest.xml 中的 application 节点信息 , ProviderInfo 是 AndroidManifest.xml 中的 provider 节点信息 ;

在该 installContentProviders 方法中 , 调用了 installProvider 为每个 ProviderInfo 各自创建一个 ContentProvider ;

​相关代码示例 :​

public final class ActivityThread {

// ★ 传入两个参数 ,
// ★ Context context : 之前创建的 Application 上下文对象 ,
// 这个 Application 对象是替换前的 代理 Application 对象 ,
// 是在 AndroidManifest.xml 中的 application 节点信息 ,
// ★ List<ProviderInfo> providers , 这里的 ProviderInfo 集合
// ★ 是为生成多个 ContentProvider 准备的
// ★ ProviderInfo 与 ApplicationInfo 是相同的
// ★ ApplicationInfo 是 AndroidManifest.xml 中的 application 节点信息
// ★ ProviderInfo 是 AndroidManifest.xml 中的 provider 节点信息
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
// ★ 存放创建的多个 ContentProvider
final ArrayList<ContentProviderHolder> results = new ArrayList<>();

// ★ 创建多个 ContentProvider
for (ProviderInfo cpi : providers) {

// ★ 注意这里 installProvider 的第一个参数是 ProxyApplication 类型的
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
}

}

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

五、 ActivityThread 中的 installProvider 方法 ( 创建 ContentProvider 内容提供者 )


在 installProvider 方法中 , 通过 反射创建 ContentProvider ;

// ★ 反射创建 ContentProvider 
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();

在 创建 ContentProvider 之后 , 调用了 attachInfo 函数 , 注意此处与 Activity , Service , BrocastReceiver 不同 , 这三个组件创建后调用的是 attach 函数 ;

// XXX Need to create the correct context for this provider.
// ★ 创建 ContentProvider 之后 , 调用了 attachInfo 函数
// 注意此处与 Activity , Service , BrocastReceiver 不同 ,
// 这三个组件创建后调用的是 attach 函数
localProvider.attachInfo(c, info);

这里分析 attachInfo 中的 c 参数 , 也就是 Context 上下文的获取过程 :

声明空的 Context c 对象 ,

// ★ 该上下文对象很重要 
Context c = null;

获取 ApplicationInfo 信息 ApplicationInfo ai , 即 AndroidManifest.xml 中配置的 application 节点信息

// 该 ApplicationInfo 是 AndroidManifest.xml 中配置的 application 节点信息
ApplicationInfo ai = info.applicationInfo;

​进行如下三个分支的判定 :​

  • ​分支一 :​ if (context.getPackageName().equals(ai.packageName)) : 在应用中配置的代理 Application 包名与真实 Application 包名都是相等的 ;
  • ​分之二 :​ else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) : 与分支一类似 , 也是要求包名相等 ;
  • ​分支三 :​ 上面两个分支没有命中 , 就执行第三个分支 ;
// ★ 该上下文对象很重要 
Context c = null;
// 该 ApplicationInfo 是 AndroidManifest.xml 中配置的 application 节点信息
ApplicationInfo ai = info.applicationInfo;

// 该 context 是 ProxyApplication , 代理 Application
if (context.getPackageName().equals(ai.packageName)) {
// 在应用中配置的代理 Application 包名与真实 Application 包名都是相等的
// 该分支是命中的
c = context;
} else if (mInitialApplication != null &&
mInitialApplication.getPackageName().equals(ai.packageName)) {
// 该分支中 mInitialApplication 就是 Context context 参数 , 肯定不为空
// 该分支无法命中
c = mInitialApplication;
} else {

// 上述两个分支都无法命中 , 才进入该分支
// 需要将代理 Application 的包名 与 真实应用的包名设置成不同的
// 此时上面两个分支都无法命中
try {
c = context.createPackageContext(ai.packageName,
Context.CONTEXT_INCLUDE_CODE);
} catch (PackageManager.NameNotFoundException e) {
// Ignore
}
}

上面的分支一 与 分支二 都是将 代理 Application 分支 , 因此必须要命中第三个分支 ;

如果将 代理 Application 的 getPackageName() 获取包名的方法返回空 , 此时肯定无法命中前两个分支 , 只能命中第三分支 ;

​相关代码示例 :​

public final class ActivityThread {

/**
* Installs the provider.
*
* Providers that are local to the process or that come from the system server
* may be installed permanently which is indicated by setting noReleaseNeeded to true.
* Other remote providers are reference counted. The initial reference count
* for all reference counted providers is one. Providers that are not reference
* counted do not have a reference count (at all).
*
* This method detects when a provider has already been installed. When this happens,
* it increments the reference count of the existing provider (if appropriate)
* and returns the existing provider. This can happen due to concurrent
* attempts to acquire the same provider.
*/
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {

// ★ 声明 ContentProvider
ContentProvider localProvider = null;
IContentProvider provider;
if (holder == null || holder.provider == null) {
if (DEBUG_PROVIDER || noisy) {
Slog.d(TAG, "Loading provider " + info.authority + ": "
+ info.name);
}

// 该上下文对象很重要
Context c = null;
ApplicationInfo ai = info.applicationInfo;


// 该 context 是 ProxyApplication , 代理 Application
if (context.getPackageName().equals(ai.packageName)) {
// 在应用中配置的代理 Application 包名与真实 Application 包名都是相等的
// 该分支是命中的
c = context;
} else if (mInitialApplication != null &&
mInitialApplication.getPackageName().equals(ai.packageName)) {
// 该分支中 mInitialApplication 就是 Context context 参数 , 肯定不为空
// 该分支无法命中
c = mInitialApplication;
} else {

// 上述两个分支都无法命中 , 才进入该分支
// 需要将代理 Application 的包名 与 真实应用的包名设置成不同的
// 此时上面两个分支都无法命中
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);
// XXX Need to create the correct context for this provider.
// ★ 创建 ContentProvider 之后 , 调用了 attachInfo 函数
// 注意此处与 Activity , Service , BrocastReceiver 不同 ,
// 这三个组件创建后调用的是 attach 函数
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
return null;
}
} else {
}
return retHolder;
}

}

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

六、 ContentProvider 中的 attachInfo 方法


在 ContentProvider 中的 attachInfo(Context context, ProviderInfo info) 方法中 , 调用了重载的三个参数的 attachInfo(Context context, ProviderInfo info, boolean testing) 方法 , 其中就有关于上下文对象的赋值 mContext = context , 注意此处进行了上下文赋值 , 就是代理 Application , ProxyApplication , 在 ContentProvider 组件中调用 getContext 获取上下文对象 , 获取的就是该对象 ;

// ★ 注意此处进行了上下文赋值 , 就是代理 Application , ProxyApplication 
// ★ 在 ContentProvider 组件中调用 getContext 获取上下文对象
// ★ 获取的就是该对象
mContext = context;

​ContentProvider 相关源码 :​

public abstract class ContentProvider implements ComponentCallbacks2 {

/**
* ★ ContentProvider 安装后, 回调该函数通知其本身.
*
* @param context ContentProvider 运行的上下文对象
* @param info ContentProvider 组件的注册信息
*/
public void attachInfo(Context context, ProviderInfo info) {
attachInfo(context, info, false);
}

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
mNoPerms = testing;

/*
* Only allow it to be set once, so after the content service gives
* this to us clients can't change it.
*/
if (mContext == null) {
// ★ 注意此处进行了上下文赋值 , 就是代理 Application , ProxyApplication
// ★ 在 ContentProvider 组件中调用 getContext 获取上下文对象
// ★ 获取的就是该对象
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();
}
}


}

​参考源码路径 :​ frameworks/base/core/java/android/content/ContentProvider.java

六、 LoadedApk 中的 mApplication 成员


LoadedApk 中的 mApplication 成员已经替换成了自定义的 Application , 不再是代理的 Application , 因此从 Service 组件中获取的 Application 是已经替换后的用户自定义的 Application , 不是代理 Application ;

Application 已经执行完毕 , Application 替换操作是在 Application 的 onCreate 方法中执行的 , 此处的 Activity 执行肯定在 Application 创建完毕之后执行的 ;

​主要源码 :​

public final class LoadedApk {

public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {

// ★ 如果之前创建过 Application , 就直接使用
if (mApplication != null) {
return mApplication;
}

}
}

​参考路径 :​ frameworks/base/core/java/android/app/LoadedApk.java

七、 ActivityThread 涉及源码


public final class ActivityThread {

private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int BIND_APPLICATION = 110;
public static final int CREATE_SERVICE = 114;
public static final int RECEIVER = 113;

public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);

// ★ 调用 handleLaunchActivity 方法处理该消息
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
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;
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;

} // switch
} // handleMessage
} // private class H extends Handler


private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;

if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}

// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);

if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);

// Initialize before creating the activity
WindowManagerGlobal.initialize();

// ★ 此处创建了一个 Activity
Activity a = performLaunchActivity(r, customIntent);

if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out paused, because it
// needs to be visible but isn't in the foreground. We accomplish this by going
// through the normal startup (because activities expect to go through onResume()
// the first time they run, before their window is displayed), and then pausing it.
// However, in this case we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just retain the current
// state it has.
performPauseActivityIfNeeded(r, reason);

// We need to keep around the original state, in case we need to be created again.
// But we only do this for pre-Honeycomb apps, which always save their state when
// pausing, so we can not have them save their state when restarting from a paused
// state. For HC and later, we want to (and can) let the state be saved as the
// normal part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}



private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}

ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}

if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}

ContextImpl appContext = createBaseContextForActivity(r);
// ★ 声明 Activity
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();

// ★ 创建 Activity , 与创建 Application 类似
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}

try {
// ★ 这里是传入 Activity attach 方法中的 Application , 赋值给 Activity 中的 mApplication 成员
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());

if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);

// ★ 此处调用了 Activity 的 attach 方法 , 给 Activity 中的 mApplication 成员赋值
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);

if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}

activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;

mActivities.put(r.token, r);

} catch (SuperNotCalledException e) {
throw e;

} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}

return activity;
}

// ★ 创建 Service 组件
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();

LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();

// ★ 创建 Service
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}

try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);

Application app = packageInfo.makeApplication(false, mInstrumentation);


// ★ 调用了 Service 的 attach 方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}

private void handleReceiver(ReceiverData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();

String component = data.intent.getComponent().getClassName();

LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);

IActivityManager mgr = ActivityManager.getService();

Application app;

// ★ 声明 BroadcastReceiver
BroadcastReceiver receiver;
ContextImpl context;
try {
app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);

// ★ 创建 BroadcastReceiver 对象
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
throw new RuntimeException(
"Unable to instantiate receiver " + component
+ ": " + e.toString(), e);
}

try {
if (localLOGV) Slog.v(
TAG, "Performing receive of " + data.intent
+ ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + packageInfo.getPackageName()
+ ", comp=" + data.intent.getComponent().toShortString()
+ ", dir=" + packageInfo.getAppDir());

sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);

// ★ 调用 BroadcastReceiver 广播接收者的 onReceive 方法
// 这里注意传入的参数就是 context.getReceiverRestrictedContext()
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
if (!mInstrumentation.onException(receiver, e)) {
throw new RuntimeException(
"Unable to start receiver " + component
+ ": " + e.toString(), e);
}
} finally {
sCurrentBroadcastIntent.set(null);
}

if (receiver.getPendingResult() != null) {
data.finish();
}
}

private void handleBindApplication(AppBindData data) {
// Register the UI Thread as a sensitive thread to the runtime.
VMRuntime.registerSensitiveThread();
if (data.trackAllocation) {
DdmVmInternal.enableRecentAllocations(true);
}

// Note when this process has started.
Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());

mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);

mProfiler = new Profiler();
if (data.initProfilerInfo != null) {
mProfiler.profileFile = data.initProfilerInfo.profileFile;
mProfiler.profileFd = data.initProfilerInfo.profileFd;
mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
}

// send up app name; do this *before* waiting for debugger
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());

if (data.persistent) {
// Persistent processes on low-memory devices do not get to
// use hardware accelerated drawing, since this can add too much
// overhead to the process.
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(false);
}
}

if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
}

// If the app is Honeycomb MR1 or earlier, switch its AsyncTask
// implementation to use the pool executor. Normally, we use the
// serialized executor as the default. This has to happen in the
// main thread so the main looper is set right.
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}

Message.updateCheckRecycle(data.appInfo.targetSdkVersion);

/*
* Before spawning a new process, reset the time zone to be the system time zone.
* This needs to be done because the system time zone could have changed after the
* the spawning of this process. Without doing this this process would have the incorrect
* system time zone.
*/
TimeZone.setDefault(null);

/*
* Set the LocaleList. This may change once we create the App Context.
*/
LocaleList.setDefault(data.config.getLocales());

synchronized (mResourcesManager) {
/*
* Update the system configuration since its preloaded and might not
* reflect configuration changes. The configuration object passed
* in AppBindData can be safely assumed to be up to date
*/
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;

// This calls mResourcesManager so keep it within the synchronized block.
applyCompatConfiguration(mCurDefaultDisplayDpi);
}

data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

/**
* Switch this process to density compatibility mode if needed.
*/
if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
== 0) {
mDensityCompatMode = true;
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
}
updateDefaultDensity();

final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
Boolean is24Hr = null;
if (use24HourSetting != null) {
is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
}
// null : use locale default for 12/24 hour formatting,
// false : use 12 hour format,
// true : use 24 hour format.
DateFormat.set24HourTimePref(is24Hr);

View.mDebugViewAttributes =
mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;

/**
* For system applications on userdebug/eng builds, log stack
* traces of disk and network access to dropbox for analysis.
*/
if ((data.appInfo.flags &
(ApplicationInfo.FLAG_SYSTEM |
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
StrictMode.conditionallyEnableDebugLogging();
}

/**
* For apps targetting Honeycomb or later, we don't allow network usage
* on the main event loop / UI thread. This is what ultimately throws
* {@link NetworkOnMainThreadException}.
*/
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}

/**
* For apps targetting N or later, we don't allow file:// Uri exposure.
* This is what ultimately throws {@link FileUriExposedException}.
*/
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
StrictMode.enableDeathOnFileUriExposure();
}

// We deprecated Build.SERIAL and only apps that target pre NMR1
// SDK can see it. Since access to the serial is now behind a
// permission we push down the value and here we fix it up
// before any app code has been loaded.
try {
Field field = Build.class.getDeclaredField("SERIAL");
field.setAccessible(true);
field.set(Build.class, data.buildSerial);
} catch (NoSuchFieldException | IllegalAccessException e) {
/* ignore */
}

if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
// XXX should have option to change the port.
Debug.changeDebugPort(8100);
if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
Slog.w(TAG, "Application " + data.info.getPackageName()
+ " is waiting for the debugger on port 8100...");

IActivityManager mgr = ActivityManager.getService();
try {
mgr.showWaitingForDebugger(mAppThread, true);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}

Debug.waitForDebugger();

try {
mgr.showWaitingForDebugger(mAppThread, false);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}

} else {
Slog.w(TAG, "Application " + data.info.getPackageName()
+ " can be debugged on port 8100...");
}
}

// Allow application-generated systrace messages if we're debuggable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(isAppDebuggable);
if (isAppDebuggable && data.enableBinderTracking) {
Binder.enableTracing();
}

/**
* Initialize the default http proxy in this process for the reasons we set the time zone.
*/
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
// In pre-boot mode (doing initial launch to collect password), not
// all system is up. This includes the connectivity service, so don't
// crash if we can't get it.
final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw e.rethrowFromSystemServer();
}
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

// Instrumentation info affects the class loader, so load it before
// setting up the app context.
final InstrumentationInfo ii;
if (data.instrumentationName != null) {
try {
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find instrumentation info for: " + data.instrumentationName);
}

mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
} else {
ii = null;
}

final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());

if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
// This cache location probably points at credential-encrypted
// storage which may not be accessible yet; assign it anyway instead
// of pointing at device-encrypted storage.
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
// Provide a usable directory for temporary files
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
} else {
Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "
+ "due to missing cache directory");
}

// Setup a location to store generated/compiled graphics code.
final Context deviceContext = appContext.createDeviceProtectedStorageContext();
final File codeCacheDir = deviceContext.getCodeCacheDir();
if (codeCacheDir != null) {
setupGraphicsSupport(appContext, codeCacheDir);
} else {
Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
}
}

// If we use profiles, setup the dex reporter to notify package manager
// of any relevant dex loads. The idle maintenance job will use the information
// reported to optimize the loaded dex files.
// Note that we only need one global reporter per app.
// Make sure we do this before calling onCreate so that we can capture the
// complete application startup.
if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
BaseDexClassLoader.setReporter(DexLoadReporter.getInstance());
}

// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
NetworkSecurityConfigProvider.install(appContext);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

// Continue loading instrumentation.
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}

final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

if (mProfiler.profileFile != null && !ii.handleProfiling
&& mProfiler.profileFd == null) {
mProfiler.handlingProfiling = true;
final File file = new File(mProfiler.profileFile);
file.getParentFile().mkdirs();
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
} else {
mInstrumentation = new Instrumentation();
}

if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
} else {
// Small heap, clamp to the current growth limit and let the heap release
// pages after the growth limit to the non growth limit capacity. b/18387825
dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
}

// Allow disk access during application and provider setup. This could
// block processing ordered broadcasts, but later processing would
// probably end up doing the same disk access.
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
// ★ 创建 Application
// ★ 此时调用 Application 的 attachBaseContext 方法
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
// ★ 在此处创建 ContentProvider
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
// ★ 安装 ContentProvider
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}

// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
// ★ 此处调用 Application 的 onCreate 方法
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}

try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}

// Preload fonts resources
FontsContract.setApplicationContextForResources(appContext);
try {
final ApplicationInfo info =
getPackageManager().getApplicationInfo(
data.appInfo.packageName,
PackageManager.GET_META_DATA /*flags*/,
UserHandle.myUserId());
if (info.metaData != null) {
final int preloadedFontsResource = info.metaData.getInt(
ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
if (preloadedFontsResource != 0) {
data.info.mResources.preloadFonts(preloadedFontsResource);
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}


// ★ 传入两个参数 ,
// ★ Context context : 之前创建的 Application 上下文对象 ,
// 这个 Application 对象是替换前的 代理 Application 对象 ,
// 是在 AndroidManifest.xml 中的 application 节点信息 ,
// ★ List<ProviderInfo> providers , 这里的 ProviderInfo 集合
// ★ 是为生成多个 ContentProvider 准备的
// ★ ProviderInfo 与 ApplicationInfo 是相同的
// ★ ApplicationInfo 是 AndroidManifest.xml 中的 application 节点信息
// ★ ProviderInfo 是 AndroidManifest.xml 中的 provider 节点信息
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
// ★ 存放创建的多个 ContentProvider
final ArrayList<ContentProviderHolder> results = new ArrayList<>();

// ★ 创建多个 ContentProvider
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());
}

// ★ 注意这里 installProvider 的第一个参数是 ProxyApplication 类型的
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}

try {
ActivityManager.getService().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}




/**
* Installs the provider.
*
* Providers that are local to the process or that come from the system server
* may be installed permanently which is indicated by setting noReleaseNeeded to true.
* Other remote providers are reference counted. The initial reference count
* for all reference counted providers is one. Providers that are not reference
* counted do not have a reference count (at all).
*
* This method detects when a provider has already been installed. When this happens,
* it increments the reference count of the existing provider (if appropriate)
* and returns the existing provider. This can happen due to concurrent
* attempts to acquire the same provider.
*/
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {

// ★ 声明 ContentProvider
ContentProvider localProvider = null;
IContentProvider provider;
if (holder == null || holder.provider == null) {
if (DEBUG_PROVIDER || noisy) {
Slog.d(TAG, "Loading provider " + info.authority + ": "
+ info.name);
}
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;
}

if (info.splitName != null) {
try {
c = c.createContextForSplit(info.splitName);
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
}

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);
// XXX Need to create the correct context for this provider.
// ★ 创建 ContentProvider 之后 , 调用了 attachInfo 函数
// 注意此处与 Activity , Service , BrocastReceiver 不同 ,
// 这三个组件创建后调用的是 attach 函数
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);
}

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 ContentProviderHolder(info);
holder.provider = provider;
holder.noReleaseNeeded = true;
pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
mLocalProviders.put(jBinder, pr);
mLocalProvidersByName.put(cname, pr);
}
retHolder = pr.mHolder;
} else {
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
if (DEBUG_PROVIDER) {
Slog.v(TAG, "installProvider: lost the race, updating ref count");
}
// We need to transfer our new reference to the existing
// ref count, releasing the old one... but only if
// release is needed (that is, it is not running in the
// system process).
if (!noReleaseNeeded) {
incProviderRefLocked(prc, stable);
try {
ActivityManager.getService().removeContentProvider(
holder.connection, stable);
} catch (RemoteException e) {
//do nothing content provider object is dead any way
}
}
} else {
ProviderClientRecord client = installProviderAuthoritiesLocked(
provider, localProvider, holder);
if (noReleaseNeeded) {
prc = new ProviderRefCount(holder, client, 1000, 1000);
} else {
prc = stable
? new ProviderRefCount(holder, client, 1, 0)
: new ProviderRefCount(holder, client, 0, 1);
}
mProviderRefCountMap.put(jBinder, prc);
}
retHolder = prc.holder;
}
}
return retHolder;
}




}

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

八、 Instrumentation 涉及源码


Instrumentation 中创建 Activity 的 newActivity 方法 ;

public class Instrumentation {

/**
* Perform instantiation of an {@link Activity} object. This method is intended for use with
* unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
* locally but will be missing some of the linkages necessary for use within the system.
*
* @param clazz The Class of the desired Activity
* @param context The base context for the activity to use
* @param token The token for this activity to communicate with
* @param application The application object (if any)
* @param intent The intent that started this Activity
* @param info ActivityInfo from the manifest
* @param title The title, typically retrieved from the ActivityInfo record
* @param parent The parent Activity (if any)
* @param id The embedded Id (if any)
* @param lastNonConfigurationInstance Arbitrary object that will be
* available via {@link Activity#getLastNonConfigurationInstance()
* Activity.getLastNonConfigurationInstance()}.
* @return Returns the instantiated activity
* @throws InstantiationException
* @throws IllegalAccessException
*/
public Activity newActivity(Class<?> clazz, Context context,
IBinder token, Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance) throws InstantiationException,
IllegalAccessException {
Activity activity = (Activity)clazz.newInstance();
ActivityThread aThread = null;
activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration(), null /* referrer */, null /* voiceInteractor */,
null /* window */, null /* activityConfigCallback */);
return activity;
}

}

​参考路径 :​ frameworks/base/core/java/android/app/Instrumentation.java

九、 LoadedApk 涉及源码


​LoadedApk 中相关源码 :​

public final class LoadedApk {

public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {

// ★ 如果之前创建过 Application , 就直接使用
if (mApplication != null) {
return mApplication;
}

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

Application app = null;

String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}

try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;

if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}

// Rewrite the R 'constants' for all library apks.
SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
final int N = packageIdentifiers.size();
for (int i = 0; i < N; i++) {
final int id = packageIdentifiers.keyAt(i);
if (id == 0x01 || id == 0x7f) {
continue;
}

rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
}

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

return app;
}


}

​参考路径 :​ frameworks/base/core/java/android/app/LoadedApk.java