ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> { synchronized (mResourcesManager) { // TODO (b/135719017): Temporary log for debugging IME service. if (Build.IS_DEBUGGABLE && mHasImeComponent) { Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, " + "config=" + globalConfig); }
// We need to apply this change to the resources immediately, because upon returning // the view hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig, null/* compat */)) { updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(), mResourcesManager.getConfiguration().getLocales());
// This actually changed the resources! Tell everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(globalConfig)) { mPendingConfiguration = globalConfig; sendMessage(H.CONFIGURATION_CHANGED, globalConfig); } } } }; ViewRootImpl.addConfigCallback(configChangedCallback); }
查阅ActivityManagerService
@Override publicfinalvoidattachApplication(IApplicationThread thread, long startSeq){ if (thread == null) { thrownew SecurityException("Invalid application interface"); } synchronized (this) { int callingPid = Binder.getCallingPid(); finalint callingUid = Binder.getCallingUid(); finallong origId = Binder.clearCallingIdentity();
privatebooleanattachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq){
... 代码省略
if (app.isolatedEntryPoint != null) { // 这里是孤立进程入口,它不应被绑定到应用程序上 // This is an isolated process which should just call an entry point instead of // being bound to an application. thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } elseif (instr2 != null) { // 这里的命中条件是活动的Instrumentation如果存在,也就是当前应用已经打开 ... ... } else { // 对于首次进入的应用进程走这里 thread.bindApplication(processName, appInfo, providerList, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, autofillOptions, contentCaptureOptions, app.mDisabledCompatChanges); }
// don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } }
// Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { thrownew RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { thrownew RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } }
// Preload fonts resources FontsContract.setApplicationContextForResources(appContext); if (!Process.isIsolated()) { try { final ApplicationInfo info = getPackageManager().getApplicationInfo( data.appInfo.packageName, PackageManager.GET_META_DATA /*flags*/, UserHandle.myUserId()); if (info.metaData != null) { finalint preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { data.info.getResources().preloadFonts(preloadedFontsResource); } } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }