Android4.1 关于Rotation相关的Configuration整体分析2

114 篇文章 1 订阅

http://blog.csdn.net/siobhan/article/details/8564798

这篇文章继续当旋转手机的时候,系统会做什么操作去通知Activity要旋转界面了。

在上一篇文章中我们看到如果我们在Settings选中了“Auto-rotate”的时候,PhoneWindowManager调用updateOrientationListenerLp去SensorManager里面去注册一个Listener,这样当Sensor发生变化的时候,PhoneWindowManager就可以监听到并且调用回调onProposeRotationChanged。

1. MyOrientationListener.onProposeRotationChange

[java]  view plain copy
  1. class MyOrientationListener extends WindowOrientationListener {  
  2.       
  3.     @Override  
  4.     public void onProposedRotationChanged(int rotation) {  
  5.         if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);  
  6.         updateRotation(false);  
  7.     }  
  8. }  

2. PhoneWindowManager.updateRotation(boolean alwaysSendConfiguration)

    注意上面传下来的alwaysSendConfiguration是false。

[java]  view plain copy
  1. void updateRotation(boolean alwaysSendConfiguration) {  
  2.     try {  
  3.         //set orientation on WindowManager  
  4.         mWindowManager.updateRotation(alwaysSendConfiguration, false);  
  5.     } catch (RemoteException e) {  
  6.         // Ignore  
  7.     }  
  8. }  

3. WindowManagerService.updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout)

    alwaysSendConfiguration = false;

    forceRelayout = false;

    updateRotation中直接调用了updateRotatinUnchecked(false, false); 

    1. 在updateRotatinUnchecked中先通过updateRotationUncheckedLocked(false) 去检测是否Rotation发生改变了。

    2. performLayoutAndPlaceSurfacesLocked();  //这个函数太复杂....

    3. 如果Rotation发生变化了或者alwaysSendConfiguration为true,就sendNewConfiguration给AMS。

[java]  view plain copy
  1. public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {  
  2.     updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);  
  3. }  

[java]  view plain copy
  1. public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {  
  2.     boolean changed;  
  3.     synchronized(mWindowMap) {  
  4.         changed = updateRotationUncheckedLocked(false);  
  5.         if (!changed || forceRelayout) {  
  6.             getDefaultDisplayContentLocked().layoutNeeded = true;  
  7.             performLayoutAndPlaceSurfacesLocked();  
  8.         }  
  9.     }  
  10.   
  11.     if (changed || alwaysSendConfiguration) {  
  12.         sendNewConfiguration();  
  13.     }  
  14.     ... ...  
  15. }  

3.1 WindowManagerService.updateRotationUncheckedLocked(boolean inTransaction)  // inTrasaction = false

     1. 请求mPolicy.rotationForOrientationLw去获取当前的rotation

     2. 如果发现当然的mRotation与刚才取出来的rotation是一样的并且mAltOrientation跟刚才取出来的altOrientation是一样就返回false

         要不然就 rotation,altOrientation放在mRotation和mAltOrientation 中保存起来; 

     3. mPolicy.setRotationLw(mRotation); 把mRotation保存在mOrientationListener的mCurrentRotation中。

     4. computeScreenConfigurationLocked()调用这个函数主要是更新Screen size的信息,包括Rotation啊,width,height...

     5. mDisplayManagerService.performTraversalInTransactionFromWindowManager();

     6. 遍历所有windows,把有Surface的Window的mOrientationChanging设为true.

[java]  view plain copy
  1. public boolean updateRotationUncheckedLocked(boolean inTransaction) {  
  2.     ... ...  
  3.   
  4.     int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);  
  5.     boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(  
  6.             mForcedAppOrientation, rotation);  
  7.     ... ...  
  8.   
  9.     if (mRotation == rotation && mAltOrientation == altOrientation) {  
  10.         // No change.  
  11.         return false;  
  12.     }  
  13.     ... ...  
  14.   
  15.     mRotation = rotation;  
  16.     mAltOrientation = altOrientation;  
  17.     mPolicy.setRotationLw(mRotation);  
  18.   
  19.     mWindowsFreezingScreen = true;  
  20.     mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);  
  21.     mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),  
  22.             WINDOW_FREEZE_TIMEOUT_DURATION);  
  23.     mWaitingForConfig = true;  
  24.     getDefaultDisplayContentLocked().layoutNeeded = true;  
  25.     startFreezingDisplayLocked(inTransaction, 00);  
  26.     // startFreezingDisplayLocked can reset the ScreenRotationAnimation.  
  27.     screenRotationAnimation =  
  28.             mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);  
  29.   
  30.     // We need to update our screen size information to match the new  
  31.     // rotation.  Note that this is redundant with the later call to  
  32.     // sendNewConfiguration() that must be called after this function  
  33.     // returns...  however we need to do the screen size part of that  
  34.     // before then so we have the correct size to use when initializing  
  35.     // the rotation animation for the new rotation.  
  36.     computeScreenConfigurationLocked(null);  
  37.   
  38.     final DisplayContent displayContent = getDefaultDisplayContentLocked();  
  39.     final DisplayInfo displayInfo = displayContent.getDisplayInfo();  
  40.     if (!inTransaction) {  
  41.         if (SHOW_TRANSACTIONS) {  
  42.             Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");  
  43.         }  
  44.         Surface.openTransaction();  
  45.     }  
  46.     try {  
  47.         // NOTE: We disable the rotation in the emulator because  
  48.         //       it doesn't support hardware OpenGL emulation yet.  
  49.         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null  
  50.                 && screenRotationAnimation.hasScreenshot()) {  
  51.             if (screenRotationAnimation.setRotationInTransaction(  
  52.                     rotation, mFxSession,  
  53.                     MAX_ANIMATION_DURATION, mTransitionAnimationScale,  
  54.                     displayInfo.logicalWidth, displayInfo.logicalHeight)) {  
  55.                 updateLayoutToAnimationLocked();  
  56.             }  
  57.         }  
  58.   
  59.         mDisplayManagerService.performTraversalInTransactionFromWindowManager();  
  60.     } finally {  
  61.         if (!inTransaction) {  
  62.             Surface.closeTransaction();  
  63.             if (SHOW_LIGHT_TRANSACTIONS) {  
  64.                 Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");  
  65.             }  
  66.         }  
  67.     }  
  68.   
  69.     final WindowList windows = displayContent.getWindowList();  
  70.     for (int i = windows.size() - 1; i >= 0; i--) {  
  71.         WindowState w = windows.get(i);  
  72.         if (w.mHasSurface) {  
  73.             if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);  
  74.             w.mOrientationChanging = true;  
  75.             mInnerFields.mOrientationChangeComplete = false;  
  76.         }  
  77.     }  
  78.   
  79.     for (int i=mRotationWatchers.size()-1; i>=0; i--) {  
  80.         try {  
  81.             mRotationWatchers.get(i).onRotationChanged(rotation);  
  82.         } catch (RemoteException e) {  
  83.         }  
  84.     }  
  85.   
  86.     scheduleNotifyRotationChangedIfNeededLocked(displayContent, rotation);  
  87.   
  88.     return true;  
  89. }  

3.1.1 PhoneWindowManager.rotationForOrientationLw(int orientation, int lastRotation)

  1.  通过mOrientationListener.getPropsoeRotation() 从Sensor那边获取建议的Rotation,返回给sensorRotation.

  2.  定义一个perferredRotation,然后根据一系列的判断条件找到一个符合条件的Rotation赋值给perferredRotation, 

  3. 然后再根据传进来的应用程序自己设定的orientation,如果有设定强制哪种横竖屏方式就直接返回与横竖屏对应的Rotation,如果没有强制设定,默认就返回perferredRotation。

[java]  view plain copy
  1. public int rotationForOrientationLw(int orientation, int lastRotation) {  
  2.     ... ...  
  3.     synchronized (mLock) {  
  4.         int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1  
  5.         if (sensorRotation < 0) {  
  6.             sensorRotation = lastRotation;  
  7.         }  
  8.   
  9.         final int preferredRotation;  
  10.         if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {  
  11.             // Ignore sensor when lid switch is open and rotation is forced.  
  12.             preferredRotation = mLidOpenRotation;  
  13.         } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR  
  14.                 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {  
  15.             // Ignore sensor when in car dock unless explicitly enabled.  
  16.             // This case can override the behavior of NOSENSOR, and can also  
  17.             // enable 180 degree rotation while docked.  
  18.             preferredRotation = mCarDockEnablesAccelerometer  
  19.                     ? sensorRotation : mCarDockRotation;  
  20.         } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK  
  21.                 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK  
  22.                 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)  
  23.                 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {  
  24.             // Ignore sensor when in desk dock unless explicitly enabled.  
  25.             // This case can override the behavior of NOSENSOR, and can also  
  26.             // enable 180 degree rotation while docked.  
  27.             preferredRotation = mDeskDockEnablesAccelerometer  
  28.                     ? sensorRotation : mDeskDockRotation;  
  29.         } else if (mHdmiPlugged && mHdmiRotationLock) {  
  30.             // Ignore sensor when plugged into HDMI.  
  31.             // Note that the dock orientation overrides the HDMI orientation.  
  32.             preferredRotation = mHdmiRotation;  
  33.         } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE  
  34.                         && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER  
  35.                                 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))  
  36.                 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR  
  37.                 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR  
  38.                 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE  
  39.                 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {  
  40.             // Otherwise, use sensor only if requested by the application or enabled  
  41.             // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.  
  42.             if (mAllowAllRotations < 0) {  
  43.                 // Can't read this during init() because the context doesn't  
  44.                 // have display metrics at that time so we cannot determine  
  45.                 // tablet vs. phone then.  
  46.                 mAllowAllRotations = mContext.getResources().getBoolean(  
  47.                         com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;  
  48.             }  
  49.             if (sensorRotation != Surface.ROTATION_180  
  50.                     || mAllowAllRotations == 1  
  51.                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {  
  52.                 preferredRotation = sensorRotation;  
  53.             } else {  
  54.                 preferredRotation = lastRotation;  
  55.             }  
  56.         } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED  
  57.                 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {  
  58.             // Apply rotation lock.  Does not apply to NOSENSOR.  
  59.             // The idea is that the user rotation expresses a weak preference for the direction  
  60.             // of gravity and as NOSENSOR is never affected by gravity, then neither should  
  61.             // NOSENSOR be affected by rotation lock (although it will be affected by docks).  
  62.             preferredRotation = mUserRotation;  
  63.         } else {  
  64.             // No overriding preference.  
  65.             // We will do exactly what the application asked us to do.  
  66.             preferredRotation = -1;  
  67.         }  
  68.   
  69.         switch (orientation) {  
  70.             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:  
  71.                 // Return portrait unless overridden.  
  72.                 if (isAnyPortrait(preferredRotation)) {  
  73.                     return preferredRotation;  
  74.                 }  
  75.                 return mPortraitRotation;  
  76.   
  77.             case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:  
  78.                 // Return landscape unless overridden.  
  79.                 if (isLandscapeOrSeascape(preferredRotation)) {  
  80.                     return preferredRotation;  
  81.                 }  
  82.                 return mLandscapeRotation;  
  83.   
  84.             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:  
  85.                 // Return reverse portrait unless overridden.  
  86.                 if (isAnyPortrait(preferredRotation)) {  
  87.                     return preferredRotation;  
  88.                 }  
  89.                 return mUpsideDownRotation;  
  90.   
  91.             case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:  
  92.                 // Return seascape unless overridden.  
  93.                 if (isLandscapeOrSeascape(preferredRotation)) {  
  94.                     return preferredRotation;  
  95.                 }  
  96.                 return mSeascapeRotation;  
  97.   
  98.             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:  
  99.                 // Return either landscape rotation.  
  100.                 if (isLandscapeOrSeascape(preferredRotation)) {  
  101.                     return preferredRotation;  
  102.                 }  
  103.                 if (isLandscapeOrSeascape(lastRotation)) {  
  104.                     return lastRotation;  
  105.                 }  
  106.                 return mLandscapeRotation;  
  107.   
  108.             case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:  
  109.                 // Return either portrait rotation.  
  110.                 if (isAnyPortrait(preferredRotation)) {  
  111.                     return preferredRotation;  
  112.                 }  
  113.                 if (isAnyPortrait(lastRotation)) {  
  114.                     return lastRotation;  
  115.                 }  
  116.                 return mPortraitRotation;  
  117.   
  118.             default:  
  119.                 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,  
  120.                 // just return the preferred orientation we already calculated.  
  121.                 if (preferredRotation >= 0) {  
  122.                     return preferredRotation;  
  123.                 }  
  124.                 return Surface.ROTATION_0;  
  125.         }  
  126.     }  

3.2 WindowManagerService.performLayoutAndPlaceSurfacesLocked()

      1. 在performLayoutAndPlaceSurfacesLocked中就调用了一次performLayoutAndPlaceSurfacesLockedLoop()

[java]  view plain copy
  1. private final void performLayoutAndPlaceSurfacesLocked() {  
  2.     int loopCount = 6;  
  3.     do {  
  4.         mTraversalScheduled = false;  
  5.         performLayoutAndPlaceSurfacesLockedLoop();  
  6.         mH.removeMessages(H.DO_TRAVERSAL);  
  7.         loopCount--;  
  8.     } while (mTraversalScheduled && loopCount > 0);  
  9. }  


3.3 WindowManagerService.sendNewConfiguration() 

    1. 去调AMS的updateConfiguration.

[java]  view plain copy
  1. void sendNewConfiguration() {  
  2.     try {  
  3.         mActivityManager.updateConfiguration(null);  
  4.     } catch (RemoteException e) {  
  5.     }  
  6. }  

3.3.1 updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean persistent, boolean initLocale)

      先通过mWindowManager.computeNewConfiguration(); 去获取WMS中最新的configuration,然后通过mSystemThread.applyConfigurationToResources(configCopy);去更新AMS所在进程资源。

  1. 通过app.thread.scheduleConfigurationChanged(configCopy); 给让每个进程去update configuration

  2. 发送一个Intent.ACTION_CONFIGURATION_CHANGED的broadcast出去。

  3. starting = mMainStack.topRunningActivityLocked(null);

      kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
      mMainStack.ensureActivitiesVisibleLocked(starting, changes);

[java]  view plain copy
  1. boolean updateConfigurationLocked(Configuration values,  
  2.         ActivityRecord starting, boolean persistent, boolean initLocale) {  
  3.     // do nothing if we are headless  
  4.     if (mHeadless) return true;  
  5.   
  6.     int changes = 0;  
  7.       
  8.     boolean kept = true;  
  9.       
  10.     if (values != null) {  
  11.         Configuration newConfig = new Configuration(mConfiguration);  
  12.         changes = newConfig.updateFrom(values);  
  13.         if (changes != 0) {  
  14.             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {  
  15.                 Slog.i(TAG, "Updating configuration to: " + values);  
  16.             }  
  17.               
  18.             EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);  
  19.   
  20.             if (values.locale != null && !initLocale) {  
  21.                 saveLocaleLocked(values.locale,   
  22.                                  !values.locale.equals(mConfiguration.locale),  
  23.                                  values.userSetLocale);  
  24.             }  
  25.   
  26.             mConfigurationSeq++;  
  27.             if (mConfigurationSeq <= 0) {  
  28.                 mConfigurationSeq = 1;  
  29.             }  
  30.             newConfig.seq = mConfigurationSeq;  
  31.             mConfiguration = newConfig;  
  32.             Slog.i(TAG, "Config changed: " + newConfig);  
  33.   
  34.             final Configuration configCopy = new Configuration(mConfiguration);  
  35.               
  36.             // TODO: If our config changes, should we auto dismiss any currently  
  37.             // showing dialogs?  
  38.             mShowDialogs = shouldShowDialogs(newConfig);  
  39.   
  40.             AttributeCache ac = AttributeCache.instance();  
  41.             if (ac != null) {  
  42.                 ac.updateConfiguration(configCopy);  
  43.             }  
  44.   
  45.             // Make sure all resources in our process are updated  
  46.             // right now, so that anyone who is going to retrieve  
  47.             // resource values after we return will be sure to get  
  48.             // the new ones.  This is especially important during  
  49.             // boot, where the first config change needs to guarantee  
  50.             // all resources have that config before following boot  
  51.             // code is executed.  
  52.             mSystemThread.applyConfigurationToResources(configCopy);  
  53.   
  54.             if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {  
  55.                 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);  
  56.                 msg.obj = new Configuration(configCopy);  
  57.                 mHandler.sendMessage(msg);  
  58.             }  
  59.       
  60.             for (int i=mLruProcesses.size()-1; i>=0; i--) {  
  61.                 ProcessRecord app = mLruProcesses.get(i);  
  62.                 try {  
  63.                     if (app.thread != null) {  
  64.                         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "  
  65.                                 + app.processName + " new config " + mConfiguration);  
  66.                         app.thread.scheduleConfigurationChanged(configCopy);  
  67.                     }  
  68.                 } catch (Exception e) {  
  69.                 }  
  70.             }  
  71.             Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);  
  72.             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY  
  73.                     | Intent.FLAG_RECEIVER_REPLACE_PENDING  
  74.                     | Intent.FLAG_RECEIVER_FOREGROUND);  
  75.             broadcastIntentLocked(nullnull, intent, nullnull0nullnull,  
  76.                     nullfalsefalse, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);  
  77.             if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {  
  78.                 intent = new Intent(Intent.ACTION_LOCALE_CHANGED);  
  79.                 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);  
  80.                 broadcastIntentLocked(nullnull, intent,  
  81.                         nullnull0nullnull,  
  82.                         nullfalsefalse, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);  
  83.             }  
  84.         }  
  85.     }  
  86.       
  87.     if (changes != 0 && starting == null) {  
  88.         // If the configuration changed, and the caller is not already  
  89.         // in the process of starting an activity, then find the top  
  90.         // activity to check if its configuration needs to change.  
  91.         starting = mMainStack.topRunningActivityLocked(null);  
  92.     }  
  93.       
  94.     if (starting != null) {  
  95.         kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);  
  96.         // And we need to make sure at this point that all other activities  
  97.         // are made visible with the correct configuration.  
  98.         mMainStack.ensureActivitiesVisibleLocked(starting, changes);  
  99.     }  
  100.       
  101.     if (values != null && mWindowManager != null) {  
  102.         mWindowManager.setNewConfiguration(mConfiguration);  
  103.     }  
  104.       
  105.     return kept;  
  106. }  

3.3.1.1 ActivityThread.handleConfigurationChanged() 

    1.  applyConfigurationToResourcesLocked(config, compat);  // 更新该进程的资源相关的东西

    2.  performConfigurationChanged() // 调用callback的onConfigurationChanged

[java]  view plain copy
  1. final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {  
  2.   
  3.     int configDiff = 0;  
  4.   
  5.     synchronized (mPackages) {  
  6.         ... ...  
  7.         applyConfigurationToResourcesLocked(config, compat);  
  8.           
  9.         if (mConfiguration == null) {  
  10.             mConfiguration = new Configuration();  
  11.         }  
  12.         if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {  
  13.             return;  
  14.         }  
  15.         configDiff = mConfiguration.diff(config);  
  16.         mConfiguration.updateFrom(config);  
  17.         config = applyCompatConfiguration(mCurDefaultDisplayDpi);  
  18.     }  
  19.   
  20.     ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);  
  21.     ... ...  
  22.     if (callbacks != null) {  
  23.         final int N = callbacks.size();  
  24.         for (int i=0; i<N; i++) {  
  25.             performConfigurationChanged(callbacks.get(i), config);  
  26.         }  
  27.     }  
  28. }  

3.3.1.3 ActivityStack.ensureActivityConfigurationLocked(ActivityRecord r, int globalChanges)


[java]  view plain copy
  1. final boolean ensureActivityConfigurationLocked(ActivityRecord r,  
  2.         int globalChanges) {  
  3.     if (mConfigWillChange) {  
  4.         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  5.                 "Skipping config check (will change): " + r);  
  6.         return true;  
  7.     }  
  8.       
  9.     if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  10.             "Ensuring correct configuration: " + r);  
  11.       
  12.     // Short circuit: if the two configurations are the exact same  
  13.     // object (the common case), then there is nothing to do.  
  14.     Configuration newConfig = mService.mConfiguration;  
  15.     if (r.configuration == newConfig && !r.forceNewConfig) {  
  16.         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  17.                 "Configuration unchanged in " + r);  
  18.         return true;  
  19.     }  
  20.       
  21.     // We don't worry about activities that are finishing.  
  22.     if (r.finishing) {  
  23.         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  24.                 "Configuration doesn't matter in finishing " + r);  
  25.         r.stopFreezingScreenLocked(false);  
  26.         return true;  
  27.     }  
  28.       
  29.     // Okay we now are going to make this activity have the new config.  
  30.     // But then we need to figure out how it needs to deal with that.  
  31.     Configuration oldConfig = r.configuration;  
  32.     r.configuration = newConfig;  
  33.   
  34.     // Determine what has changed.  May be nothing, if this is a config  
  35.     // that has come back from the app after going idle.  In that case  
  36.     // we just want to leave the official config object now in the  
  37.     // activity and do nothing else.  
  38.     final int changes = oldConfig.diff(newConfig);  
  39.     if (changes == 0 && !r.forceNewConfig) {  
  40.         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  41.                 "Configuration no differences in " + r);  
  42.         return true;  
  43.     }  
  44.   
  45.     // If the activity isn't currently running, just leave the new  
  46.     // configuration and it will pick that up next time it starts.  
  47.     if (r.app == null || r.app.thread == null) {  
  48.         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  49.                 "Configuration doesn't matter not running " + r);  
  50.         r.stopFreezingScreenLocked(false);  
  51.         r.forceNewConfig = false;  
  52.         return true;  
  53.     }  
  54.       
  55.     // Figure out how to handle the changes between the configurations.  
  56.     if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {  
  57.         Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"  
  58.                 + Integer.toHexString(changes) + ", handles=0x"  
  59.                 + Integer.toHexString(r.info.getRealConfigChanged())  
  60.                 + ", newConfig=" + newConfig);  
  61.     }  
  62.     if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {  
  63.         // Aha, the activity isn't handling the change, so DIE DIE DIE.  
  64.         r.configChangeFlags |= changes;  
  65.         r.startFreezingScreenLocked(r.app, globalChanges);  
  66.         r.forceNewConfig = false;  
  67.         if (r.app == null || r.app.thread == null) {  
  68.             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  69.                     "Config is destroying non-running " + r);  
  70.             destroyActivityLocked(r, truefalse"config");  
  71.         } else if (r.state == ActivityState.PAUSING) {  
  72.             // A little annoying: we are waiting for this activity to  
  73.             // finish pausing.  Let's not do anything now, but just  
  74.             // flag that it needs to be restarted when done pausing.  
  75.             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  76.                     "Config is skipping already pausing " + r);  
  77.             r.configDestroy = true;  
  78.             return true;  
  79.         } else if (r.state == ActivityState.RESUMED) {  
  80.             // Try to optimize this case: the configuration is changing  
  81.             // and we need to restart the top, resumed activity.  
  82.             // Instead of doing the normal handshaking, just say  
  83.             // "restart!".  
  84.             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  85.                     "Config is relaunching resumed " + r);  
  86.             relaunchActivityLocked(r, r.configChangeFlags, true);  
  87.             r.configChangeFlags = 0;  
  88.         } else {  
  89.             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,  
  90.                     "Config is relaunching non-resumed " + r);  
  91.             relaunchActivityLocked(r, r.configChangeFlags, false);  
  92.             r.configChangeFlags = 0;  
  93.         }  
  94.           
  95.         // All done...  tell the caller we weren't able to keep this  
  96.         // activity around.  
  97.         return false;  
  98.     }  
  99.       
  100.     // Default case: the activity can handle this new configuration, so  
  101.     // hand it over.  Note that we don't need to give it the new  
  102.     // configuration, since we always send configuration changes to all  
  103.     // process when they happen so it can just use whatever configuration  
  104.     // it last got.  
  105.     if (r.app != null && r.app.thread != null) {  
  106.         try {  
  107.             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);  
  108.             r.app.thread.scheduleActivityConfigurationChanged(r.appToken);  
  109.         } catch (RemoteException e) {  
  110.             // If process died, whatever.  
  111.         }  
  112.     }  
  113.     r.stopFreezingScreenLocked(false);  
  114.       
  115.     return true;  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值