Merge cherrypicks of [16663837, 16663579, 16682031, 16458641] into sc-v2-release.

Change-Id: I8ce0dc7b246a5679496cb09166a636d7d51acddc
This commit is contained in:
Android Build Coastguard Worker
2022-01-21 01:29:02 +00:00
8 changed files with 126 additions and 19 deletions

View File

@@ -43,6 +43,9 @@
<!-- PiP minimum size, which is a % based off the shorter side of display width and height -->
<fraction name="config_pipShortestEdgePercent">40%</fraction>
<!-- Show PiP enter split icon, which allows apps to directly enter splitscreen from PiP. -->
<bool name="config_pipEnableEnterSplitButton">false</bool>
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>

View File

@@ -104,8 +104,6 @@ public class PipMenuView extends FrameLayout {
private static final float MENU_BACKGROUND_ALPHA = 0.3f;
private static final float DISABLED_ACTION_ALPHA = 0.54f;
private static final boolean ENABLE_ENTER_SPLIT = true;
private int mMenuState;
private boolean mAllowMenuTimeout = true;
private boolean mAllowTouches = true;
@@ -277,6 +275,8 @@ public class PipMenuView extends FrameLayout {
boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
mAllowMenuTimeout = allowMenuTimeout;
mDidLastShowMenuResize = resizeMenuOnShow;
final boolean enableEnterSplit =
mContext.getResources().getBoolean(R.bool.config_pipEnableEnterSplitButton);
if (mMenuState != menuState) {
// Disallow touches if the menu needs to resize while showing, and we are transitioning
// to/from a full menu state.
@@ -297,7 +297,7 @@ public class PipMenuView extends FrameLayout {
mDismissButton.getAlpha(), 1f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA,
mEnterSplitButton.getAlpha(),
ENABLE_ENTER_SPLIT && mFocusedTaskAllowSplitScreen ? 1f : 0f);
enableEnterSplit && mFocusedTaskAllowSplitScreen ? 1f : 0f);
if (menuState == MENU_STATE_FULL) {
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
enterSplitAnim);

View File

@@ -16,12 +16,15 @@
package com.android.systemui.flags;
import android.content.res.Resources;
import android.util.SparseBooleanArray;
import androidx.annotation.BoolRes;
import androidx.annotation.NonNull;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import java.io.FileDescriptor;
@@ -38,8 +41,11 @@ import javax.inject.Inject;
@SysUISingleton
public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
SparseBooleanArray mAccessedFlags = new SparseBooleanArray();
private Resources mResources;
@Inject
public FeatureFlagManager(DumpManager dumpManager) {
public FeatureFlagManager(DumpManager dumpManager, @Main Resources resources) {
mResources = resources;
dumpManager.registerDumpable("SysUIFlags", this);
}
@@ -51,7 +57,20 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
@Override
public boolean isEnabled(BooleanFlag flag) {
return isEnabled(flag.getId(), flag.getDefault());
boolean def = flag.getDefault();
if (flag.hasResourceOverride()) {
try {
def = isEnabledInOverlay(flag.getResourceOverride());
} catch (Resources.NotFoundException e) {
// no-op
}
}
return isEnabled(flag.getId(), def);
}
private boolean isEnabledInOverlay(@BoolRes int resId) {
return mResources.getBoolean(resId);
}
@Override

View File

@@ -25,15 +25,14 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -53,14 +52,14 @@ import java.io.StringWriter;
public class FeatureFlagManagerTest extends SysuiTestCase {
FeatureFlagManager mFeatureFlagManager;
@Mock private Context mContext;
@Mock private DumpManager mDumpManager;
@Mock private Resources mResources;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mFeatureFlagManager = new FeatureFlagManager(mDumpManager);
mFeatureFlagManager = new FeatureFlagManager(mDumpManager, mResources);
}
@After
@@ -70,6 +69,24 @@ public class FeatureFlagManagerTest extends SysuiTestCase {
verifyNoMoreInteractions(mDumpManager);
}
@Test
public void testSimpleFlag() {
BooleanFlag flagA = new BooleanFlag(100, false);
BooleanFlag flagB = new BooleanFlag(200, true);
assertThat(mFeatureFlagManager.isEnabled(flagA)).isFalse();
assertThat(mFeatureFlagManager.isEnabled(flagB)).isTrue();
}
@Test
public void testResourceOverride() {
when(mResources.getBoolean(1)).thenReturn(true);
BooleanFlag flag = new BooleanFlag(100, false, 1);
assertThat(mFeatureFlagManager.isEnabled(flag)).isTrue();
}
@Test
public void testIsEnabled() {
mFeatureFlagManager.setEnabled(1, true);

View File

@@ -2722,9 +2722,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
boolean isResizeable() {
return isResizeable(/* checkPictureInPictureSupport */ true);
}
boolean isResizeable(boolean checkPictureInPictureSupport) {
return mAtmService.mForceResizableActivities
|| ActivityInfo.isResizeableMode(info.resizeMode)
|| info.supportsPictureInPicture()
|| (info.supportsPictureInPicture() && checkPictureInPictureSupport)
// If the activity can be embedded, it should inherit the bounds of task fragment.
|| isEmbedded();
}
@@ -7679,10 +7683,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// orientation with insets applied.
return;
}
// Activity should be resizable if the task is.
// Not using Task#isResizeable() or ActivityRecord#isResizeable() directly because app
// compatibility testing showed that android:supportsPictureInPicture="true" alone is not
// sufficient signal for not letterboxing an app.
// TODO(214602463): Remove multi-window check since orientation and aspect ratio
// restrictions should always be applied in multi-window.
final boolean isResizeable = task != null
? task.isResizeable() || isResizeable()
: isResizeable();
// Activity should be resizable if the task is.
? task.isResizeable(/* checkPictureInPictureSupport */ false)
|| isResizeable(/* checkPictureInPictureSupport */ false)
: isResizeable(/* checkPictureInPictureSupport */ false);
if (WindowConfiguration.inMultiWindowMode(windowingMode) && isResizeable) {
// Ignore orientation request for resizable apps in multi window.
return;
@@ -8211,8 +8221,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final float maxAspectRatio = info.getMaxAspectRatio();
final Task rootTask = getRootTask();
final float minAspectRatio = getMinAspectRatio();
// Not using ActivityRecord#isResizeable() directly because app compatibility testing
// showed that android:supportsPictureInPicture="true" alone is not sufficient signal for
// not letterboxing an app.
// TODO(214602463): Remove multi-window check since orientation and aspect ratio
// restrictions should always be applied in multi-window.
if (task == null || rootTask == null
|| (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
|| (inMultiWindowMode() && isResizeable(/* checkPictureInPictureSupport */ false)
&& !fixedOrientationLetterboxed)
|| (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1)
|| isInVrUiMode(getConfiguration())) {

View File

@@ -4122,9 +4122,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* which controls the visibility and animation of the input method window.
*/
void updateImeInputAndControlTarget(WindowState target) {
if (target != null && target.mActivityRecord != null) {
target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
}
if (mImeInputTarget != target) {
ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
setImeInputTarget(target);
@@ -4132,6 +4129,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
updateImeControlTarget();
}
// Unfreeze IME insets after the new target updated, in case updateAboveInsetsState may
// deliver unrelated IME insets change to the non-IME requester.
if (target != null && target.mActivityRecord != null) {
target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
}
}
void updateImeControlTarget() {

View File

@@ -2728,10 +2728,14 @@ class Task extends TaskFragment {
}
boolean isResizeable() {
return isResizeable(/* checkPictureInPictureSupport */ true);
}
boolean isResizeable(boolean checkPictureInPictureSupport) {
final boolean forceResizable = mAtmService.mForceResizableActivities
&& getActivityType() == ACTIVITY_TYPE_STANDARD;
return forceResizable || ActivityInfo.isResizeableMode(mResizeMode)
|| mSupportsPictureInPicture;
|| (mSupportsPictureInPicture && checkPictureInPictureSupport);
}
/**

View File

@@ -99,6 +99,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
@@ -131,6 +132,7 @@ import android.view.IWindowManager;
import android.view.IWindowSession;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.InsetsVisibilities;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
@@ -147,6 +149,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import java.util.ArrayList;
@@ -3076,6 +3079,50 @@ public class ActivityRecordTests extends WindowTestsBase {
assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
}
@UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD})
@Test
public void testImeInsetsFrozenFlag_noDispatchVisibleInsetsWhenAppNotRequest()
throws RemoteException {
final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindow(
mImeWindow, null, null);
mImeWindow.getControllableInsetProvider().setServerVisible(true);
// Simulate app2 is closing and let app1 is visible to be IME targets.
makeWindowVisibleAndDrawn(app1, mImeWindow);
mDisplayContent.setImeLayeringTarget(app1);
mDisplayContent.updateImeInputAndControlTarget(app1);
app2.mActivityRecord.commitVisibility(false, false);
// app1 requests IME visible.
final InsetsVisibilities requestedVisibilities = new InsetsVisibilities();
requestedVisibilities.setVisibility(ITYPE_IME, true);
app1.setRequestedVisibilities(requestedVisibilities);
mDisplayContent.getInsetsStateController().onInsetsModified(app1);
// Verify app1's IME insets is visible and app2's IME insets frozen flag set.
assertTrue(app1.getInsetsState().peekSource(ITYPE_IME).isVisible());
assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
// Simulate switching to app2 to make it visible to be IME targets.
makeWindowVisibleAndDrawn(app2);
spyOn(app2);
spyOn(app2.mClient);
ArgumentCaptor<InsetsState> insetsStateCaptor = ArgumentCaptor.forClass(InsetsState.class);
doReturn(true).when(app2).isReadyToDispatchInsetsState();
mDisplayContent.setImeLayeringTarget(app2);
mDisplayContent.updateImeInputAndControlTarget(app2);
// Verify after unfreezing app2's IME insets state, we won't dispatch visible IME insets
// to client if the app didn't request IME visible.
assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
verify(app2.mClient, atLeastOnce()).insetsChanged(insetsStateCaptor.capture(), anyBoolean(),
anyBoolean());
assertFalse(insetsStateCaptor.getAllValues().get(0).peekSource(ITYPE_IME).isVisible());
}
@Test
public void testInClosingAnimation_doNotHideSurface() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");