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:

  1. Use Context to invoke methods, such as starting an Activity, accessing resources, calling system-level services, and so on.
  2. 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:

  1. Users (such as Servcice) can easily use the Context.
  2. If ContextImpl changes, its decorator class ContextWrapper does not need to be modified.
  3. The implementation of the ContextImpl is not exposed to the consumer, nor should the consumer care about the implementation.
  4. 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