Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Prevent non-fullscreen activities from influencing orientation
This changelist enforces that activities targeting O and beyond
can only specify an orientation if they are fullscreen. The
change ignores the orientation on the server side and throws an
exception when the client has an orientation set in onCreate or
invokes Activity#setRequestedOrientation.

Fixes: 33483680
Test: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerAppConfigurationTests#testNonFullscreenActivityProhibited
Test: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerAppConfigurationTests#testLegacyNonFullscreenActivityPermitted
Change-Id: I4f7f79744918fad6465a537633dfadec8d05c6df
  • Loading branch information
Bryce Lee committed May 9, 2017
1 parent dea0438 commit 3979159
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 14 deletions.
13 changes: 13 additions & 0 deletions core/java/android/app/Activity.java
Expand Up @@ -131,6 +131,7 @@
import java.util.HashMap;
import java.util.List;

import static android.os.Build.VERSION_CODES.O;
import static java.lang.Character.MIN_VALUE;

/**
Expand Down Expand Up @@ -974,6 +975,18 @@ public View getCurrentFocus() {
@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);
}
Expand Down
31 changes: 29 additions & 2 deletions core/java/android/content/pm/ActivityInfo.java
Expand Up @@ -20,6 +20,7 @@
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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -978,11 +978,19 @@ private String persistableModeToString() {
* 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
Expand Down Expand Up @@ -1162,6 +1170,25 @@ public void writeToParcel(Parcel dest, int parcelableFlags) {
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) {
Expand Down
16 changes: 7 additions & 9 deletions services/core/java/com/android/server/am/ActivityRecord.java
Expand Up @@ -131,6 +131,7 @@
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;
Expand Down Expand Up @@ -892,15 +893,7 @@ boolean isResolverActivity() {

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);

Expand Down Expand Up @@ -2188,6 +2181,11 @@ int getRequestedOrientation() {
}

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);
Expand Down
9 changes: 8 additions & 1 deletion services/core/java/com/android/server/wm/AppWindowToken.java
Expand Up @@ -53,6 +53,7 @@
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;
Expand All @@ -70,6 +71,8 @@
import java.util.ArrayDeque;
import java.util.ArrayList;

import static android.os.Build.VERSION_CODES.O;

class AppTokenList extends ArrayList<AppWindowToken> {
}

Expand Down Expand Up @@ -1245,7 +1248,11 @@ void onAppTransitionDone() {
*/
@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;
}
Expand Down
Expand Up @@ -173,8 +173,8 @@ public void testGetOrientation() throws Exception {
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());

This comment has been minimized.

Copy link
@rifalmyname

rifalmyname Nov 9, 2017

LTE 4G


token.setFillsParent(true);
token.hidden = true;
Expand Down

1 comment on commit 3979159

@rifalmyname
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LTE 4G

Please sign in to comment.