1. 当转屏时,系统会调用ams.setRequestedOrientation
public void setRequestedOrientation(IBinder token,
int requestedOrientation) {
synchronized (this) {
ActivityRecord r = mMainStack.isInStackLocked(token);
if (r == null) {
return;
}
......
mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mConfiguration,
r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
if (config != null) {
r.frozenBeforeDestroy = true;
if (!updateConfigurationLocked(config, r, false, false)) {
mMainStack.resumeTopActivityLocked(null);
}
}
......
}
}
2. 调用ams.updateConfigurationLocked
boolean updateConfigurationLocked(Configuration values,
......
boolean kept = true;
if (values != null) {
Configuration newConfig = new Configuration(mConfiguration);
changes = newConfig.updateFrom(values);
if (changes != 0) {
......
for (int i=mLruProcesses.size()-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
try {
if (app.thread != null) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
+ app.processName + " new config " + mConfiguration);
app.thread.scheduleConfigurationChanged(configCopy);
}
} catch (Exception e) {
}
}
......
}
if (changes != 0 && starting == null) {
// If the configuration changed, and the caller is not already
// in the process of starting an activity, then find the top
// activity to check if its configuration needs to change.
starting = mMainStack.topRunningActivityLocked(null);
}
if (starting != null) {
kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
mMainStack.ensureActivitiesVisibleLocked(starting, changes);
}
if (values != null && mWindowManager != null) {
mWindowManager.setNewConfiguration(mConfiguration);
}
return kept;
}
会调用activitythread.scheduleConfigurationChanged,在这个方法中会判断是否由Activity自己处理config change,如果是在Activity的confiChange中声明的则由Activity的onConfigChanged方法处理
接下来调用activitythread.scheduleConfigurationChanged,如果返回false则要销毁当前的activity,调用activitystack.relaunchActivityLocked销毁当前的activity,然后重新创建,;如果返回true则不会销毁当前的activity,进而就不会调用Activity的生命周期回调方法,当前发生改变的config是在Activity的configChange属性中声明的则说明由Activity的onConfigChanged来处理,不销毁当前activity
final boolean ensureActivityConfigurationLocked(ActivityRecord r,
int globalChanges) {
......
if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
// Aha, the activity isn't handling the change, so DIE DIE DIE.
r.configChangeFlags |= changes;
r.startFreezingScreenLocked(r.app, globalChanges);
r.forceNewConfig = false;
if (r.app == null || r.app.thread == null) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Config is destroying non-running " + r);
destroyActivityLocked(r, true, false, "config");
} else if (r.state == ActivityState.PAUSING) {
// A little annoying: we are waiting for this activity to
// finish pausing. Let's not do anything now, but just
// flag that it needs to be restarted when done pausing.
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Config is skipping already pausing " + r);
r.configDestroy = true;
return true;
} else if (r.state == ActivityState.RESUMED) {
// Try to optimize this case: the configuration is changing
// and we need to restart the top, resumed activity.
// Instead of doing the normal handshaking, just say
// "restart!".
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Config is relaunching resumed " + r);
//销毁重建
relaunchActivityLocked(r, r.configChangeFlags, true);
r.configChangeFlags = 0;
} else {
//销毁重建
relaunchActivityLocked(r, r.configChangeFlags, false);
r.configChangeFlags = 0;
}
// All done... tell the caller we weren't able to keep this
// activity around.
return false;
}
......
return true;
}
3. 在ams.updateConfigurationLocked返回false的情况下(即创建新的Activity),调用activitystack.resumeTopActivityLocked显示新创建的Activity