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

Commit 1fd07815 authored by Bill Lin's avatar Bill Lin
Browse files

Re-map DisplayAreaAppearedInfo to token-leash map

Clean-up DA callback APIs of OneHandedDisplayAreaOrganizer
  onDisplayAreaAppeared()
  onDisplayAreaVanished()

Note:
  When super.unregisterOrganizer() is called, all DAs should be
  removed from the map in the callback of onDisplayAreaVanished().
  It was not working correctly because the map is using DisplayAreaInfo
  as the key, which will be different because of the different
  configuration object. We should use the DA token as the key.

Bug: b/172298357
Test: atest WMShellUnitTests:OneHandedDisplayAreaOrganizerTest
Test: atest SystemUITests
Test: Trigger OHM, rotate screen
Test: Trigger OHM, disabled through settings
Change-Id: I4560df1ab36ec33292fa4ec08cab28644b0fabe2
parent 2e4306e9
Loading
Loading
Loading
Loading
+22 −18
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.view.SurfaceControl;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
import android.window.WindowContainerToken;

import androidx.annotation.VisibleForTesting;

@@ -55,7 +56,7 @@ public class OneHandedAnimationController {

    private final Interpolator mOvershootInterpolator;
    private final OneHandedSurfaceTransactionHelper mSurfaceTransactionHelper;
    private final HashMap<SurfaceControl, OneHandedTransitionAnimator> mAnimatorMap =
    private final HashMap<WindowContainerToken, OneHandedTransitionAnimator> mAnimatorMap =
            new HashMap<>();

    /**
@@ -67,23 +68,23 @@ public class OneHandedAnimationController {
    }

    @SuppressWarnings("unchecked")
    OneHandedTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds,
            Rect endBounds) {
        final OneHandedTransitionAnimator animator = mAnimatorMap.get(leash);
    OneHandedTransitionAnimator getAnimator(WindowContainerToken token, SurfaceControl leash,
            Rect startBounds, Rect endBounds) {
        final OneHandedTransitionAnimator animator = mAnimatorMap.get(token);
        if (animator == null) {
            mAnimatorMap.put(leash, setupOneHandedTransitionAnimator(
                    OneHandedTransitionAnimator.ofBounds(leash, startBounds, endBounds)));
            mAnimatorMap.put(token, setupOneHandedTransitionAnimator(
                    OneHandedTransitionAnimator.ofBounds(token, leash, startBounds, endBounds)));
        } else if (animator.isRunning()) {
            animator.updateEndValue(endBounds);
        } else {
            animator.cancel();
            mAnimatorMap.put(leash, setupOneHandedTransitionAnimator(
                    OneHandedTransitionAnimator.ofBounds(leash, startBounds, endBounds)));
            mAnimatorMap.put(token, setupOneHandedTransitionAnimator(
                    OneHandedTransitionAnimator.ofBounds(token, leash, startBounds, endBounds)));
        }
        return mAnimatorMap.get(leash);
        return mAnimatorMap.get(token);
    }

    HashMap<SurfaceControl, OneHandedTransitionAnimator> getAnimatorMap() {
    HashMap<WindowContainerToken, OneHandedTransitionAnimator> getAnimatorMap() {
        return mAnimatorMap;
    }

@@ -91,8 +92,8 @@ public class OneHandedAnimationController {
        return mAnimatorMap.isEmpty();
    }

    void removeAnimator(SurfaceControl key) {
        final OneHandedTransitionAnimator animator = mAnimatorMap.remove(key);
    void removeAnimator(WindowContainerToken token) {
        final OneHandedTransitionAnimator animator = mAnimatorMap.remove(token);
        if (animator != null && animator.isRunning()) {
            animator.cancel();
        }
@@ -116,6 +117,7 @@ public class OneHandedAnimationController {
            ValueAnimator.AnimatorListener {

        private final SurfaceControl mLeash;
        private final WindowContainerToken mToken;
        private T mStartValue;
        private T mEndValue;
        private T mCurrentValue;
@@ -128,8 +130,10 @@ public class OneHandedAnimationController {

        private @TransitionDirection int mTransitionDirection;

        private OneHandedTransitionAnimator(SurfaceControl leash, T startValue, T endValue) {
        private OneHandedTransitionAnimator(WindowContainerToken token, SurfaceControl leash,
                T startValue, T endValue) {
            mLeash = leash;
            mToken = token;
            mStartValue = startValue;
            mEndValue = endValue;
            addListener(this);
@@ -208,8 +212,8 @@ public class OneHandedAnimationController {
            return this;
        }

        SurfaceControl getLeash() {
            return mLeash;
        WindowContainerToken getToken() {
            return mToken;
        }

        Rect getDestinationBounds() {
@@ -254,10 +258,10 @@ public class OneHandedAnimationController {
        }

        @VisibleForTesting
        static OneHandedTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
                Rect startValue, Rect endValue) {
        static OneHandedTransitionAnimator<Rect> ofBounds(WindowContainerToken token,
                SurfaceControl leash, Rect startValue, Rect endValue) {

            return new OneHandedTransitionAnimator<Rect>(leash, new Rect(startValue),
            return new OneHandedTransitionAnimator<Rect>(token, leash, new Rect(startValue),
                    new Rect(endValue)) {

                private final Rect mTmpRect = new Rect();
+24 −37
Original line number Diff line number Diff line
@@ -26,11 +26,11 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Log;
import android.view.SurfaceControl;
import android.window.DisplayAreaAppearedInfo;
import android.window.DisplayAreaInfo;
import android.window.DisplayAreaOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.annotation.NonNull;
@@ -44,8 +44,6 @@ import com.android.wm.shell.common.ShellExecutor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * Manages OneHanded display areas such as offset.
@@ -69,7 +67,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
    private int mEnterExitAnimationDurationMs;

    @VisibleForTesting
    ArrayMap<DisplayAreaInfo, SurfaceControl> mDisplayAreaMap = new ArrayMap();
    ArrayMap<WindowContainerToken, SurfaceControl> mDisplayAreaTokenMap = new ArrayMap();
    private DisplayController mDisplayController;
    private OneHandedAnimationController mAnimationController;
    private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
@@ -89,7 +87,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
                @Override
                public void onOneHandedAnimationEnd(SurfaceControl.Transaction tx,
                        OneHandedAnimationController.OneHandedTransitionAnimator animator) {
                    mAnimationController.removeAnimator(animator.getLeash());
                    mAnimationController.removeAnimator(animator.getToken());
                    if (mAnimationController.isAnimatorsConsumed()) {
                        finishOffset(animator.getDestinationOffset(),
                                animator.getTransitionDirection());
@@ -99,7 +97,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
                @Override
                public void onOneHandedAnimationCancel(
                        OneHandedAnimationController.OneHandedTransitionAnimator animator) {
                    mAnimationController.removeAnimator(animator.getLeash());
                    mAnimationController.removeAnimator(animator.getToken());
                    if (mAnimationController.isAnimatorsConsumed()) {
                        finishOffset(animator.getDestinationOffset(),
                                animator.getTransitionDirection());
@@ -119,7 +117,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
        super(mainExecutor);
        mAnimationController = animationController;
        mDisplayController = displayController;
        mDefaultDisplayBounds.set(getDisplayBounds());
        mLastVisualDisplayBounds.set(getDisplayBounds());
        final int animationDurationConfig = context.getResources().getInteger(
                R.integer.config_one_handed_translate_animation_duration);
@@ -134,24 +131,12 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
    @Override
    public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
            @NonNull SurfaceControl leash) {
        Objects.requireNonNull(displayAreaInfo, "displayAreaInfo must not be null");
        Objects.requireNonNull(leash, "leash must not be null");
        if (mDisplayAreaMap.get(displayAreaInfo) == null) {
            // mDefaultDisplayBounds may out of date after removeDisplayChangingController()
            mDefaultDisplayBounds.set(getDisplayBounds());
            mDisplayAreaMap.put(displayAreaInfo, leash);
        }
        mDisplayAreaTokenMap.put(displayAreaInfo.token, leash);
    }

    @Override
    public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
        Objects.requireNonNull(displayAreaInfo,
                "Requires valid displayArea, and displayArea must not be null");
        if (!mDisplayAreaMap.containsKey(displayAreaInfo)) {
            Log.w(TAG, "Unrecognized token: " + displayAreaInfo.token);
            return;
        }
        mDisplayAreaMap.remove(displayAreaInfo);
        mDisplayAreaTokenMap.remove(displayAreaInfo.token);
    }

    @Override
@@ -162,6 +147,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
            final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
            onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
        }
        mDefaultDisplayBounds.set(getDisplayBounds());
        return displayAreaInfos;
    }

@@ -210,11 +196,11 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
                : TRANSITION_DIRECTION_EXIT;

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        mDisplayAreaMap.forEach(
                (key, leash) -> {
                    animateWindows(leash, fromBounds, toBounds, direction,
        mDisplayAreaTokenMap.forEach(
                (token, leash) -> {
                    animateWindows(token, leash, fromBounds, toBounds, direction,
                            mEnterExitAnimationDurationMs);
                    wct.setBounds(key.token, toBounds);
                    wct.setBounds(token, toBounds);
                });
        applyTransaction(wct);
    }
@@ -222,10 +208,10 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
    private void resetWindowsOffset(WindowContainerTransaction wct) {
        final SurfaceControl.Transaction tx =
                mSurfaceControlTransactionFactory.getTransaction();
        mDisplayAreaMap.forEach(
                (key, leash) -> {
        mDisplayAreaTokenMap.forEach(
                (token, leash) -> {
                    final OneHandedAnimationController.OneHandedTransitionAnimator animator =
                            mAnimationController.getAnimatorMap().remove(leash);
                            mAnimationController.getAnimatorMap().remove(token);
                    if (animator != null && animator.isRunning()) {
                        animator.cancel();
                    }
@@ -233,16 +219,17 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
                            .setWindowCrop(leash, -1/* reset */, -1/* reset */);
                    // DisplayRotationController will applyTransaction() after finish rotating
                    if (wct != null) {
                        wct.setBounds(key.token, null/* reset */);
                        wct.setBounds(token, null/* reset */);
                    }
                });
        tx.apply();
    }

    private void animateWindows(SurfaceControl leash, Rect fromBounds, Rect toBounds,
            @OneHandedAnimationController.TransitionDirection int direction, int durationMs) {
    private void animateWindows(WindowContainerToken token, SurfaceControl leash, Rect fromBounds,
            Rect toBounds, @OneHandedAnimationController.TransitionDirection int direction,
            int durationMs) {
        final OneHandedAnimationController.OneHandedTransitionAnimator animator =
                mAnimationController.getAnimator(leash, fromBounds, toBounds);
                mAnimationController.getAnimator(token, leash, fromBounds, toBounds);
        if (animator != null) {
            animator.setTransitionDirection(direction)
                    .addOneHandedAnimationCallback(mOneHandedAnimationCallback)
@@ -311,8 +298,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
        pw.println(TAG + "states: ");
        pw.print(innerPrefix + "mIsInOneHanded=");
        pw.println(mIsInOneHanded);
        pw.print(innerPrefix + "mDisplayAreaMap=");
        pw.println(mDisplayAreaMap);
        pw.print(innerPrefix + "mDisplayAreaTokenMap=");
        pw.println(mDisplayAreaTokenMap);
        pw.print(innerPrefix + "mDefaultDisplayBounds=");
        pw.println(mDefaultDisplayBounds);
        pw.print(innerPrefix + "mLastVisualDisplayBounds=");
+4 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.SurfaceControl;
import android.window.WindowContainerToken;

import androidx.test.filters.SmallTest;

@@ -50,6 +51,8 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase {

    @Mock
    private SurfaceControl mMockLeash;
    @Mock
    private WindowContainerToken mMockToken;

    @Mock
    private ShellExecutor mMainExecutor;
@@ -69,7 +72,7 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase {
        destinationBounds.offset(0, 300);
        final OneHandedAnimationController.OneHandedTransitionAnimator animator =
                mOneHandedAnimationController
                        .getAnimator(mMockLeash, originalBounds, destinationBounds);
                        .getAnimator(mMockToken, mMockLeash, originalBounds, destinationBounds);

        assertNotNull(animator);
    }
+7 −4
Original line number Diff line number Diff line
@@ -24,13 +24,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.Configuration;
import android.os.Handler;
import android.os.Binder;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Display;
@@ -89,12 +90,14 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mTestableLooper = TestableLooper.get(this);
        Binder binder = new Binder();
        doReturn(binder).when(mMockRealToken).asBinder();
        mToken = new WindowContainerToken(mMockRealToken);
        mLeash = new SurfaceControl();
        mDisplay = mContext.getDisplay();
        mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY, FEATURE_ONE_HANDED);
        mDisplayAreaInfo.configuration.orientation = Configuration.ORIENTATION_PORTRAIT;
        when(mMockAnimationController.getAnimator(any(), any(), any())).thenReturn(null);
        when(mMockAnimationController.getAnimator(any(), any(), any(), any())).thenReturn(null);
        when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
        when(mMockSurfaceTransactionHelper.translate(any(), any(), anyFloat())).thenReturn(
                mMockSurfaceTransactionHelper);
@@ -121,7 +124,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
    public void testOnDisplayAreaAppeared() {
        mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);

        verify(mMockAnimationController, never()).getAnimator(any(), any(), any());
        verify(mMockAnimationController, never()).getAnimator(any(), any(), any(), any());
    }

    @Test
@@ -129,7 +132,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
        mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
        mDisplayAreaOrganizer.onDisplayAreaVanished(mDisplayAreaInfo);

        assertThat(mDisplayAreaOrganizer.mDisplayAreaMap).isEmpty();
        assertThat(mDisplayAreaOrganizer.mDisplayAreaTokenMap).isEmpty();
    }

    @Test