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

Commit b77e62cf authored by Vali Calinescu's avatar Vali Calinescu
Browse files

Merge compat fake focus properties into one

Merge PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN/OUT properties into PROPERTY_COMPAT_ENABLE_FAKE_FOCUS and move to WindowManager class to be consistent with other existing properties in WindowManager and also in anticipation of us making those public APIs in Android U.

Fix: 263987615
Test: atest WmTests:LetterboxUiControllerTest
atest WmTests:LetterboxConfigurationTest
atest WmTests:SizeCompatTests#testShouldSendFakeFocus_compatFakeFocusEnabled
atest WmTests:SizeCompatTests#testShouldSendFakeFocus_compatFakeFocusDisabled

Change-Id: Ic10b3a25e3a8bcef25be27b549148d36a2192fbc
parent 958993bf
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -852,6 +852,43 @@ public interface WindowManager extends ViewManager {
    String PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION =
            "android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION";

    /**
     * Application level {@link android.content.pm.PackageManager.Property PackageManager
     * .Property} for an app to inform the system that the application can be opted-in or opted-out
     * from the compatibility treatment that enables sending a fake focus event for unfocused
     * resumed split screen activities. This is needed because some game engines wait to get
     * focus before drawing the content of the app which isn't guaranteed by default in multi-window
     * modes.
     *
     * <p>Device manufacturers can enable this treatment using their discretion on a per-device
     * basis to improve display compatibility. The treatment also needs to be specifically enabled
     * on a per-app basis afterwards. This can either be done by device manufacturers or developers.
     *
     * <p>With this property set to {@code true}, the system will apply the treatment only if the
     * device manufacturer had previously enabled it on the device. A fake focus event will be sent
     * to the app after it is resumed only if the app is in split-screen.
     *
     * <p>Setting this property to {@code false} informs the system that the activity must be
     * opted-out from the compatibility treatment even if the device manufacturer has opted the app
     * into the treatment.
     *
     * <p>If the property remains unset the system will apply the treatment only if it had
     * previously been enabled both at the device and app level by the device manufacturer.
     *
     * <p><b>Syntax:</b>
     * <pre>
     * &lt;application&gt;
     *   &lt;property
     *     android:name="android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS"
     *     android:value="true|false"/&gt;
     * &lt;/application&gt;
     * </pre>
     *
     * @hide
     */
    // TODO(b/263984287): Make this public API.
    String PROPERTY_COMPAT_ENABLE_FAKE_FOCUS = "android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS";

    /**
     * Application level {@link android.content.pm.PackageManager.Property PackageManager
     * .Property} for an app to inform the system that the app should be excluded from the
+2 −2
Original line number Diff line number Diff line
@@ -10214,8 +10214,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    // TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when
    // covered with bubbles.
    boolean shouldSendCompatFakeFocus() {
        return mWmService.mLetterboxConfiguration.isCompatFakeFocusEnabled(info)
                && inMultiWindowMode() && !inPinnedWindowingMode() && !inFreeformWindowingMode();
        return mLetterboxUiController.shouldSendFakeFocus() && inMultiWindowMode()
                && !inPinnedWindowingMode() && !inFreeformWindowingMode();
    }

    static class Builder {
+1 −33
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.provider.DeviceConfig;
import android.util.Slog;
@@ -1062,38 +1060,8 @@ final class LetterboxConfiguration {
                "enable_translucent_activity_letterbox", false);
    }

    @VisibleForTesting
    boolean getPackageManagerProperty(PackageManager pm, String property) {
        boolean enabled = false;
        try {
            final PackageManager.Property p = pm.getProperty(property, mContext.getPackageName());
            enabled = p.getBoolean();
        } catch (PackageManager.NameNotFoundException e) {
            // Property not found
        }
        return enabled;
    }

    @VisibleForTesting
    boolean isCompatFakeFocusEnabled(ActivityInfo info) {
        if (!isCompatFakeFocusEnabledOnDevice()) {
            return false;
        }
        // See if the developer has chosen to opt in / out of treatment
        PackageManager pm = mContext.getPackageManager();
        if (getPackageManagerProperty(pm, PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT)) {
            return false;
        } else if (getPackageManagerProperty(pm, PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN)) {
            return true;
        }
        if (info.isChangeEnabled(ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS)) {
            return true;
        }
        return false;
    }

    /** Whether fake sending focus is enabled for unfocused apps in splitscreen */
    boolean isCompatFakeFocusEnabledOnDevice() {
    boolean isCompatFakeFocusEnabled() {
        return mIsCompatFakeFocusEnabled
                && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                        DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, true);
+34 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
@@ -41,6 +42,7 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH;
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;

import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
@@ -149,6 +151,9 @@ final class LetterboxUiController {
    // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION
    private final boolean mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled;

    // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS
    private final boolean mIsOverrideEnableCompatFakeFocusEnabled;

    @Nullable
    private final Boolean mBooleanPropertyAllowOrientationOverride;
    @Nullable
@@ -204,6 +209,9 @@ final class LetterboxUiController {
    @Nullable
    private final Boolean mBooleanPropertyIgnoreRequestedOrientation;

    @Nullable
    private final Boolean mBooleanPropertyFakeFocus;

    private boolean mIsRelauchingAfterRequestedOrientationChanged;

    LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) {
@@ -218,6 +226,10 @@ final class LetterboxUiController {
                readComponentProperty(packageManager, mActivityRecord.packageName,
                        mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled,
                        PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION);
        mBooleanPropertyFakeFocus =
                readComponentProperty(packageManager, mActivityRecord.packageName,
                        mLetterboxConfiguration::isCompatFakeFocusEnabled,
                        PROPERTY_COMPAT_ENABLE_FAKE_FOCUS);
        mBooleanPropertyCameraCompatAllowForceRotation =
                readComponentProperty(packageManager, mActivityRecord.packageName,
                        () -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
@@ -265,6 +277,9 @@ final class LetterboxUiController {

        mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled =
                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION);

        mIsOverrideEnableCompatFakeFocusEnabled =
                isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS);
    }

    /**
@@ -359,6 +374,25 @@ final class LetterboxUiController {
        return false;
    }

    /**
     * Whether sending compat fake focus for split screen resumed activities is enabled. Needed
     * because some game engines wait to get focus before drawing the content of the app which isn't
     * guaranteed by default in multi-window modes.
     *
     * <p>This treatment is enabled when the following conditions are met:
     * <ul>
     *     <li>Flag gating the treatment is enabled
     *     <li>Component property is NOT set to false
     *     <li>Component property is set to true or per-app override is enabled
     * </ul>
     */
    boolean shouldSendFakeFocus() {
        return shouldEnableWithOverrideAndProperty(
                /* gatingCondition */ mLetterboxConfiguration::isCompatFakeFocusEnabled,
                mIsOverrideEnableCompatFakeFocusEnabled,
                mBooleanPropertyFakeFocus);
    }

    /**
     * Sets whether an activity is relaunching after the app has called {@link
     * android.app.Activity#setRequestedOrientation}.
+4 −4
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ import java.util.function.BiConsumer;
 * Tests for the {@link LetterboxConfiguration} class.
 *
 * Build/Install/Run:
 *  atest WmTests:LetterboxConfigurationTests
 *  atest WmTests:LetterboxConfigurationTest
 */
@SmallTest
@Presubmit
@@ -243,18 +243,18 @@ public class LetterboxConfigurationTest {
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "true", false);
        mLetterboxConfiguration.setIsCompatFakeFocusEnabled(false);
        assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
        assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabled());

        // Set runtime flag to false and build time flag to true
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "false", false);
        mLetterboxConfiguration.setIsCompatFakeFocusEnabled(true);
        assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
        assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabled());

        // Set runtime flag to true so that both are enabled
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "true", false);
        assertTrue(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
        assertTrue(mLetterboxConfiguration.isCompatFakeFocusEnabled());

        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, Boolean.toString(wasFakeFocusEnabled),
Loading