diff options
| author | 2017-05-10 14:45:34 +0000 | |
|---|---|---|
| committer | 2017-05-10 14:45:39 +0000 | |
| commit | 8a698a17215919e6ce575ec80d091381f0482d27 (patch) | |
| tree | 26c285f66203540cb73d6cceafe0740dfd5dc235 | |
| parent | b94abe5e30f9be317cee31331e15fa1fab7898fc (diff) | |
| parent | 39791594560b2326625b663ed6796882900c220f (diff) | |
Merge "Prevent non-fullscreen activities from influencing orientation" into oc-dev
5 files changed, 59 insertions, 14 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 26ac6adce95d..4dea0e046f5a 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -131,6 +131,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import static android.os.Build.VERSION_CODES.O; import static java.lang.Character.MIN_VALUE; /** @@ -974,6 +975,18 @@ public class Activity extends ContextThemeWrapper @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); + + if (getApplicationInfo().targetSdkVersion >= O && mActivityInfo.isFixedOrientation()) { + final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window); + final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta); + ta.recycle(); + + if (isTranslucentOrFloating) { + throw new IllegalStateException( + "Only fullscreen opaque activities can request orientation"); + } + } + if (mLastNonConfigurationInstances != null) { mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders); } diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 587ab3b3b743..9a014766c206 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration.NativeConfig; +import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; import android.util.Printer; @@ -440,7 +441,6 @@ public class ActivityInfo extends ComponentInfo * @hide */ public static final int FLAG_SUPPORTS_PICTURE_IN_PICTURE = 0x400000; - /** * @hide Bit in {@link #flags}: If set, this component will only be seen * by the system user. Only works with broadcast receivers. Set from the @@ -978,12 +978,20 @@ public class ActivityInfo extends ComponentInfo * Returns true if the activity's orientation is fixed. * @hide */ - boolean isFixedOrientation() { + public boolean isFixedOrientation() { return isFixedOrientationLandscape() || isFixedOrientationPortrait() || screenOrientation == SCREEN_ORIENTATION_LOCKED; } /** + * Returns true if the specified orientation is considered fixed. + * @hide + */ + static public boolean isFixedOrientation(int orientation) { + return isFixedOrientationLandscape(orientation) || isFixedOrientationPortrait(orientation); + } + + /** * Returns true if the activity's orientation is fixed to landscape. * @hide */ @@ -1162,6 +1170,25 @@ public class ActivityInfo extends ComponentInfo dest.writeFloat(maxAspectRatio); } + /** + * Determines whether the {@link Activity} is considered translucent or floating. + * @hide + */ + public static boolean isTranslucentOrFloating(TypedArray attributes) { + final boolean isTranslucent = + attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, + false); + final boolean isSwipeToDismiss = !attributes.hasValue( + com.android.internal.R.styleable.Window_windowIsTranslucent) + && attributes.getBoolean( + com.android.internal.R.styleable.Window_windowSwipeToDismiss, false); + final boolean isFloating = + attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, + false); + + return isFloating || isTranslucent || isSwipeToDismiss; + } + public static final Parcelable.Creator<ActivityInfo> CREATOR = new Parcelable.Creator<ActivityInfo>() { public ActivityInfo createFromParcel(Parcel source) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index a5cfbcf30b3f..5c57be283793 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -131,6 +131,7 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Rect; +import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.IBinder; @@ -892,15 +893,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo Entry ent = AttributeCache.instance().get(packageName, realTheme, com.android.internal.R.styleable.Window, userId); - final boolean translucent = ent != null && (ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowIsTranslucent, false) - || (!ent.array.hasValue( - com.android.internal.R.styleable.Window_windowIsTranslucent) - && ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowSwipeToDismiss, - false))); - fullscreen = ent != null && !ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowIsFloating, false) && !translucent; + fullscreen = ent != null && !ActivityInfo.isTranslucentOrFloating(ent.array); noDisplay = ent != null && ent.array.getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, false); @@ -2186,6 +2179,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } void setRequestedOrientation(int requestedOrientation) { + if (ActivityInfo.isFixedOrientation(requestedOrientation) && !fullscreen + && appInfo.targetSdkVersion >= O) { + throw new IllegalStateException("Only fullscreen activities can request orientation"); + } + final int displayId = getDisplayId(); final Configuration displayConfig = mStackSupervisor.getDisplayOverrideConfiguration(displayId); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 640bac28efdf..982561c989ff 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -53,6 +53,7 @@ import android.app.Activity; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.Build; import android.os.Debug; import android.os.IBinder; import android.os.SystemClock; @@ -70,6 +71,8 @@ import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; +import static android.os.Build.VERSION_CODES.O; + class AppTokenList extends ArrayList<AppWindowToken> { } @@ -1245,7 +1248,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree */ @Override int getOrientation(int candidate) { - if (!fillsParent()) { + // We do not allow non-fullscreen apps to influence orientation at and beyond O. While we do + // throw an exception in {@link Activity#onCreate} and + // {@link Activity#setRequestedOrientation}, we also ignore the orientation here so that + // other calculations aren't affected. + if (!fillsParent() && mTargetSdk >= O) { // Can't specify orientation if app doesn't fill parent. return SCREEN_ORIENTATION_UNSET; } diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java index 876008b7412b..46f10c1959ff 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java @@ -173,8 +173,8 @@ public class AppWindowTokenTests extends WindowTestsBase { token.setOrientation(SCREEN_ORIENTATION_LANDSCAPE); token.setFillsParent(false); - // Can not specify orientation if app doesn't fill parent. - assertEquals(SCREEN_ORIENTATION_UNSET, token.getOrientation()); + // Can specify orientation if app doesn't fill parent. Allowed for SDK <= 25. + assertEquals(SCREEN_ORIENTATION_LANDSCAPE, token.getOrientation()); token.setFillsParent(true); token.hidden = true; |