return true;
}
+ case UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final Configuration config = Configuration.CREATOR.createFromParcel(data);
+ final int displayId = data.readInt();
+ final boolean updated = updateDisplayOverrideConfiguration(config, displayId);
+ reply.writeNoException();
+ reply.writeInt(updated ? 1 : 0);
+ return true;
+ }
+
case SET_REQUESTED_ORIENTATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
data.recycle();
return res;
}
- public boolean updateConfiguration(Configuration values) throws RemoteException
- {
+ public boolean updateConfiguration(Configuration values) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
reply.recycle();
return updated;
}
+ public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ values.writeToParcel(data, 0);
+ data.writeInt(displayId);
+ mRemote.transact(UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean updated = reply.readInt() == 1;
+ data.recycle();
+ reply.recycle();
+ return updated;
+ }
public void setRequestedOrientation(IBinder token, int requestedOrientation)
throws RemoteException {
Parcel data = Parcel.obtain();
/**
* Updates global configuration and applies changes to the entire system.
- * @param values Update values for global configuration.
+ * @param values Update values for global configuration. If null is passed it will request the
+ * Window Manager to compute new config for the default display.
* @throws RemoteException
* @return Returns true if the configuration was updated.
*/
public boolean updateConfiguration(Configuration values) throws RemoteException;
+ /**
+ * Updates override configuration applied to specific display.
+ * @param values Update values for display configuration. If null is passed it will request the
+ * Window Manager to compute new config for the specified display.
+ * @param displayId Id of the display to apply the config to.
+ * @throws RemoteException
+ * @return Returns true if the configuration was updated.
+ */
+ public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId)
+ throws RemoteException;
+
public void setRequestedOrientation(IBinder token,
int requestedOrientation) throws RemoteException;
public int getRequestedOrientation(IBinder token) throws RemoteException;
int REQUEST_ACTIVITY_RELAUNCH = IBinder.FIRST_CALL_TRANSACTION+400;
int GET_DEFAULT_PICTURE_IN_PICTURE_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 401;
int GET_PICTURE_IN_PICTURE_MOVEMENT_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 402;
+ int UPDATE_DISPLAY_OVERRIDE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 403;
}
// If there is a change, the new Configuration is returned and the
// caller must call setNewConfiguration() sometime later.
Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
- IBinder freezeThisOneIfNeeded);
- // Notify window manager of the new configuration. Returns an array of stack ids that's
- // affected by the update, ActivityManager should resize these stacks.
- int[] setNewConfiguration(in Configuration config);
+ IBinder freezeThisOneIfNeeded, int displayId);
+ // Notify window manager of the new display override configuration. Returns an array of stack
+ // ids that were affected by the update, ActivityManager should resize these stacks.
+ int[] setNewDisplayOverrideConfiguration(in Configuration overrideConfig, int displayId);
// Retrieves the new bounds after the configuration update evaluated by window manager.
Rect getBoundsForNewConfiguration(int stackId);
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.Xml;
-import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
+import static android.Manifest.permission.CHANGE_CONFIGURATION;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.os.Build.VERSION_CODES.N;
import static android.os.Process.PROC_CHAR;
import static android.os.Process.PROC_OUT_LONG;
import static android.os.Process.PROC_PARENS;
import static android.provider.Settings.System.FONT_SCALE;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
private int mConfigurationSeq;
/**
- * Temp object used when global configuration is updated. It is also sent to outer world
- * instead of {@link #getGlobalConfiguration} because we don't trust anyone...
+ * Temp object used when global and/or display override configuration is updated. It is also
+ * sent to outer world instead of {@link #getGlobalConfiguration} because we don't trust
+ * anyone...
*/
- private Configuration mTempGlobalConfig = new Configuration();
+ private Configuration mTempConfig = new Configuration();
private final UpdateConfigurationResult mTmpUpdateConfigurationResult =
new UpdateConfigurationResult();
mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
- mTempGlobalConfig.setToDefaults();
- mTempGlobalConfig.setLocales(LocaleList.getDefault());
- mConfigurationSeq = mTempGlobalConfig.seq = 1;
+ mTempConfig.setToDefaults();
+ mTempConfig.setLocales(LocaleList.getDefault());
+ mConfigurationSeq = mTempConfig.seq = 1;
mProcessCpuTracker.init();
mStackSupervisor = new ActivityStackSupervisor(this);
- mStackSupervisor.onConfigurationChanged(mTempGlobalConfig);
+ mStackSupervisor.onConfigurationChanged(mTempConfig);
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mActivityStarter = new ActivityStarter(this, mStackSupervisor);
if (r == null) {
return;
}
- TaskRecord task = r.task;
- if (task != null && (!task.mFullscreen || !task.getStack().mFullscreen)) {
- // Fixed screen orientation isn't supported when activities aren't in full screen
- // mode.
- return;
- }
final long origId = Binder.clearCallingIdentity();
- mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
- Configuration config = mWindowManager.updateOrientationFromAppTokens(
- getGlobalConfiguration(), r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
- if (config != null) {
- r.frozenBeforeDestroy = true;
- if (!updateConfigurationLocked(config, r, false)) {
- mStackSupervisor.resumeFocusedStackTopActivityLocked();
- }
+ try {
+ r.setRequestedOrientation(requestedOrientation);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
- Binder.restoreCallingIdentity(origId);
}
}
}
if (dumpPackage == null) {
pw.println(" mGlobalConfiguration: " + getGlobalConfiguration());
+ mStackSupervisor.dumpDisplayConfigs(pw, " ");
}
if (dumpAll) {
pw.println(" mConfigWillChange: " + getFocusedStack().mConfigWillChange);
@Override
public void updatePersistentConfiguration(Configuration values) {
- enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
- "updatePersistentConfiguration()");
+ enforceCallingPermission(CHANGE_CONFIGURATION, "updatePersistentConfiguration()");
enforceWriteSettingsPermission("updatePersistentConfiguration()");
if (values == null) {
throw new NullPointerException("Configuration must not be null");
private void updateFontScaleIfNeeded(@UserIdInt int userId) {
final float scaleFactor = Settings.System.getFloatForUser(mContext.getContentResolver(),
FONT_SCALE, 1.0f, userId);
- if (getGlobalConfiguration().fontScale != scaleFactor) {
- final Configuration configuration = mWindowManager.computeNewConfiguration();
- configuration.fontScale = scaleFactor;
- synchronized (this) {
- updatePersistentConfigurationLocked(configuration, userId);
+
+ synchronized (this) {
+ if (getGlobalConfiguration().fontScale == scaleFactor) {
+ return;
}
+
+ final Configuration configuration
+ = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
+ configuration.fontScale = scaleFactor;
+ updatePersistentConfigurationLocked(configuration, userId);
}
}
@Override
public boolean updateConfiguration(Configuration values) {
- enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
- "updateConfiguration()");
+ enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
synchronized(this) {
if (values == null && mWindowManager != null) {
// sentinel: fetch the current configuration from the window manager
- values = mWindowManager.computeNewConfiguration();
+ values = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
}
if (mWindowManager != null) {
+ // Update OOM levels based on display size.
mProcessList.applyDisplaySize(mWindowManager);
}
final long origId = Binder.clearCallingIdentity();
-
try {
if (values != null) {
Settings.System.clearConfiguration(values);
/** Update default (global) configuration and notify listeners about changes. */
private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale,
boolean persistent, int userId, boolean deferResume) {
- mTempGlobalConfig.setTo(getGlobalConfiguration());
- final int changes = mTempGlobalConfig.updateFrom(values);
+ mTempConfig.setTo(getGlobalConfiguration());
+ final int changes = mTempConfig.updateFrom(values);
if (changes == 0) {
return 0;
}
}
mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
- mTempGlobalConfig.seq = mConfigurationSeq;
+ mTempConfig.seq = mConfigurationSeq;
// Update stored global config and notify everyone about the change.
- mStackSupervisor.onConfigurationChanged(mTempGlobalConfig);
+ mStackSupervisor.onConfigurationChanged(mTempConfig);
- Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempGlobalConfig);
+ Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
// TODO(multi-display): Update UsageEvents#Event to include displayId.
- mUsageStatsService.reportConfigurationChange(mTempGlobalConfig,
+ mUsageStatsService.reportConfigurationChange(mTempConfig,
mUserController.getCurrentUserIdLocked());
// TODO: If our config changes, should we auto dismiss any currently showing dialogs?
- mShowDialogs = shouldShowDialogs(mTempGlobalConfig, mInVrMode);
+ mShowDialogs = shouldShowDialogs(mTempConfig, mInVrMode);
AttributeCache ac = AttributeCache.instance();
if (ac != null) {
- ac.updateConfiguration(mTempGlobalConfig);
+ ac.updateConfiguration(mTempConfig);
}
// Make sure all resources in our process are updated right now, so that anyone who is going
// to retrieve resource values after we return will be sure to get the new ones. This is
// especially important during boot, where the first config change needs to guarantee all
// resources have that config before following boot code is executed.
- mSystemThread.applyConfigurationToResources(mTempGlobalConfig);
+ mSystemThread.applyConfigurationToResources(mTempConfig);
// We need another copy of global config because we're scheduling some calls instead of
// running them in place. We need to be sure that object we send will be handled unchanged.
- final Configuration configCopy = new Configuration(mTempGlobalConfig);
+ final Configuration configCopy = new Configuration(mTempConfig);
if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
msg.obj = configCopy;
mHandler.sendMessage(msg);
}
- // TODO(multi-display): Clear also on secondary display density change?
- final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
- if (isDensityChange) {
- // Reset the unsupported display size dialog.
- mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
-
- killAllBackgroundProcessesExcept(Build.VERSION_CODES.N,
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
- }
-
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord app = mLruProcesses.get(i);
try {
UserHandle.USER_ALL);
}
+ // Override configuration of the default display duplicates global config, so we need to
+ // update it also. This will also notify WindowManager about changes.
+ performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume,
+ DEFAULT_DISPLAY);
+
+ return changes;
+ }
+
+ @Override
+ public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId) {
+ enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
+
+ synchronized (this) {
+ if (values == null && mWindowManager != null) {
+ // sentinel: fetch the current configuration from the window manager
+ values = mWindowManager.computeNewConfiguration(displayId);
+ }
+
+ if (mWindowManager != null) {
+ // Update OOM levels based on display size.
+ mProcessList.applyDisplaySize(mWindowManager);
+ }
+
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ if (values != null) {
+ Settings.System.clearConfiguration(values);
+ }
+ updateDisplayOverrideConfigurationLocked(values, null /* starting */,
+ false /* deferResume */, displayId, mTmpUpdateConfigurationResult);
+ return mTmpUpdateConfigurationResult.changes != 0;
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ boolean updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean deferResume, int displayId) {
+ return updateDisplayOverrideConfigurationLocked(values, starting, deferResume /* deferResume */,
+ displayId, null /* result */);
+ }
+
+ /**
+ * Updates override configuration specific for the selected display. If no config is provided,
+ * new one will be computed in WM based on current display info.
+ */
+ private boolean updateDisplayOverrideConfigurationLocked(Configuration values,
+ ActivityRecord starting, boolean deferResume, int displayId,
+ UpdateConfigurationResult result) {
+ int changes = 0;
+ boolean kept = true;
+
+ if (mWindowManager != null) {
+ mWindowManager.deferSurfaceLayout();
+ }
+ try {
+ if (values != null) {
+ if (displayId == DEFAULT_DISPLAY) {
+ // Override configuration of the default display duplicates global config, so
+ // we're calling global config update instead for default display. It will also
+ // apply the correct override config.
+ changes = updateGlobalConfiguration(values, false /* initLocale */,
+ false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
+ } else {
+ changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);
+ }
+ }
+
+ kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ } finally {
+ if (mWindowManager != null) {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ if (result != null) {
+ result.changes = changes;
+ result.activityRelaunched = !kept;
+ }
+ return kept;
+ }
+
+ private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume,
+ int displayId) {
+ mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
+ final int changes = mTempConfig.updateFrom(values);
+ if (changes == 0) {
+ return 0;
+ }
+
+ Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " " + mTempConfig
+ + " for displayId=" + displayId);
+ mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
+
+ final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
+ if (isDensityChange) {
+ // Reset the unsupported display size dialog.
+ mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
+
+ killAllBackgroundProcessesExcept(N, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+ }
+
// Update the configuration with WM first and check if any of the stacks need to be resized
// due to the configuration change. If so, resize the stacks now and do any relaunches if
// necessary. This way we don't need to relaunch again afterwards in
// ensureActivityConfigurationLocked().
if (mWindowManager != null) {
final int[] resizedStacks =
- mWindowManager.setNewConfiguration(mTempGlobalConfig);
+ mWindowManager.setNewDisplayOverrideConfiguration(mTempConfig, displayId);
if (resizedStacks != null) {
for (int stackId : resizedStacks) {
resizeStackWithBoundsFromWindowManager(stackId, deferResume);
return null;
}
+ /**
+ * @return display id to which this record is attached, -1 if not attached.
+ */
+ int getDisplayId() {
+ final ActivityStack stack = getStack();
+ if (stack == null) {
+ return -1;
+ }
+ return stack.mDisplayId;
+ }
+
final boolean isDestroyable() {
if (finishing || app == null || state == ActivityState.DESTROYING
|| state == ActivityState.DESTROYED) {
}
}
+ void setRequestedOrientation(int requestedOrientation) {
+ if (task != null && (!task.mFullscreen || !task.getStack().mFullscreen)) {
+ // Fixed screen orientation isn't supported when activities aren't in full screen mode.
+ return;
+ }
+
+ service.mWindowManager.setAppOrientation(appToken, requestedOrientation);
+ final int displayId = getDisplayId();
+ final Configuration config = service.mWindowManager.updateOrientationFromAppTokens(
+ mStackSupervisor.getDisplayOverrideConfiguration(displayId),
+ mayFreezeScreenLocked(app) ? appToken : null, displayId);
+ if (config != null) {
+ frozenBeforeDestroy = true;
+ if (!service.updateDisplayOverrideConfigurationLocked(config, this,
+ false /* deferResume */, displayId)) {
+ mStackSupervisor.resumeFocusedStackTopActivityLocked();
+ }
+ }
+ }
+
// TODO: now used only in one place to address race-condition. Remove when that will be fixed.
void setLastReportedConfiguration(@NonNull Configuration config) {
mLastReportedConfiguration.setTo(config);
// the screen based on the new activity order.
boolean notUpdated = true;
if (mStackSupervisor.isFocusedStack(this)) {
- Configuration config = mWindowManager.updateOrientationFromAppTokens(
- mService.getGlobalConfiguration(),
- next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
+ final Configuration config = mWindowManager.updateOrientationFromAppTokens(
+ mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
+ next.mayFreezeScreenLocked(next.app) ? next.appToken : null, mDisplayId);
if (config != null) {
next.frozenBeforeDestroy = true;
}
- notUpdated = !mService.updateConfigurationLocked(config, next, false);
+ notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
+ false /* deferResume */, mDisplayId);
}
if (notUpdated) {
}
@Override
- protected ConfigurationContainer getChildAt(int index) {
+ protected ActivityDisplay getChildAt(int index) {
return mActivityDisplays.valueAt(index);
}
return null;
}
+ Configuration getDisplayOverrideConfiguration(int displayId) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay == null) {
+ throw new IllegalArgumentException("No display found with id: " + displayId);
+ }
+
+ return activityDisplay.getOverrideConfiguration();
+ }
+
+ void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay == null) {
+ throw new IllegalArgumentException("No display found with id: " + displayId);
+ }
+
+ activityDisplay.onOverrideConfigurationChanged(overrideConfiguration);
+ }
+
static class FindTaskResult {
ActivityRecord r;
boolean matchedByRootAffinity;
r.startLaunchTickingLocked();
}
- // Have the window manager re-evaluate the orientation of
- // the screen based on the new activity order. Note that
- // as a result of this, it can call back into the activity
- // manager with a new orientation. We don't care about that,
- // because the activity is not currently running so we are
- // just restarting it anyway.
+ // Have the window manager re-evaluate the orientation of the screen based on the new
+ // activity order. Note that as a result of this, it can call back into the activity
+ // manager with a new orientation. We don't care about that, because the activity is not
+ // currently running so we are just restarting it anyway.
if (checkConfig) {
- Configuration config = mWindowManager.updateOrientationFromAppTokens(
- mService.getGlobalConfiguration(),
- r.mayFreezeScreenLocked(app) ? r.appToken : null);
+ final int displayId = r.getDisplayId();
+ final Configuration config = mWindowManager.updateOrientationFromAppTokens(
+ getDisplayOverrideConfiguration(displayId),
+ r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused stack.
- mService.updateConfigurationLocked(config, r, false, true /* deferResume */);
+ mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
+ displayId);
}
r.app = app;
}
/**
+ * Dump all connected displays' configurations.
+ * @param prefix Prefix to apply to each line of the dump.
+ */
+ void dumpDisplayConfigs(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println("Display override configurations:");
+ final int displayCount = mActivityDisplays.size();
+ for (int i = 0; i < displayCount; i++) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.valueAt(i);
+ pw.print(prefix); pw.print(" "); pw.print(activityDisplay.mDisplayId); pw.print(": ");
+ pw.println(activityDisplay.getOverrideConfiguration());
+ }
+ }
+
+ /**
* Dumps the activities matching the given {@param name} in the either the focused stack
* or all visible stacks if {@param dumpVisibleStacks} is true.
*/
mService.updateFocusedWindowLocked(
UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
- mService.getDefaultDisplayContentLocked().setLayoutNeeded();
+ getDisplayContent().setLayoutNeeded();
mService.mWindowPlacerLocked.performSurfacePlacement();
Binder.restoreCallingIdentity(origId);
return true;
}
void notifyDockedStackExistsChanged(boolean exists) {
+ // TODO(multi-display): Perform all actions only for current display.
final int size = mDockedStackListeners.beginBroadcast();
for (int i = 0; i < size; ++i) {
final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
package com.android.server.wm;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
/* Notifies that the input device configuration has changed. */
@Override
public void notifyConfigurationChanged() {
- mService.sendNewConfiguration();
+ // TODO(multi-display): Notify proper displays that are associated with this input device.
+ mService.sendNewConfiguration(DEFAULT_DISPLAY);
synchronized (mInputDevicesReadyMonitor) {
if (!mInputDevicesReady) {
mService.configureDisplayPolicyLocked(dc);
// TODO(multi-display): Create an input channel for each display with touch capability.
- if (displayId == Display.DEFAULT_DISPLAY) {
+ if (displayId == DEFAULT_DISPLAY) {
dc.mTapDetector = new TaskTapPointerEventListener(
mService, dc);
mService.registerPointerEventListener(dc.mTapDetector);
mService.mStackIdToStack.put(stackId, stack);
if (stackId == DOCKED_STACK_ID) {
- mService.getDefaultDisplayContentLocked().mDividerControllerLocked
- .notifyDockedStackExistsChanged(true);
+ dc.mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
}
}
}
- /** Set new config and return array of ids of stacks that were changed during update. */
- int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
+ /**
+ * Set new display override config and return array of ids of stacks that were changed during
+ * update. If called for the default display, global configuration will also be updated.
+ */
+ int[] setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId) {
+ final DisplayContent displayContent = getDisplayContent(displayId);
+ if (displayContent == null) {
+ throw new IllegalArgumentException("Display not found for id: " + displayId);
+ }
+
+ final Configuration currentConfig = displayContent.getOverrideConfiguration();
+ final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
+ if (!configChanged) {
+ return null;
+ }
+ displayContent.onOverrideConfigurationChanged(currentConfig);
+
+ if (displayId == DEFAULT_DISPLAY) {
+ // Override configuration of the default display duplicates global config. In this case
+ // we also want to update the global config.
+ return setGlobalConfigurationIfNeeded(newConfiguration);
+ } else {
+ return updateStackBoundsAfterConfigChange(displayId);
+ }
+ }
+
+ private int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
if (!configChanged) {
return null;
return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
}
+ /** Same as {@link #updateStackBoundsAfterConfigChange()} but only for a specific display. */
+ private int[] updateStackBoundsAfterConfigChange(int displayId) {
+ mChangedStackList.clear();
+
+ final DisplayContent dc = getDisplayContent(displayId);
+ dc.updateStackBoundsAfterConfigChange(mChangedStackList);
+
+ return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
+ }
+
private void prepareFreezingTaskBounds() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
mChildren.get(i).prepareFreezingTaskBounds();
if (mUpdateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
- if (mService.updateRotationUncheckedLocked(false)) {
- mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+ // TODO(multi-display): Update rotation for different displays separately.
+ final int displayId = defaultDisplay.getDisplayId();
+ if (mService.updateRotationUncheckedLocked(false, displayId)) {
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
} else {
mUpdateRotation = false;
}
final int displayId = dc.getDisplayId();
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
- final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ final boolean isDefaultDisplay = (displayId == DEFAULT_DISPLAY);
final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
// Reset for each display.
if (isDefaultDisplay
&& (dc.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
- if (mService.updateOrientationFromAppTokensLocked(true)) {
+ if (mService.updateOrientationFromAppTokensLocked(true, displayId)) {
dc.setLayoutNeeded();
- mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
}
* the adjusted bounds's top.
*/
void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
- final Configuration overrideConfig = getOverrideConfiguration();
- if (!isResizeable() || Configuration.EMPTY.equals(overrideConfig)) {
+ // Task override config might be empty, while display or stack override config isn't, so
+ // we have to check merged override config here.
+ if (!isResizeable() || Configuration.EMPTY.equals(getMergedOverrideConfiguration())) {
return;
}
mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
}
setTempInsetBounds(tempInsetBounds);
- resizeLocked(mTmpRect2, overrideConfig, false /* forced */);
+ resizeLocked(mTmpRect2, getOverrideConfiguration(), false /* forced */);
}
/** Return true if the current bound can get outputted to the rest of the system as-is. */
// Calculate the current position.
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
- final int dividerSize = mService.getDefaultDisplayContentLocked()
- .getDockedDividerController().getContentWidth();
+ final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
final int dockSide = getDockSide(outBounds);
final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
dockSide, dividerSize);
mAnimationBackgroundSurface.destroySurface();
mAnimationBackgroundSurface = null;
}
+ final DockedStackDividerController dividerController =
+ mDisplayContent.mDividerControllerLocked;
mDisplayContent = null;
mService.mWindowPlacerLocked.requestTraversal();
if (mStackId == DOCKED_STACK_ID) {
- mService.getDefaultDisplayContentLocked().mDividerControllerLocked
- .notifyDockedStackExistsChanged(false);
+ dividerController.notifyDockedStackExistsChanged(false);
}
}
win.applyAdjustForImeIfNeeded();
if (type == TYPE_DOCK_DIVIDER) {
- getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win);
+ mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win);
}
final WindowStateAnimator winAnimator = win.mWinAnimator;
if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
+ client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
- if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
+ if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
reportNewConfig = true;
}
}
if (reportNewConfig) {
- sendNewConfiguration();
+ sendNewConfiguration(displayId);
}
Binder.restoreCallingIdentity(origId);
== PackageManager.PERMISSION_GRANTED;
long origId = Binder.clearCallingIdentity();
+ final int displayId;
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return 0;
}
+ displayId = win.getDisplayId();
WindowStateAnimator winAnimator = win.mWinAnimator;
if (viewVisibility != View.GONE) {
}
if (wallpaperMayMove) {
- getDefaultDisplayContentLocked().pendingLayoutChanges |=
+ win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
- configChanged = updateOrientationFromAppTokensLocked(false);
+ configChanged = updateOrientationFromAppTokensLocked(false, displayId);
mWindowPlacerLocked.performSurfacePlacement();
if (toBeDisplayed && win.mIsWallpaper) {
- DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
+ DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
dc.mWallpaperController.updateWallpaperOffset(
win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
}
}
if (configChanged) {
- sendNewConfiguration();
+ sendNewConfiguration(displayId);
}
Binder.restoreCallingIdentity(origId);
return result;
}
win.destroyOrSaveSurface();
}
- //TODO (multidisplay): Magnification is supported only for the default
- if (mAccessibilityController != null
- && win.getDisplayId() == DEFAULT_DISPLAY) {
+ // TODO(multidisplay): Magnification is supported only for the default display.
+ if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
mAccessibilityController.onWindowTransitionLocked(win, transit);
}
return focusMayChange;
}
}
- public void finishDrawingWindow(Session session, IWindow client) {
+ void finishDrawingWindow(Session session, IWindow client) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mWindowMap) {
+ (win != null ? win.mWinAnimator.drawStateToString() : "null"));
if (win != null && win.mWinAnimator.finishDrawingLocked()) {
if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
- getDefaultDisplayContentLocked().pendingLayoutChanges |=
+ win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
}
@Override
- public Configuration updateOrientationFromAppTokens(
- Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
+ public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
+ IBinder freezeThisOneIfNeeded, int displayId) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
- Configuration config = null;
- long ident = Binder.clearCallingIdentity();
-
- synchronized(mWindowMap) {
- config = updateOrientationFromAppTokensLocked(currentConfig,
- freezeThisOneIfNeeded);
+ final Configuration config;
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized(mWindowMap) {
+ config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
+ displayId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- Binder.restoreCallingIdentity(ident);
return config;
}
- private Configuration updateOrientationFromAppTokensLocked(
- Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
+ private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
+ IBinder freezeThisOneIfNeeded, int displayId) {
if (!mDisplayReady) {
return null;
}
Configuration config = null;
- if (updateOrientationFromAppTokensLocked(false)) {
+ if (updateOrientationFromAppTokensLocked(false, displayId)) {
// If we changed the orientation but mOrientationChangeComplete is already true,
// we used seamless rotation, and we don't need to freeze the screen.
if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
atoken.startFreezingScreen();
}
}
- config = computeNewConfigurationLocked();
+ config = computeNewConfigurationLocked(displayId);
} else if (currentConfig != null) {
// No obvious action we need to take, but if our current state mismatches the activity
// to keep override configs clear of non-empty values (e.g. fontSize).
mTempConfiguration.unset();
mTempConfiguration.updateFrom(currentConfig);
- computeScreenConfigurationLocked(mTempConfiguration);
+ computeScreenConfigurationLocked(mTempConfiguration, displayId);
if (currentConfig.diff(mTempConfiguration) != 0) {
mWaitingForConfig = true;
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
displayContent.setLayoutNeeded();
int anim[] = new int[2];
if (displayContent.isDimming()) {
return config;
}
- /*
- * Determine the new desired orientation of the display, returning
- * a non-null new Configuration if it has changed from the current
- * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
- * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
- * SCREEN. This will typically be done for you if you call
- * sendNewConfiguration().
+ /**
+ * Determine the new desired orientation of the display, returning a non-null new Configuration
+ * if it has changed from the current orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
+ * {@link #setNewDisplayOverrideConfiguration(Configuration, int)} TO TELL THE WINDOW MANAGER IT
+ * CAN UNFREEZE THE SCREEN. This will typically be done for you if you call
+ * {@link #sendNewConfiguration(int)}.
*
- * The orientation is computed from non-application windows first. If none of
- * the non-application windows specify orientation, the orientation is computed from
- * application tokens.
- * @see android.view.IWindowManager#updateOrientationFromAppTokens(
- * android.os.IBinder)
+ * The orientation is computed from non-application windows first. If none of the
+ * non-application windows specify orientation, the orientation is computed from application
+ * tokens.
+ * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
*/
- boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
+ boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
long ident = Binder.clearCallingIdentity();
try {
- // TODO: multi-display
- int req = getDefaultDisplayContentLocked().getOrientation();
+ final int req = mRoot.getDisplayContent(displayId).getOrientation();
if (req != mLastOrientation) {
mLastOrientation = req;
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
- if (updateRotationUncheckedLocked(inTransaction)) {
+ if (updateRotationUncheckedLocked(inTransaction, displayId)) {
// changed
return true;
}
}
@Override
- public int[] setNewConfiguration(Configuration config) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewConfiguration()")) {
+ public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
+ if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
}
- return mRoot.setGlobalConfigurationIfNeeded(config);
+ return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
}
}
}
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
- return screenshotApplicationsInner(null, DEFAULT_DISPLAY, -1, -1, true, 1f,
- Bitmap.Config.ARGB_8888, true);
+ return screenshotApplicationsInner(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
+ -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
+ Bitmap.Config.ARGB_8888, true /* wallpaperOnly */);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
- FgThread.getHandler().post(new Runnable() {
- @Override
- public void run() {
- Bitmap bm = screenshotApplicationsInner(null, DEFAULT_DISPLAY, -1, -1,
- true, 1f, Bitmap.Config.ARGB_8888, false);
- try {
- receiver.send(bm);
- } catch (RemoteException e) {
- }
+ FgThread.getHandler().post(() -> {
+ Bitmap bm = screenshotApplicationsInner(null /* appToken */, DEFAULT_DISPLAY,
+ -1 /* width */, -1 /* height */, true /* includeFullDisplay */,
+ 1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */);
+ try {
+ receiver.send(bm);
+ } catch (RemoteException e) {
}
});
if (mDeferredRotationPauseCount > 0) {
mDeferredRotationPauseCount -= 1;
if (mDeferredRotationPauseCount == 0) {
- boolean changed = updateRotationUncheckedLocked(false);
+ // TODO(multi-display): Update rotation for different displays separately.
+ final int displayId = DEFAULT_DISPLAY;
+ final boolean changed = updateRotationUncheckedLocked(false, displayId);
if (changed) {
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
}
}
}
- private void updateRotationUnchecked(boolean alwaysSendConfiguration,
- boolean forceRelayout) {
+ private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
if(DEBUG_ORIENTATION) Slog.v(TAG_WM, "updateRotationUnchecked:"
+ " alwaysSendConfiguration=" + alwaysSendConfiguration
+ " forceRelayout=" + forceRelayout);
try {
final boolean rotationChanged;
+ // TODO(multi-display): Update rotation for different displays separately.
+ int displayId = DEFAULT_DISPLAY;
synchronized (mWindowMap) {
- rotationChanged = updateRotationUncheckedLocked(false);
+ rotationChanged = updateRotationUncheckedLocked(false, displayId);
if (!rotationChanged || forceRelayout) {
getDefaultDisplayContentLocked().setLayoutNeeded();
mWindowPlacerLocked.performSurfacePlacement();
}
if (rotationChanged || alwaysSendConfiguration) {
- sendNewConfiguration();
+ sendNewConfiguration(displayId);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
-
- // TODO(multidisplay): Rotate any display?
/**
- * Updates the current rotation.
+ * Updates the current rotation of the specified display.
*
- * Returns true if the rotation has been changed. In this case YOU
- * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
+ * Returns true if the rotation has been changed. In this case YOU MUST CALL
+ * {@link #sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
*/
- boolean updateRotationUncheckedLocked(boolean inTransaction) {
+ boolean updateRotationUncheckedLocked(boolean inTransaction, int displayId) {
if (mDeferredRotationPauseCount > 0) {
// Rotation updates have been paused temporarily. Defer the update until
// updates have been resumed.
}
ScreenRotationAnimation screenRotationAnimation =
- mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
+ mAnimator.getScreenRotationAnimationLocked(displayId);
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
// Rotation updates cannot be performed while the previous rotation change
// animation is still in progress. Skip this update. We will try updating
return false;
}
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
final WindowList windows = displayContent.getWindowList();
final int oldRotation = mRotation;
startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
// startFreezingDisplayLocked can reset the ScreenRotationAnimation.
screenRotationAnimation =
- mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
+ mAnimator.getScreenRotationAnimationLocked(displayId);
} else {
// The screen rotation animation uses a screenshot to freeze the screen
// while windows resize underneath.
// the top of the method, the caller is obligated to call computeNewConfigurationLocked().
// By updating the Display info here it will be available to
// computeScreenConfigurationLocked later.
- updateDisplayAndOrientationLocked(mRoot.getConfiguration().uiMode);
+ updateDisplayAndOrientationLocked(displayContent.getConfiguration().uiMode, displayId);
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (!inTransaction) {
}
/**
- * Instruct the Activity Manager to fetch new configurations, update global configuration
- * and broadcast changes to config-changed listeners if appropriate.
+ * Instruct the Activity Manager to fetch and update the current display's configuration and
+ * broadcast them to config-changed listeners if appropriate.
* NOTE: Can't be called with the window manager lock held since it call into activity manager.
*/
- void sendNewConfiguration() {
+ void sendNewConfiguration(int displayId) {
try {
- final boolean configUpdated = mActivityManager.updateConfiguration(null);
+ final boolean configUpdated = mActivityManager.updateDisplayOverrideConfiguration(
+ null /* values */, displayId);
if (!configUpdated) {
// Something changed (E.g. device rotation), but no configuration update is needed.
// E.g. changing device rotation by 180 degrees. Go ahead and perform surface
if (mWaitingForConfig) {
mWaitingForConfig = false;
mLastFinishedFreezeSource = "config-unchanged";
- getDefaultDisplayContentLocked().setLayoutNeeded();
+ mRoot.getDisplayContent(displayId).setLayoutNeeded();
mWindowPlacerLocked.performSurfacePlacement();
}
}
}
}
- public Configuration computeNewConfiguration() {
+ public Configuration computeNewConfiguration(int displayId) {
synchronized (mWindowMap) {
- return computeNewConfigurationLocked();
+ return computeNewConfigurationLocked(displayId);
}
}
- private Configuration computeNewConfigurationLocked() {
+ private Configuration computeNewConfigurationLocked(int displayId) {
if (!mDisplayReady) {
return null;
}
- Configuration config = new Configuration();
- computeScreenConfigurationLocked(config);
+ final Configuration config = new Configuration();
+ computeScreenConfigurationLocked(config, displayId);
return config;
}
}
/** Do not call if mDisplayReady == false */
- DisplayInfo updateDisplayAndOrientationLocked(int uiMode) {
- // TODO(multidisplay): For now, apply Configuration to main screen only.
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ private DisplayInfo updateDisplayAndOrientationLocked(int uiMode, int displayId) {
+ final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
// Use the effective "visual" dimensions based on current rotation
final boolean rotated = (mRotation == Surface.ROTATION_90
}
/** Do not call if mDisplayReady == false */
- void computeScreenConfigurationLocked(Configuration config) {
- final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(
- config.uiMode);
+ private void computeScreenConfigurationLocked(Configuration config, int displayId) {
+ final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(config.uiMode, displayId);
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
View view = null;
try {
- final Configuration overrideConfig =
- wtoken != null ? wtoken.getMergedOverrideConfiguration() : null;
view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
- sd.windowFlags, overrideConfig);
+ sd.windowFlags, wtoken.getMergedOverrideConfiguration());
} catch (Exception e) {
Slog.w(TAG_WM, "Exception when adding starting window", e);
}
}
case SEND_NEW_CONFIGURATION: {
- removeMessages(SEND_NEW_CONFIGURATION);
- sendNewConfiguration();
+ removeMessages(SEND_NEW_CONFIGURATION, msg.obj);
+ final int displayId = (Integer) msg.obj;
+ sendNewConfiguration(displayId);
break;
}
configureDisplayPolicyLocked(displayContent);
displayContent.setLayoutNeeded();
- boolean configChanged = updateOrientationFromAppTokensLocked(false);
- final Configuration globalConfig = mRoot.getConfiguration();
- mTempConfiguration.setTo(globalConfig);
- computeScreenConfigurationLocked(mTempConfiguration);
- configChanged |= globalConfig.diff(mTempConfiguration) != 0;
+ final int displayId = displayContent.getDisplayId();
+ boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
+ displayId);
+ final Configuration currentDisplayConfig = displayContent.getConfiguration();
+ mTempConfiguration.setTo(currentDisplayConfig);
+ computeScreenConfigurationLocked(mTempConfiguration, displayId);
+ configChanged |= currentDisplayConfig.diff(mTempConfiguration) != 0;
if (configChanged) {
mWaitingForConfig = true;
- startFreezingDisplayLocked(false, 0, 0);
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
+ 0 /* enterAnim */);
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
mWindowPlacerLocked.performSurfacePlacement();
// to avoid inconsistent states. However, something interesting
// could have actually changed during that time so re-evaluate it
// now to catch that.
- configChanged = updateOrientationFromAppTokensLocked(false);
+ configChanged = updateOrientationFromAppTokensLocked(false, displayId);
// A little kludge: a lot could have happened while the
// display was frozen, so now that we are coming back we
if (updateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
- configChanged |= updateRotationUncheckedLocked(false);
+ configChanged |= updateRotationUncheckedLocked(false, displayId);
}
if (configChanged) {
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
}
if (DEBUG_ORIENTATION) {
Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
}
- if (updateRotationUncheckedLocked(false)) {
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ final int displayId = w.getDisplayId();
+ if (updateRotationUncheckedLocked(false, displayId)) {
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
}
}
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.TimeUtils;
-import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IApplicationToken;
//TODO (multidisplay): Accessibility supported only for the default display.
if (mService.mAccessibilityController != null
- && getDisplayContent().getDisplayId() == Display.DEFAULT_DISPLAY) {
+ && getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
// Visibility of the removed window. Will be used later to update orientation later on.
boolean wasVisible = false;
+ final int displayId = getDisplayId();
+
// First, see if we need to run an animation. If we do, we have to hold off on removing the
// window until the animation is done. If the display is frozen, just remove immediately,
// since the animation wouldn't be seen.
mAnimatingExit = true;
}
//TODO (multidisplay): Magnification is supported only for the default display.
- if (mService.mAccessibilityController != null
- && getDisplayId() == Display.DEFAULT_DISPLAY) {
+ if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
mService.mAccessibilityController.onWindowTransitionLocked(this, transit);
}
}
removeImmediately();
// Removing a visible window will effect the computed orientation
// So just update orientation if needed.
- if (wasVisible && mService.updateOrientationFromAppTokensLocked(false)) {
- mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+ if (wasVisible && mService.updateOrientationFromAppTokensLocked(false, displayId)) {
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
}
mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
Binder.restoreCallingIdentity(origId);
}
//TODO (multidisplay): Accessibility supported only for the default display.
- if (mService.mAccessibilityController != null
- && getDisplayId() == Display.DEFAULT_DISPLAY) {
+ if (mService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
import java.util.Timer;
import java.util.TimerTask;
+import static android.view.Display.DEFAULT_DISPLAY;
+
public final class SystemServer {
private static final String TAG = "SystemServer";
// Update the configuration for this context by hand, because we're going
// to start using it before the config change done in wm.systemReady() will
// propagate to it.
- Configuration config = wm.computeNewConfiguration();
+ final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
DisplayMetrics metrics = new DisplayMetrics();
WindowManager w = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
w.getDefaultDisplay().getMetrics(metrics);
import junit.framework.TestCase;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.view.Display.DEFAULT_DISPLAY;
/**
* TODO: Remove this. This is only a placeholder, need to implement this.
}
try {
- mWm.updateOrientationFromAppTokens(new Configuration(), null);
+ mWm.updateOrientationFromAppTokens(new Configuration(),
+ null /* freezeThisOneIfNeeded */, DEFAULT_DISPLAY);
fail("IWindowManager.updateOrientationFromAppTokens did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
}
@Override
- public int[] setNewConfiguration(Configuration arg0) throws RemoteException {
+ public int[] setNewDisplayOverrideConfiguration(Configuration arg0, int displayId)
+ throws RemoteException {
// TODO Auto-generated method stub
return null;
}
}
@Override
- public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1)
+ public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1, int arg2)
throws RemoteException {
// TODO Auto-generated method stub
return null;