Merge "Add per-app controls for compat fake focus"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e09d61ca1f
@@ -1174,6 +1174,17 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
||||
@TestApi
|
||||
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
|
||||
* determine if it can be put into multi window mode.
|
||||
|
||||
@@ -10129,8 +10129,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() && inMultiWindowMode()
|
||||
&& !inPinnedWindowingMode() && !inFreeformWindowingMode();
|
||||
return mWmService.mLetterboxConfiguration.isCompatFakeFocusEnabled(info)
|
||||
&& inMultiWindowMode() && !inPinnedWindowingMode() && !inFreeformWindowingMode();
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
|
||||
@@ -23,6 +23,8 @@ 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;
|
||||
@@ -39,6 +41,10 @@ final class LetterboxConfiguration {
|
||||
|
||||
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
|
||||
* 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. */
|
||||
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;
|
||||
|
||||
// Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
|
||||
@@ -977,11 +989,49 @@ final class LetterboxConfiguration {
|
||||
"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 */
|
||||
boolean isCompatFakeFocusEnabled() {
|
||||
return mIsCompatFakeFocusEnabled && DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_WINDOW_MANAGER, "enable_compat_fake_focus", true);
|
||||
boolean isCompatFakeFocusEnabledOnDevice() {
|
||||
return mIsCompatFakeFocusEnabled
|
||||
&& 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. */
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
||||
|
||||
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_LEFT;
|
||||
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_TOP;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -34,6 +37,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -43,18 +47,25 @@ import org.junit.Test;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Tests for the {@link LetterboxConfiguration} class.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest WmTests:LetterboxConfigurationTests
|
||||
*/
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
public class LetterboxConfigurationTest {
|
||||
|
||||
private Context mContext;
|
||||
private LetterboxConfiguration mLetterboxConfiguration;
|
||||
private LetterboxConfigurationPersister mLetterboxConfigurationPersister;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Context context = getInstrumentation().getTargetContext();
|
||||
mContext = getInstrumentation().getTargetContext();
|
||||
mLetterboxConfigurationPersister = mock(LetterboxConfigurationPersister.class);
|
||||
mLetterboxConfiguration = new LetterboxConfiguration(context,
|
||||
mLetterboxConfiguration = new LetterboxConfiguration(mContext,
|
||||
mLetterboxConfigurationPersister);
|
||||
}
|
||||
|
||||
@@ -222,6 +233,34 @@ public class LetterboxConfigurationTest {
|
||||
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,
|
||||
boolean halfFoldPose, BiConsumer<LetterboxConfiguration, Boolean> move) {
|
||||
// We are in the current position
|
||||
|
||||
@@ -56,6 +56,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.STOPPED;
|
||||
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.google.common.truth.Truth.assertThat;
|
||||
@@ -3228,6 +3230,80 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
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) {
|
||||
int dividerWindowWidth =
|
||||
mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
|
||||
|
||||
Reference in New Issue
Block a user