Merge "Add per-app controls for compat fake focus" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f4fa929785
@@ -1128,6 +1128,17 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
|||||||
@Overridable
|
@Overridable
|
||||||
public static final long OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN = 218959984L;
|
public static final long OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN = 218959984L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables sending fake focus for unfocused apps in splitscreen. Some game engines
|
||||||
|
* wait to get focus before drawing the content of the app so fake focus helps them to avoid
|
||||||
|
* staying blacked out when they are resumed and do not have focus yet.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@ChangeId
|
||||||
|
@Disabled
|
||||||
|
@Overridable
|
||||||
|
public static final long OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS = 263259275L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares activity window layout min width/height with require space for multi window to
|
* Compares activity window layout min width/height with require space for multi window to
|
||||||
* determine if it can be put into multi window mode.
|
* determine if it can be put into multi window mode.
|
||||||
|
|||||||
@@ -10127,8 +10127,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
// TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when
|
// TODO(b/263592337): Explore enabling compat fake focus for fullscreen, e.g. for when
|
||||||
// covered with bubbles.
|
// covered with bubbles.
|
||||||
boolean shouldSendCompatFakeFocus() {
|
boolean shouldSendCompatFakeFocus() {
|
||||||
return mWmService.mLetterboxConfiguration.isCompatFakeFocusEnabled() && inMultiWindowMode()
|
return mWmService.mLetterboxConfiguration.isCompatFakeFocusEnabled(info)
|
||||||
&& !inPinnedWindowingMode() && !inFreeformWindowingMode();
|
&& inMultiWindowMode() && !inPinnedWindowingMode() && !inFreeformWindowingMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Builder {
|
static class Builder {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import android.annotation.IntDef;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -39,6 +41,10 @@ final class LetterboxConfiguration {
|
|||||||
|
|
||||||
private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxConfiguration" : TAG_ATM;
|
private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxConfiguration" : TAG_ATM;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static final String DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS =
|
||||||
|
"enable_compat_fake_focus";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override of aspect ratio for fixed orientation letterboxing that is set via ADB with
|
* Override of aspect ratio for fixed orientation letterboxing that is set via ADB with
|
||||||
* set-fixed-orientation-letterbox-aspect-ratio or via {@link
|
* set-fixed-orientation-letterbox-aspect-ratio or via {@link
|
||||||
@@ -108,6 +114,12 @@ final class LetterboxConfiguration {
|
|||||||
/** Letterboxed app window is aligned to the right side. */
|
/** Letterboxed app window is aligned to the right side. */
|
||||||
static final int LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM = 2;
|
static final int LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM = 2;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static final String PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN = "com.android.COMPAT_FAKE_FOCUS_OPT_IN";
|
||||||
|
@VisibleForTesting
|
||||||
|
static final String PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT =
|
||||||
|
"com.android.COMPAT_FAKE_FOCUS_OPT_OUT";
|
||||||
|
|
||||||
final Context mContext;
|
final Context mContext;
|
||||||
|
|
||||||
// Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
|
// Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
|
||||||
@@ -977,11 +989,49 @@ final class LetterboxConfiguration {
|
|||||||
"enable_translucent_activity_letterbox", false);
|
"enable_translucent_activity_letterbox", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/262866240): Add listener to check for device config property
|
@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 */
|
/** Whether fake sending focus is enabled for unfocused apps in splitscreen */
|
||||||
boolean isCompatFakeFocusEnabled() {
|
boolean isCompatFakeFocusEnabledOnDevice() {
|
||||||
return mIsCompatFakeFocusEnabled && DeviceConfig.getBoolean(
|
return mIsCompatFakeFocusEnabled
|
||||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER, "enable_compat_fake_focus", true);
|
&& DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides whether fake sending focus is enabled for unfocused apps in splitscreen
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
void setIsCompatFakeFocusEnabled(boolean enabled) {
|
||||||
|
mIsCompatFakeFocusEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether camera compatibility treatment is enabled. */
|
/** Whether camera compatibility treatment is enabled. */
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
|||||||
|
|
||||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||||
|
|
||||||
|
import static com.android.server.wm.LetterboxConfiguration.DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS;
|
||||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
|
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
|
||||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
|
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
|
||||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
|
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
|
||||||
@@ -25,6 +26,8 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_RE
|
|||||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
|
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
|
||||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
|
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -34,6 +37,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -43,18 +47,25 @@ import org.junit.Test;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the {@link LetterboxConfiguration} class.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WmTests:LetterboxConfigurationTests
|
||||||
|
*/
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@Presubmit
|
@Presubmit
|
||||||
public class LetterboxConfigurationTest {
|
public class LetterboxConfigurationTest {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
private LetterboxConfiguration mLetterboxConfiguration;
|
private LetterboxConfiguration mLetterboxConfiguration;
|
||||||
private LetterboxConfigurationPersister mLetterboxConfigurationPersister;
|
private LetterboxConfigurationPersister mLetterboxConfigurationPersister;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
Context context = getInstrumentation().getTargetContext();
|
mContext = getInstrumentation().getTargetContext();
|
||||||
mLetterboxConfigurationPersister = mock(LetterboxConfigurationPersister.class);
|
mLetterboxConfigurationPersister = mock(LetterboxConfigurationPersister.class);
|
||||||
mLetterboxConfiguration = new LetterboxConfiguration(context,
|
mLetterboxConfiguration = new LetterboxConfiguration(mContext,
|
||||||
mLetterboxConfigurationPersister);
|
mLetterboxConfigurationPersister);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +233,34 @@ public class LetterboxConfigurationTest {
|
|||||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop);
|
LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsCompatFakeFocusEnabledOnDevice() {
|
||||||
|
boolean wasFakeFocusEnabled = DeviceConfig
|
||||||
|
.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, false);
|
||||||
|
|
||||||
|
// Set runtime flag to true and build time flag to false
|
||||||
|
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, "true", false);
|
||||||
|
mLetterboxConfiguration.setIsCompatFakeFocusEnabled(false);
|
||||||
|
assertFalse(mLetterboxConfiguration.isCompatFakeFocusEnabledOnDevice());
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
|
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
DEVICE_CONFIG_KEY_ENABLE_COMPAT_FAKE_FOCUS, Boolean.toString(wasFakeFocusEnabled),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertForHorizontalMove(int from, int expected, int expectedTime,
|
private void assertForHorizontalMove(int from, int expected, int expectedTime,
|
||||||
boolean halfFoldPose, BiConsumer<LetterboxConfiguration, Boolean> move) {
|
boolean halfFoldPose, BiConsumer<LetterboxConfiguration, Boolean> move) {
|
||||||
// We are in the current position
|
// We are in the current position
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
|
|||||||
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
||||||
import static com.android.server.wm.ActivityRecord.State.STOPPED;
|
import static com.android.server.wm.ActivityRecord.State.STOPPED;
|
||||||
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
|
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
|
||||||
|
import static com.android.server.wm.LetterboxConfiguration.PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN;
|
||||||
|
import static com.android.server.wm.LetterboxConfiguration.PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT;
|
||||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@@ -3228,6 +3230,80 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
assertEquals(newDensity, mActivity.getConfiguration().densityDpi);
|
assertEquals(newDensity, mActivity.getConfiguration().densityDpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ActivityRecord setUpActivityForCompatFakeFocusTest() {
|
||||||
|
final ActivityRecord activity = new ActivityBuilder(mAtm)
|
||||||
|
.setCreateTask(true)
|
||||||
|
.setOnTop(true)
|
||||||
|
// Set the component to be that of the test class in order to enable compat changes
|
||||||
|
.setComponent(ComponentName.createRelative(mContext,
|
||||||
|
com.android.server.wm.SizeCompatTests.class.getName()))
|
||||||
|
.build();
|
||||||
|
final Task task = activity.getTask();
|
||||||
|
task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
||||||
|
spyOn(activity.mWmService.mLetterboxConfiguration);
|
||||||
|
doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
|
||||||
|
.isCompatFakeFocusEnabledOnDevice();
|
||||||
|
return activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
|
||||||
|
public void testShouldSendFakeFocus_overrideEnabled_returnsTrue() {
|
||||||
|
ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
|
||||||
|
|
||||||
|
assertTrue(activity.shouldSendCompatFakeFocus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
|
||||||
|
public void testShouldSendFakeFocus_overrideDisabled_returnsFalse() {
|
||||||
|
ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
|
||||||
|
|
||||||
|
assertFalse(activity.shouldSendCompatFakeFocus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
|
||||||
|
public void testIsCompatFakeFocusEnabled_optOutPropertyAndOverrideEnabled_fakeFocusDisabled() {
|
||||||
|
ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
|
||||||
|
doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
|
||||||
|
.getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT));
|
||||||
|
|
||||||
|
assertFalse(activity.mWmService.mLetterboxConfiguration
|
||||||
|
.isCompatFakeFocusEnabled(activity.info));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS})
|
||||||
|
public void testIsCompatFakeFocusEnabled_optInPropertyEnabled_noOverride_fakeFocusEnabled() {
|
||||||
|
ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
|
||||||
|
doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
|
||||||
|
.getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN));
|
||||||
|
|
||||||
|
assertTrue(activity.mWmService.mLetterboxConfiguration
|
||||||
|
.isCompatFakeFocusEnabled(activity.info));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsCompatFakeFocusEnabled_optOutPropertyEnabled_fakeFocusDisabled() {
|
||||||
|
ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
|
||||||
|
doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
|
||||||
|
.getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_OUT));
|
||||||
|
|
||||||
|
assertFalse(activity.mWmService.mLetterboxConfiguration
|
||||||
|
.isCompatFakeFocusEnabled(activity.info));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsCompatFakeFocusEnabled_optInPropertyEnabled_fakeFocusEnabled() {
|
||||||
|
ActivityRecord activity = setUpActivityForCompatFakeFocusTest();
|
||||||
|
doReturn(true).when(activity.mWmService.mLetterboxConfiguration)
|
||||||
|
.getPackageManagerProperty(any(), eq(PROPERTY_COMPAT_FAKE_FOCUS_OPT_IN));
|
||||||
|
|
||||||
|
assertTrue(activity.mWmService.mLetterboxConfiguration
|
||||||
|
.isCompatFakeFocusEnabled(activity.info));
|
||||||
|
}
|
||||||
|
|
||||||
private int getExpectedSplitSize(int dimensionToSplit) {
|
private int getExpectedSplitSize(int dimensionToSplit) {
|
||||||
int dividerWindowWidth =
|
int dividerWindowWidth =
|
||||||
mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
|
mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
|
||||||
|
|||||||
Reference in New Issue
Block a user