From d4b1d1ee725afbac1c316d4bf6ee721853bde9b6 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Mon, 10 Apr 2017 06:35:59 -0700 Subject: [PATCH] Don't send configuration that app doesn't support to it. If an app doesn't support the current device orientation configuration, then don't run the app in that configuration. Instead have the run in the last configuration that it supports. This mostly fixes transient cases where there is a short window that the device is switching configuration and the app could be sent the single incorrect configuration that is quickly corrected Test: Will be added soon. Fixes: 36897968 Change-Id: I030a04200fdf33c4c1938bda980ea8c14aa1c736 --- .../java/android/content/pm/ActivityInfo.java | 32 ++++++++--- .../com/android/server/am/ActivityRecord.java | 57 ++++++++++++++++--- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 0be0885c5bdcf..56233819f5b1b 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -985,10 +985,18 @@ public class ActivityInfo extends ComponentInfo * @hide */ boolean isFixedOrientationLandscape() { - return screenOrientation == SCREEN_ORIENTATION_LANDSCAPE - || screenOrientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE - || screenOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE - || screenOrientation == SCREEN_ORIENTATION_USER_LANDSCAPE; + return isFixedOrientationLandscape(screenOrientation); + } + + /** + * Returns true if the activity's orientation is fixed to landscape. + * @hide + */ + public static boolean isFixedOrientationLandscape(@ScreenOrientation int orientation) { + return orientation == SCREEN_ORIENTATION_LANDSCAPE + || orientation == SCREEN_ORIENTATION_SENSOR_LANDSCAPE + || orientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE + || orientation == SCREEN_ORIENTATION_USER_LANDSCAPE; } /** @@ -996,10 +1004,18 @@ public class ActivityInfo extends ComponentInfo * @hide */ boolean isFixedOrientationPortrait() { - return screenOrientation == SCREEN_ORIENTATION_PORTRAIT - || screenOrientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT - || screenOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT - || screenOrientation == SCREEN_ORIENTATION_USER_PORTRAIT; + return isFixedOrientationPortrait(screenOrientation); + } + + /** + * Returns true if the activity's orientation is fixed to portrait. + * @hide + */ + public static boolean isFixedOrientationPortrait(@ScreenOrientation int orientation) { + return orientation == SCREEN_ORIENTATION_PORTRAIT + || orientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT + || orientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT + || orientation == SCREEN_ORIENTATION_USER_PORTRAIT; } /** diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 158175f4b0d95..a2384dcb95435 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -61,6 +61,8 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; +import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; +import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; import static android.content.res.Configuration.EMPTY; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -2222,15 +2224,19 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } @Override - void onOverrideConfigurationChanged(Configuration overrideConfiguration) { - super.onOverrideConfigurationChanged(overrideConfiguration); - if (mWindowContainerController != null) { - mWindowContainerController.onOverrideConfigurationChanged( - overrideConfiguration, mBounds); - // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent() - // to just use this method instead? - onOverrideConfigurationSent(); + void onOverrideConfigurationChanged(Configuration newConfig) { + final Configuration currentConfig = getOverrideConfiguration(); + if (currentConfig.equals(newConfig)) { + return; } + super.onOverrideConfigurationChanged(newConfig); + if (mWindowContainerController == null) { + return; + } + mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds); + // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent() + // to just use this method instead? + onOverrideConfigurationSent(); } // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. @@ -2238,6 +2244,26 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo mTmpConfig.unset(); computeBounds(mTmpBounds); if (mTmpBounds.equals(mBounds)) { + final ActivityStack stack = getStack(); + if (!mBounds.isEmpty() || task == null || stack == null || !task.mFullscreen) { + // We don't want to influence the override configuration here if our task is in + // multi-window mode or there is a bounds specified to calculate the override + // config. In both of this cases the app should be compatible with whatever the + // current configuration is or will be. + return; + } + + // Currently limited to the top activity for now to avoid situations where non-top + // visible activity and top might have conflicting requests putting the non-top activity + // windows in an odd state. + final ActivityRecord top = mStackSupervisor.topRunningActivityLocked(); + final Configuration parentConfig = getParent().getConfiguration(); + if (top != this || isConfigurationCompatible(parentConfig)) { + onOverrideConfigurationChanged(mTmpConfig); + } else if (isConfigurationCompatible( + mLastReportedConfiguration.getMergedConfiguration())) { + onOverrideConfigurationChanged(mLastReportedConfiguration.getMergedConfiguration()); + } return; } @@ -2250,6 +2276,21 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo onOverrideConfigurationChanged(mTmpConfig); } + /** Returns true if the configuration is compatible with this activity. */ + private boolean isConfigurationCompatible(Configuration config) { + final int orientation = mWindowContainerController != null + ? mWindowContainerController.getOrientation() : info.screenOrientation; + if (isFixedOrientationPortrait(orientation) + && config.orientation != ORIENTATION_PORTRAIT) { + return false; + } + if (isFixedOrientationLandscape(orientation) + && config.orientation != ORIENTATION_LANDSCAPE) { + return false; + } + return true; + } + /** * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}. */