5.1 Understanding the Context
Context, a Context object, is a common Android class.
Context means Context and is an interface to information about the application environment.
Usage Scenarios:
- Use Context to invoke methods, such as starting an Activity, accessing resources, calling system-level services, and so on.
- The Context is passed when a method is called, such as popping up a Toast, creating a Dialog, etc.
Activities, Services, and applications all indirectly inherit from Context.
How many contexts are there in an Application process, which is equal to the total number of activities and services plus 1,1 is the number of applications.
Context is an abstract class that defines methods and static constants inside it. It is implemented as ContextImpl.
The classes associated with Cotext include ContextImpl, ContextWrapper, ContextThemeWrapper, and Activity.
ContextImpl and ContextWrapper inherit from Context, and ContextWrapper contains an mBase object of type Context, which refers to ContextImpl.
ContextWrapper is a decorator class that wraps the ContentImpl. ContextWrapper is primarily a method passing class. Almost all methods in ContextWrapper are implemented by calling the corresponding method of ContextImpl.
ContextThemeWrapper, Service, and Application all inherit from ContextWrapper so that they can use the Context’s methods via mBase. They are also decorator classes. Different features are added to ContextWrapper.
ContextThemeWrapper contains theme-related methods (such as the getTheme method), so, An Activity that requires a theme inherits the ContextThemeWrapper, but not the theme’s Service inherits the ContextWrapper.
Context’s associated class uses the decorator mode:
- Users (such as Servcice) can easily use the Context.
- If ContextImpl changes, its decorator class ContextWrapper does not need to be modified.
- The implementation of the ContextImpl is not exposed to the consumer, nor should the consumer care about the implementation.
- Extending the functionality of ContextImpl through composition rather than inheritance, and selecting different decorator classes at run time to achieve different functionality.
5.2 Procedure for Creating an Application Context
Get the global ApplicationContext of the Application using getApplicationContext.
After an Application is started, the Application has a global Application Context.
Application Context creation process:
// frameworks/base/core/java/android/app/ActivityThread.java 1074 private class ApplicationThread extends IApplicationThread.Stub { 1075 private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s"; 1076 1077 public final void scheduleReceiver(Intent intent, ActivityInfo info, 1078 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, 1079 boolean sync, int sendingUser, int processState) { 1080 updateProcessState(processState, false); 1081 ReceiverData r = new ReceiverData(intent, resultCode, data, extras, 1082 sync, false, mAppThread.asBinder(), sendingUser); 1083 r.info = info; 1084 r.compatInfo = compatInfo; 1085 sendMessage(H.RECEIVER, r); Class H extends Handler {public static final int RECEIVER = 113; } public void handleMessage(Message msg) { 2187 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); 2188 switch (msg.what) { ... case RECEIVER: 2202 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp"); 2203 handleReceiver((ReceiverData)msg.obj); TraceEnd (TRACE_TAG_ACTIVITY_MANAGER); 2205 break;Copy the code
H inherits from Handler and is an inner class of ActivityThread.
Here, the flow of Android 12 has changed a bit
// frameworks/base/core/java/android/app/ActivityThread.java 4448 private void handleReceiver(ReceiverData data) { 4449 // If we are getting ready to gc after going to the background, well 4450 // we are back active so skip it. 4451 unscheduleGcIdler(); 4452 4453 String component = data.intent.getComponent().getClassName(); 4454 // ApK package information: Mainly for packageInfo 4455 LoadedApk packageInfo = getPackageInfoNoCheck (4456 data. Info. ApplicationInfo, data.com patInfo); 4457 4458 IActivityManager mgr = ActivityManager.getService(); 4459 4460 Application app; 4461 BroadcastReceiver receiver; 4462 ContextImpl context; 4463 try {/ / here call makeApplication 4464 app = packageInfo makeApplication (false, mInstrumentation); // Comment 1 4465 context = (ContextImpl) app.getBaseconText (); 4466 if (data.info.splitName ! = null) { 4467 context = (ContextImpl) context.createContextForSplit(data.info.splitName); 4468 } 4469 if (data.info.attributionTags ! = null && data.info.attributionTags.length > 0) { 4470 final String attributionTag = data.info.attributionTags[0]; 4471 context = (ContextImpl) context.createAttributionContext(attributionTag); 4472 } 4473 java.lang.ClassLoader cl = context.getClassLoader(); 4474 data.intent.setExtrasClassLoader(cl); 4475 data.intent.prepareToEnterProcess( 4476 isProtectedComponent(data.info) || isProtectedBroadcast(data.intent), 4477 context.getAttributionSource()); 4478 data.setExtrasClassLoader(cl); 4479 receiver = packageInfo.getAppFactory() 4480 .instantiateReceiver(cl, data.info.name, data.intent); 4481 } catch (Exception e) { 4482 if (DEBUG_BROADCAST) Slog.i(TAG, 4483 "Finishing failed broadcast to " + data.intent.getComponent()); 4484 data.sendFinished(mgr); 4485 throw new RuntimeException( 4486 "Unable to instantiate receiver " + component 4487 + ": " + e.toString(), e); 4488 } 4489 4490 try { 4491 if (localLOGV) Slog.v( 4492 TAG, "Performing receive of " + data.intent 4493 + ": app=" + app 4494 + ", appName=" + app.getPackageName() 4495 + ", pkg=" + packageInfo.getPackageName() 4496 + ", comp=" + data.intent.getComponent().toShortString() 4497 + ", dir=" + packageInfo.getAppDir()); 4498 4499 sCurrentBroadcastIntent.set(data.intent); 4500 receiver.setPendingResult(data); 4501 4502 //zte add for systrace tag 4503 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG 4504 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 4505 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 4506 "receiver:" + receiver + ", intent=" + data.intent); 4507 } 4508 //zte add end 4509 receiver.onReceive(context.getReceiverRestrictedContext(), 4510 data.intent); 4511 } catch (Exception e) { 4512 if (DEBUG_BROADCAST) Slog.i(TAG, 4513 "Finishing failed broadcast to " + data.intent.getComponent()); 4514 data.sendFinished(mgr); 4515 if (! mInstrumentation.onException(receiver, e)) { 4516 throw new RuntimeException( 4517 "Unable to start receiver " + component 4518 + ": " + e.toString(), e); 4519 } 4520 } finally { 4521 sCurrentBroadcastIntent.set(null); 4522 } 4523 4524 if (receiver.getPendingResult() ! = null) { 4525 data.finish(); 4526 } 4527 4528 //zte add for systrace tag 4529 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG 4530 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 4531 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 4532 } 4533 //zte add end 4534 }Copy the code
In note 1, call the makeApplication method in LoadedApk:
In note 1, call the makeApplication method in LoadedApk:
// frameworks/base/core/java/android/app/LoadedApk.java 1316 public Application makeApplication(boolean forceDefaultAppClass, 1317 Instrumentation instrumentation) { 1318 if (mApplication ! = null) { // 1 1319 return mApplication; 1320 } 1321 1322 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication"); 1323 1324 Application app = null; 1325 1326 String appClass = mApplicationInfo.className; 1327 if (forceDefaultAppClass || (appClass == null)) { 1328 appClass = "android.app.Application"; 1329 } 1330 1331 try { 1332 final java.lang.ClassLoader cl = getClassLoader(); 1333 if (! mPackageName.equals("android")) { 1334 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 1335 "initializeJavaContextClassLoader"); 1336 initializeJavaContextClassLoader(); 1337 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1338 } 1339 1340 // Rewrite the R 'constants' for all library apks. 1341 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers( 1342 false, false); 1343 for (int i = 0, n = packageIdentifiers.size(); i < n; i++) { 1344 final int id = packageIdentifiers.keyAt(i); 1345 if (id == 0x01 || id == 0x7f) { 1346 continue; 1347 } 1348 1349 rewriteRValues(cl, packageIdentifiers.valueAt(i), id); 1352 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //2 1353 // The network security config needs to be aware of multiple 1354 // applications in the same process to handle discrepancies 1355 NetworkSecurityConfigProvider.handleNewApplication(appContext); // Create Application, In the Instrumentation newApplication method an object of type ClassLoader is passed in with ContextImpl 1356 app = created in comment 2 mActivityThread.mInstrumentation.newApplication( 1357 cl, appClass, appContext); // 3 // Application is assigned to mOuterContext, a member of ContextImpl's Context type, so that the ContextImpl contains a reference to Application. 1358 appContext.setOuterContext(app); // 4 1359 } catch (Exception e) { 1360 if (! mActivityThread.mInstrumentation.onException(app, e)) { 1361 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1362 throw new RuntimeException( 1363 "Unable to instantiate application " + appClass 1364 + " package " + mPackageName + ": " + e.toString(), e); 1365 } 1366 } 1367 mActivityThread.mAllApplications.add(app); MApplication -> is an object of type Application, 1368 mApplication = app; // 5 1369 1370 if (instrumentation ! = null) { 1371 try { 1372 instrumentation.callApplicationOnCreate(app); 1373 } catch (Exception e) { 1374 if (! instrumentation.onException(app, e)) { 1375 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1376 throw new RuntimeException( 1377 "Unable to create application " + app.getClass().getName() 1378 + ": " + e.toString(), e); 1379 } 1380 } 1381 } 1382 1383 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1384 1385 return app; 1386}Copy the code
Here we look at how the Application in comment 3 is created, the newApplication method in Instrumentation:
// frameworks/base/core/java/android/app/Instrumentation.java
1163 /**
1164 * Perform instantiation of the process's {@link Application} object. The
1165 * default implementation provides the normal system behavior.
1166 *
1167 * @param cl The ClassLoader with which to instantiate the object.
1168 * @param className The name of the class implementing the Application
1169 * object.
1170 * @param context The context to initialize the application with
1171 *
1172 * @return The newly instantiated Application object.
1173 */
1174 public Application newApplication(ClassLoader cl, String className, Context context)
1175 throws InstantiationException, IllegalAccessException,
1176 ClassNotFoundException {
1177 Application app = getFactory(context.getPackageName())
1178 .instantiateApplication(cl, className);
1179 app.attach(context);
1180 return app;
1181 }
1183 /**
1184 * Perform instantiation of the process's {@link Application} object. The
1185 * default implementation provides the normal system behavior.
1186 *
1187 * @param clazz The class used to create an Application object from.
1188 * @param context The context to initialize the application with
1189 *
1190 * @return The newly instantiated Application object.
1191 */
1192 static public Application newApplication(Class<?> clazz, Context context)
1193 throws InstantiationException, IllegalAccessException,
1194 ClassNotFoundException {
1195 Application app = (Application)clazz.newInstance();
1196 app.attach(context); // 1
1197 return app;
1198 }
Copy the code
Instrumentataion has two newApplication overloaded methods that end up calling this one.
Annotation 1 creates the Application by reflection, calls the Attach method of the Application, passes in ContextImpl, and returns the attach method of the Application as follows:
// frameworks/base/core/java/android/app/Application.java 329 @UnsupportedAppUsage 330 /* package */ final void attach(Context context) { 331 attachBaseContext(context); 332 mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; 333}Copy the code
The attachBaseContext method is called in the Attach method, which is implemented in ContextWrapper, the parent class of the Application.
// frameworks/base/core/java/android/content/ContextWrapper.java
72 /**
73 * Set the base context for this ContextWrapper. All calls will then be
74 * delegated to the base context. Throws
75 * IllegalStateException if a base context has already been set.
76 *
77 * @param base The new base context for this wrapper.
78 */
79 protected void attachBaseContext(Context base) {
80 if (mBase != null) {
81 throw new IllegalStateException("Base context already set");
82 }
83 mBase = base;
84 }
Copy the code
And the base that’s passed all the way through refers to ContextImpl, which is the implementation class of the Context, Assign ContextImpl to mBase, a member of ContextWrapper’s Context type, so that Context’s methods can be used in ContextWrapper.
The attach method of the Application allows the Application to be the Context’s method, so that the Application can be used to represent the Application Context.
conclusion
The flow of Android 12 has changed, but not in many places. The flow is as follows:
[ActivityThread.java] | scheduleReceiver() | | sendMessage(H.RECEIVER, r) | | | H | | handleMessage(Message msg) | | handleReceiver((ReceiverData)msg.obj) | | | app = packageInfo.makeApplication(false, mInstrumentation); | | | | | | | [LoadApk.java] | | | | makeApplication | | | | | | | | | [Instrumentation.java] | | | | | newApplication | | | | | | app.attach(context) | | | | | | | | | | | | | [Application.java] | | | | | | | attachBaseContext(context) | | | | | | | | | | | | | | | ContextWrapperCopy the code
5.3 Obtaining the Application Context
Now that we know how to create the Application Context, let’s look at how to get it.
The ApplicationContext is obtained by calling the getApplicationContext method, which is implemented in ContextWrapperer.
// frameworks/base/core/java/android/content/ContextWrapper.java
124 public Context getApplicationContext() {
125 return mBase.getApplicationContext();
126 }
127
Copy the code
MBase is ContextImpl’s getApplicationContext method:
// frameworks/base/core/java/android/app/ContextImpl.java
407 public Context getApplicationContext() {
408 return (mPackageInfo != null) ?
409 mPackageInfo.getApplication() : mMainThread.getApplication();
410 }
Copy the code
If LoadedApk mPackageInfo is not null, LoadedApk’s getApplication method is called; otherwise, ActivityThread’s getApplication method is called. Since the application has been started, LoadedApk is not null and LoadApk’s getApplication method is called.
// frameworks/base/core/java/android/app/LoadedApk.java 162 Application getApplication() { 163 return mApplication; 164}Copy the code
The mApplication here is assigned in comment 5 of the makeApplication method of LoadedApk above.
So we get the ApplicationContext using the getApplicationContext method.
5.4 Creating an Activity Context
To use the methods provided by the Context in your Activity, you must first create the Context.
The Activity Context is created during the start of the Activity.
Let’s look directly at ActivityThread’s FormLaunchActivity method:
// frameworks/base/core/java/android/app/ActivityThread.java
/** Core implementation of activity launch. */
3683 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
3684 ActivityInfo aInfo = r.activityInfo;
3685 if (r.packageInfo == null) {
3686 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
3687 Context.CONTEXT_INCLUDE_CODE);
3688 }
3689
3690 if (ZTE_TRAVERSAL_ACCELERATE_ENABLED) {
3691 // nubia add for app launch traversals accelerate
3692 if (sIsAppFirstStartActivity) {
3693 sIsAppFirstStartActivity = false;
3694 if (r != null && r.intent != null) {
3695 String intentInfoStr = r.intent.toString();
3696 if (!(intentInfoStr != null && intentInfoStr.contains(Intent.ACTION_MAIN)
3697 && intentInfoStr.contains(Intent.CATEGORY_LAUNCHER))) {
3698 //if app not launch from Launcher so disable app launch traversals accelerate.
3699 sIsEnableAppTraversalsAccelerate = false;
3700 }
3701 }
3702 if (sIsEnableAppTraversalsAccelerate) {
3703 mH.removeCallbacks(mDisableAppTraversalsAccelerateRunnable);
3704 mH.postDelayed(mDisableAppTraversalsAccelerateRunnable, 3000);
3705 }
3706 }
3707 // nubia add end
3708 }
3709 ComponentName component = r.intent.getComponent();
3710 if (component == null) {
3711 component = r.intent.resolveActivity(
3712 mInitialApplication.getPackageManager());
3713 r.intent.setComponent(component);
3714 }
3715
3716 if (r.activityInfo.targetActivity != null) {
3717 component = new ComponentName(r.activityInfo.packageName,
3718 r.activityInfo.targetActivity);
3719 }
3720 // 通过createBaseContextForActivity 方法来创建 Activity 的 ContextImpl
// 并将其传入注释4处的 activity 的 attach 方法中
// 这样ContextImpl 也可以访问 Activity 的变量和方法
// createBaseContextForActivity 中会调用ContextImpl 的 createActivityContext 方法来创建 ContextImpl
3721 ContextImpl appContext = createBaseContextForActivity(r); // 1
3722 Activity activity = null;
3723 try {
3724 java.lang.ClassLoader cl = appContext.getClassLoader();
// 这里来创建 Activity 的实例
3725 activity = mInstrumentation.newActivity(
3726 cl, component.getClassName(), r.intent); // 2
3727 StrictMode.incrementExpectedActivityCount(activity.getClass());
3728 r.intent.setExtrasClassLoader(cl);
3729 r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
3730 appContext.getAttributionSource());
3731 if (r.state != null) {
3732 r.state.setClassLoader(cl);
3733 }
3734 } catch (Exception e) {
3735 if (!mInstrumentation.onException(activity, e)) {
3736 throw new RuntimeException(
3737 "Unable to instantiate activity " + component
3738 + ": " + e.toString(), e);
3739 }
3740 }
3741
3742 try {
3743 Application app = r.packageInfo.makeApplication(false, mInstrumentation);
3744
3745 if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
3746 if (localLOGV) Slog.v(
3747 TAG, r + ": app=" + app
3748 + ", appName=" + app.getPackageName()
3749 + ", pkg=" + r.packageInfo.getPackageName()
3750 + ", comp=" + r.intent.getComponent().toShortString()
3751 + ", dir=" + r.packageInfo.getAppDir());
3752
3753 if (activity != null) {
3754 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
3755 Configuration config =
3756 new Configuration(mConfigurationController.getCompatConfiguration());
3757 if (r.overrideConfig != null) {
3758 config.updateFrom(r.overrideConfig);
3759 }
3760 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
3761 + r.activityInfo.name + " with config " + config);
3762 Window window = null;
3763 if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
3764 window = r.mPendingRemoveWindow;
3765 r.mPendingRemoveWindow = null;
3766 r.mPendingRemoveWindowManager = null;
3767 }
3768
3769 // Activity resources must be initialized with the same loaders as the
3770 // application context.
3771 appContext.getResources().addLoaders(
3772 app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
3773
3774 appContext.setOuterContext(activity); // 3
3775 activity.attach(appContext, this, getInstrumentation(), r.token,
3776 r.ident, app, r.intent, r.activityInfo, title, r.parent,
3777 r.embeddedID, r.lastNonConfigurationInstances, config,
3778 r.referrer, r.voiceInteractor, window, r.configCallback,
3779 r.assistToken, r.shareableActivityToken); // 4
3780
3781 if (customIntent != null) {
3782 activity.mIntent = customIntent;
3783 }
3784 r.lastNonConfigurationInstances = null;
3785 checkAndBlockForNetworkAccess();
3786 activity.mStartedActivity = false;
3787 int theme = r.activityInfo.getThemeResource();
3788 if (theme != 0) {
3789 activity.setTheme(theme);
3790 }
3791
3792 if (r.mActivityOptions != null) {
3793 activity.mPendingOptions = r.mActivityOptions;
3794 r.mActivityOptions = null;
3795 }
3796 activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
3797 activity.mCalled = false;
3798 if (r.isPersistable()) {
//调用 Activity 的 onCreate 方法
3799 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); // 5
3800 } else {
3801 mInstrumentation.callActivityOnCreate(activity, r.state);
3802 }
3803 if (!activity.mCalled) {
3804 throw new SuperNotCalledException(
3805 "Activity " + r.intent.getComponent().toShortString() +
3806 " did not call through to super.onCreate()");
3807 }
3808 r.activity = activity;
3809 mLastReportedWindowingMode.put(activity.getActivityToken(),
3810 config.windowConfiguration.getWindowingMode());
3811 }
3812 r.setState(ON_CREATE);
3813
3814 // updatePendingActivityConfiguration() reads from mActivities to update
3815 // ActivityClientRecord which runs in a different thread. Protect modifications to
3816 // mActivities to avoid race.
3817 synchronized (mResourcesManager) {
3818 mActivities.put(r.token, r);
3819 }
3820
3821 } catch (SuperNotCalledException e) {
3822 throw e;
3823
3824 } catch (Exception e) {
3825 if (!mInstrumentation.onException(activity, e)) {
3826 throw new RuntimeException(
3827 "Unable to start activity " + component
3828 + ": " + e.toString(), e);
3829 }
3830 }
3831
3832 return activity;
3833 }
Copy the code
(1) Attach a method to your Activity. (2) Attach a method to your Activity.
// frameworks/base/core/java/android/app/Activity.java final void attach(Context context, ActivityThread aThread, 8532 Instrumentation instr, IBinder token, int ident, 8533 Application application, Intent intent, ActivityInfo info, 8534 CharSequence title, Activity parent, String id, 8535 NonConfigurationInstances lastNonConfigurationInstances, 8536 Configuration config, String referrer, IVoiceInteractor voiceInteractor, 8537 Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken, 8538 IBinder shareableActivityToken) { 8539 attachBaseContext(context); // 1 8540 8541 mFragments.attachHost(null /*parent*/); 8542 // Create a PhoneWindow, which represents the application window. // PhoneWindow indirectly triggers many events when running, Events such as clicks, menu pop-ups, screen focus changes, etc. // these events need to be forwarded to the Activity associated with PhoneWindow // the forwarding operation is implemented through the window.callback interface. 8543 mWindow = new PhoneWindow(this, Window, activityConfigCallback); // 2 8544 mWindow.setWindowControllerCallback(mWindowControllerCallback); // Pass the current Activity through the Window setCallback method to PhoneWindow 8545 mwindow.setcallback (this); // 3 8546 mWindow.setOnWindowDismissedCallback(this); 8547 mWindow.getLayoutInflater().setPrivateFactory(this); 8548 if (info.softInputMode ! = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { 8549 mWindow.setSoftInputMode(info.softInputMode); 8550 } 8551 if (info.uiOptions ! = 0) { 8552 mWindow.setUiOptions(info.uiOptions); 8553 } 8554 mUiThread = Thread.currentThread(); 8555 8556 mMainThread = aThread; 8557 mInstrumentation = instr; 8558 mToken = token; 8559 mAssistToken = assistToken; 8560 mShareableActivityToken = shareableActivityToken; 8561 mIdent = ident; 8562 mApplication = application; 8563 mIntent = intent; 8564 mReferrer = referrer; 8565 mComponent = intent.getComponent(); 8566 mActivityInfo = info; 8567 mTitle = title; 8568 mParent = parent; 8569 mEmbeddedID = id; 8570 mLastNonConfigurationInstances = lastNonConfigurationInstances; 8571 if (voiceInteractor ! = null) { 8572 if (lastNonConfigurationInstances ! = null) { 8573 mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor; 8574 } else { 8575 mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this, 8576 Looper.myLooper()); // Set Windows Manager 8580 mwindow.setwinDowManager (8581) for PhoneWindow (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), 8582 mToken, mComponent.flattenToString(), 8583 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) ! = 0); // 4 8584 if (mParent ! = null) { 8585 mWindow.setContainer(mParent.getWindow()); 8586} // Get the WindowManager and assign it to the Activity member variable mWindowManager // so that it can be obtained in the Activity using the getWindowManager method WindowManager 8587 mWindowManager = mWindow.getWindowManager(); // 5 8588 mCurrentConfig = config; 8589 8590 mWindow.setColorMode(info.colorMode); 8591 mWindow.setPreferMinimalPostProcessing( 8592 (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) ! = 0); 8593 8594 setAutofillOptions(application.getAutofillOptions()); 8595 setContentCaptureOptions(application.getContentCaptureOptions()); 8596 8597 try { 8598 mClipboardManager = new ClipboardManager(context, null); 8599 } catch (Exception e) { 8600 Slog.w(TAG, "ClipboardManager get failed", e); 8601} 8602 8603}Copy the code
The attachBaseContext method at comment 1 is implemented in ContextThemeWrapper.
// frameworks/base/core/java/android/view/ContextThemeWrapper.java 86 protected void attachBaseContext(Context newBase) { 87 super.attachBaseContext(newBase); 88}Copy the code
The attachBaseContext method then calls the attachBaseContext method of ContextThemeWrapper’s parent ContextWrapper:
// frameworks/base/core/java/android/content/ContextWrapper.java 79 protected void attachBaseContext(Context base) { 80 if (mBase ! = null) { 81 throw new IllegalStateException("Base context already set"); 82} // Base refers to the Activity's ContextImpl // member variable mBase // so that ContextWrapper's functions can be handed over ContextImpl to handle 83 mBase = base; 84}Copy the code
When we call ContextWrapper’s getTheme method, we are calling ContextImpl’s getTheme method.
// frameworks/base/core/java/android/content/ContextWrapper.java 141 public Resources.Theme getTheme() { 142 return mBase.getTheme(); 143} 144Copy the code
conclusion
ContextImpl is created during the Activity launch and assigned to the ContextWrapper member variable mBase.
The Activity inherits from ContextWrapper’s subclass ContextThemeWrapper, so that methods defined in the Context can be used in the Activity.
5.5 Context Creation process of a Service
The Service Context creation process is similar to the Activity Context creation process. It is created during the Service startup process.
ActivityThread start the Service
The inner class ApplicationThread of ActivityThread calls the scheduleCreateService method to start the Service.
// frameworks/base/core/java/android/app/ActivityThread.java 1110 public final void scheduleCreateService(IBinder token, 1111 ServiceInfo info, CompatibilityInfo compatInfo, int processState) { 1112 updateProcessState(processState, false); 1113 CreateServiceData s = new CreateServiceData(); 1114 s.token = token; 1115 s.info = info; 1116 s.compatInfo = compatInfo; The sendMessage method sends a message of type CREATE_SERVICE to class H. The handleMessage method of class H handles the message of type CREATE_SERVICE sendMessage(H.CREATE_SERVICE, s); 1119} 1120Copy the code
The overall flow here is similar to the Activity Context creation:
// frameworks/base/core/java/android/app/ActivityThread.java private void handleCreateService(CreateServiceData data) { 4658 // If we are getting ready to gc after going to the background, well 4659 // we are back active so skip it. 4660 unscheduleGcIdler(); 4661 4662 LoadedApk packageInfo = getPackageInfoNoCheck( 4663 data.info.applicationInfo, data.compatInfo); 4664 Service service = null; 4665 try { 4666 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); 4667 4668 Application app = packageInfo.makeApplication(false, mInstrumentation); // 1 4669 4670 final java.lang.ClassLoader cl; 4671 if (data.info.splitName ! = null) { 4672 cl = packageInfo.getSplitClassLoader(data.info.splitName); 4673 } else { 4674 cl = packageInfo.getClassLoader(); 4675 } 4676 service = packageInfo.getAppFactory() 4677 .instantiateService(cl, data.info.name, data.intent); 4678 ContextImpl context = ContextImpl.getImpl(service 4679 .createServiceBaseContext(this, packageInfo)); 4680 if (data.info.splitName ! = null) { 4681 context = (ContextImpl) context.createContextForSplit(data.info.splitName); 4682 } 4683 if (data.info.attributionTags ! = null && data.info.attributionTags.length > 0) { 4684 final String attributionTag = data.info.attributionTags[0]; 4685 context = (ContextImpl) context.createAttributionContext(attributionTag); 4686 } 4687 // Service resources must be initialized with the same loaders as the application 4688 // context. 4689 context.getResources().addLoaders( 4690 app.getResources().getLoaders().toArray(new ResourcesLoader[0])); 4691 4692 context.setOuterContext(service); 4693 service.attach(context, this, data.info.name, data.token, app, 4694 ActivityManager.getService()); // 2 4695 //zte add for systrace tag 4696 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG 4697 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 4698 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "onCreate:" + service); 4699 } 4700 //zte add end 4701 service.onCreate(); 4702 mServicesData.put(data.token, data); 4703 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG 4704 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 4705 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 4706 } 4707 //zte add end 4708 mServices.put(data.token, service); 4709 try { 4710 ActivityManager.getService().serviceDoneExecuting( 4711 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); 4712 } catch (RemoteException e) { 4713 throw e.rethrowFromSystemServer(); 4714 } 4715 } catch (Exception e) { 4716 if (! mInstrumentation.onException(service, e)) { 4717 throw new RuntimeException( 4718 "Unable to create service " + data.info.name 4719 + ": " + e.toString(), e); 4720} 4721} 4722} 4723Copy the code