Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe12e780 authored by Louis Chang's avatar Louis Chang
Browse files

Ignore fixed-orientation request on large screen device for AE

Adding a property that can be used in application AndroidManifest
that allows apps to declare if ActivityEmbedding is enabled.

Ignore the activity fixed-orientation request while running the
Activity on large screen if the ActivityEmbedding is enabled and
the activity is declared to be fixed-orientation.

Also checking a new property to know if the device supports
ActivityEmbedding.

Bug: 235797785
Test: starting portrait app in landscape mode on large screen device
Test: atest ActivityRecordTests
Change-Id: Id0d3758b1291918288d565a1dfbbb9c21bd6044d
parent 7114f242
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -52380,6 +52380,7 @@ package android.view {
    method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
    method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
    method public void removeViewImmediate(android.view.View);
    method public void removeViewImmediate(android.view.View);
    field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
    field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
    field public static final String PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED = "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";
  }
  }
  public static class WindowManager.BadTokenException extends java.lang.RuntimeException {
  public static class WindowManager.BadTokenException extends java.lang.RuntimeException {
+22 −0
Original line number Original line Diff line number Diff line
@@ -860,6 +860,28 @@ public interface WindowManager extends ViewManager {
    String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE =
    String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE =
            "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
            "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";


    /**
     * Application level {@link android.content.pm.PackageManager.Property PackageManager
     * .Property} that an app can specify to inform the system that the app is ActivityEmbedding
     * split feature enabled.
     *
     * <p>With this property, the system could provide custom behaviors for the apps that are
     * ActivityEmbedding split feature enabled. For example, the fixed-portrait orientation
     * requests of the activities could be ignored by the system in order to provide seamless
     * ActivityEmbedding split experiences while holding the large-screen devices in landscape mode.
     *
     * <p><b>Syntax:</b>
     * <pre>
     * &lt;application&gt;
     *   &lt;property
     *     android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
     *     android:value="true|false"/&gt;
     * &lt;/application&gt;
     * </pre>
     */
    String PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED =
            "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";

    /**
    /**
     * Request for keyboard shortcuts to be retrieved asynchronously.
     * Request for keyboard shortcuts to be retrieved asynchronously.
     *
     *
+44 −0
Original line number Original line Diff line number Diff line
@@ -117,6 +117,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_UNSET;
import static android.view.WindowManager.TRANSIT_OLD_UNSET;
@@ -936,6 +937,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    // is launched from this ActivityRecord. Touches are always allowed within the same uid.
    // is launched from this ActivityRecord. Touches are always allowed within the same uid.
    int mAllowedTouchUid;
    int mAllowedTouchUid;


    // Whether the ActivityEmbedding is enabled on the app.
    private final boolean mAppActivityEmbeddingSplitsEnabled;

    private final Runnable mPauseTimeoutRunnable = new Runnable() {
    private final Runnable mPauseTimeoutRunnable = new Runnable() {
        @Override
        @Override
        public void run() {
        public void run() {
@@ -2127,6 +2131,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord);
        mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord);


        updateEnterpriseThumbnailDrawable(mAtmService.getUiContext());
        updateEnterpriseThumbnailDrawable(mAtmService.getUiContext());

        boolean appActivityEmbeddingEnabled = false;
        try {
            appActivityEmbeddingEnabled = WindowManagerService.sWindowExtensionsEnabled
                    && mAtmService.mContext.getPackageManager()
                            .getProperty(PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED, packageName)
                            .getBoolean();
        } catch (PackageManager.NameNotFoundException e) {
            // No such property name.
        }
        mAppActivityEmbeddingSplitsEnabled = appActivityEmbeddingEnabled;
    }
    }


    /**
    /**
@@ -7737,12 +7752,33 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        }
    }
    }


    /**
     * Ignores the activity orientation request if the App is fixed-orientation portrait and has
     * ActivityEmbedding enabled and is currently running on large screen display. Or the display
     * could be rotated to portrait and not having large enough width for app to split.
     */
    @VisibleForTesting
    boolean shouldIgnoreOrientationRequests() {
        if (!mAppActivityEmbeddingSplitsEnabled
                || !ActivityInfo.isFixedOrientationPortrait(mOrientation)
                || task.inMultiWindowMode()) {
            return false;
        }

        return getTask().getConfiguration().smallestScreenWidthDp
                >= mAtmService.mLargeScreenSmallestScreenWidthDp;
    }

    /**
    /**
     * We override because this class doesn't want its children affecting its reported orientation
     * We override because this class doesn't want its children affecting its reported orientation
     * in anyway.
     * in anyway.
     */
     */
    @Override
    @Override
    int getOrientation(int candidate) {
    int getOrientation(int candidate) {
        if (shouldIgnoreOrientationRequests()) {
            return SCREEN_ORIENTATION_UNSET;
        }

        if (candidate == SCREEN_ORIENTATION_BEHIND) {
        if (candidate == SCREEN_ORIENTATION_BEHIND) {
            // Allow app to specify orientation regardless of its visibility state if the current
            // Allow app to specify orientation regardless of its visibility state if the current
            // candidate want us to use orientation behind. I.e. the visible app on-top of this one
            // candidate want us to use orientation behind. I.e. the visible app on-top of this one
@@ -8256,6 +8292,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return orientationRespectedWithInsets;
        return orientationRespectedWithInsets;
    }
    }


    @Override
    boolean handlesOrientationChangeFromDescendant() {
        if (shouldIgnoreOrientationRequests()) {
            return false;
        }
        return super.handlesOrientationChangeFromDescendant();
    }

    /**
    /**
     * Computes bounds (letterbox or pillarbox) when either:
     * Computes bounds (letterbox or pillarbox) when either:
     * 1. The parent doesn't handle the orientation change and the requested orientation is
     * 1. The parent doesn't handle the orientation change and the requested orientation is
+10 −2
Original line number Original line Diff line number Diff line
@@ -168,7 +168,6 @@ import android.app.IActivityManager;
import android.app.IAssistDataReceiver;
import android.app.IAssistDataReceiver;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
@@ -178,7 +177,6 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal;
import android.content.pm.TestUtilityService;
import android.content.pm.TestUtilityService;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Bitmap;
@@ -436,6 +434,16 @@ public class WindowManagerService extends IWindowManager.Stub
    static final boolean ENABLE_FIXED_ROTATION_TRANSFORM =
    static final boolean ENABLE_FIXED_ROTATION_TRANSFORM =
            SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true);
            SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true);


    /**
     * Whether the device supports the WindowManager Extensions.
     * OEMs can enable this by having their device config to inherit window_extensions.mk, such as:
     * <pre>
     * $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
     * </pre>
     */
    static final boolean sWindowExtensionsEnabled =
            SystemProperties.getBoolean("persist.wm.extensions.enabled", false);

    // Enums for animation scale update types.
    // Enums for animation scale update types.
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
    @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
+4 −0
Original line number Original line Diff line number Diff line
@@ -2533,6 +2533,10 @@ public class ActivityRecordTests extends WindowTestsBase {
        // Can specify orientation if app doesn't occludes parent.
        // Can specify orientation if app doesn't occludes parent.
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, activity.getOrientation());
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, activity.getOrientation());


        doReturn(true).when(activity).shouldIgnoreOrientationRequests();
        assertEquals(SCREEN_ORIENTATION_UNSET, activity.getOrientation());

        doReturn(false).when(activity).shouldIgnoreOrientationRequests();
        activity.setOccludesParent(true);
        activity.setOccludesParent(true);
        activity.setVisible(false);
        activity.setVisible(false);
        activity.setVisibleRequested(false);
        activity.setVisibleRequested(false);