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

Commit a1663403 authored by Tiger Huang's avatar Tiger Huang
Browse files

Refine logic about controlling transient bars

- Use copied InsetsSourceControl to prevent the leash from being
  released while the control gets revoked while playing transient
  bar animations.
- Start the animation after mAnimationControl gets assigned to prevent
  NullPointerException.
- Let SystemUI to change the bar mode to transient mode before WM
  plays the transient bar animation.
- Remove a redundunt call to the super method.
- Fix InsetsPolicyTest
- Fix InsetsStateControllerTest
- Fix misc things

Bug: 118118435
Test: Manually swipe to show transient bars many times.
Test: atest InsetsSourceProviderTest InsetsStateControllerTest
            InsetsPolicyTest WindowStateTests CommandQueueTest
            RegisterStatusBarResultTest InsetsFlagsTest
            LightBarControllerTest RegisterStatusBarResultTest
            ViewRootImplTest DisplayPolicyInsetsTests
            DisplayPolicyTests TaskSnapshotSurfaceTest
            InsetsAnimationControlImplTest
Change-Id: I7d445b7dc6f47a64048937cd439bdd5ffa7fa3a3
parent be5015b0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ public class InsetsSource implements Parcelable {
        return "InsetsSource: {"
                + "mType=" + InsetsState.typeToString(mType)
                + ", mFrame=" + mFrame.toShortString()
                + ", mVisible" + mVisible
                + ", mVisible=" + mVisible
                + "}";
    }

+1 −3
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.view;

import static android.view.WindowInsets.Type.ime;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+21 −19
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.view.ViewRootImpl;
import android.view.WindowInsetsAnimationCallback;
import android.view.WindowInsetsAnimationControlListener;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.DisplayThread;

/**
@@ -107,11 +108,11 @@ class InsetsPolicy {
            changed = true;
        }
        if (changed) {
            startAnimation(mShowingTransientTypes, true, () -> {
                synchronized (mDisplayContent.mWmService.mGlobalLock) {
                    mPolicy.getStatusBarManagerInternal().showTransient(
                            mDisplayContent.getDisplayId(),
            mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
                    mShowingTransientTypes.toArray());
            updateBarControlTarget(mFocusedWin);
            startAnimation(true /* show */, () -> {
                synchronized (mDisplayContent.mWmService.mGlobalLock) {
                    mStateController.notifyInsetsChanged();
                }
            });
@@ -122,7 +123,7 @@ class InsetsPolicy {
        if (mShowingTransientTypes.size() == 0) {
            return;
        }
        startAnimation(mShowingTransientTypes, false, () -> {
        startAnimation(false /* show */, () -> {
            synchronized (mDisplayContent.mWmService.mGlobalLock) {
                mShowingTransientTypes.clear();
                mStateController.notifyInsetsChanged();
@@ -268,18 +269,20 @@ class InsetsPolicy {
        return isDockedStackVisible || isFreeformStackVisible || isResizing;
    }

    private void startAnimation(IntArray internalTypes, boolean show, Runnable callback) {
    @VisibleForTesting
    void startAnimation(boolean show, Runnable callback) {
        int typesReady = 0;
        final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
        updateBarControlTarget(mFocusedWin);
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
        final IntArray showingTransientTypes = mShowingTransientTypes;
        for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
            InsetsSourceProvider provider =
                    mStateController.getSourceProvider(internalTypes.get(i));
            if (provider == null) continue;
            InsetsSourceControl control = provider.getControl(provider.getControlTarget());
            if (control == null || control.getLeash() == null) continue;
            typesReady |= InsetsState.toPublicType(internalTypes.get(i));
            controls.put(control.getType(), control);
                    mStateController.getSourceProvider(showingTransientTypes.get(i));
            InsetsSourceControl control = provider.getControl(mTransientControlTarget);
            if (control == null || control.getLeash() == null) {
                continue;
            }
            typesReady |= InsetsState.toPublicType(showingTransientTypes.get(i));
            controls.put(control.getType(), new InsetsSourceControl(control));
        }
        controlAnimationUnchecked(typesReady, controls, show, callback);
    }
@@ -335,7 +338,6 @@ class InsetsPolicy {
            private InsetsPolicyAnimationControlListener mListener;

            InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener) {
                super();
                mListener = listener;
            }

@@ -353,9 +355,11 @@ class InsetsPolicy {
                        InsetsController.INTERPOLATOR, true,
                        show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
                                : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
                SurfaceAnimationThread.getHandler().post(
                        () -> mListener.onReady(mAnimationControl, typesReady));
            }

            /** Called on SurfaceAnimationThread lock without global WM lock held. */
            /** Called on SurfaceAnimationThread without global WM lock held. */
            @Override
            public void scheduleApplyChangeInsets() {
                InsetsState state = getState();
@@ -384,7 +388,7 @@ class InsetsPolicy {
                return overrideState;
            }

            /** Called on SurfaceAnimationThread lock without global WM lock held. */
            /** Called on SurfaceAnimationThread without global WM lock held. */
            @Override
            public void applySurfaceParams(
                    final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
@@ -396,14 +400,12 @@ class InsetsPolicy {
                t.apply();
            }

            /** Called on SurfaceAnimationThread lock without global WM lock held. */
            @Override
            public void startAnimation(InsetsAnimationControlImpl controller,
                    WindowInsetsAnimationControlListener listener, int types,
                    WindowInsetsAnimationCallback.InsetsAnimation animation,
                    WindowInsetsAnimationCallback.AnimationBounds bounds,
                    int layoutDuringAnimation) {
                SurfaceAnimationThread.getHandler().post(() -> listener.onReady(controller, types));
            }
        }
    }
+13 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -89,6 +90,12 @@ class InsetsStateController {
        if (type == ITYPE_NAVIGATION_BAR) {
            state.removeSource(ITYPE_IME);
            state.removeSource(ITYPE_STATUS_BAR);
            state.removeSource(ITYPE_CAPTION_BAR);
        }

        // Status bar doesn't get influenced by caption bar
        if (type == ITYPE_STATUS_BAR) {
            state.removeSource(ITYPE_CAPTION_BAR);
        }

        // IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
@@ -212,18 +219,18 @@ class InsetsStateController {
    /**
     * Called when the focused window that is able to control the system bars changes.
     *
     * @param topControlling The target that is now able to control the top bar appearance
     * @param statusControlling The target that is now able to control the status bar appearance
     *                          and visibility.
     * @param navControlling The target that is now able to control the nav bar appearance
     *                       and visibility.
     */
    void onBarControlTargetChanged(@Nullable InsetsControlTarget topControlling,
            @Nullable InsetsControlTarget fakeTopControlling,
    void onBarControlTargetChanged(@Nullable InsetsControlTarget statusControlling,
            @Nullable InsetsControlTarget fakeStatusControlling,
            @Nullable InsetsControlTarget navControlling,
            @Nullable InsetsControlTarget fakeNavControlling) {
        onControlChanged(ITYPE_STATUS_BAR, topControlling);
        onControlChanged(ITYPE_STATUS_BAR, statusControlling);
        onControlChanged(ITYPE_NAVIGATION_BAR, navControlling);
        onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeTopControlling);
        onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling);
        onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling);
        notifyPendingInsetsControlChanged();
    }
+15 −10
Original line number Diff line number Diff line
@@ -29,12 +29,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;

import android.platform.test.annotations.Presubmit;
import android.util.IntArray;
@@ -122,13 +123,13 @@ public class InsetsPolicyTest extends WindowTestsBase {
    // TODO: adjust this test if we pretend to the app that it's still able to control it.
    @Test
    public void testControlsForDispatch_forceStatusBarVisible() {
        addWindow(TYPE_STATUS_BAR, "topBar").mAttrs.privateFlags |=
        addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |=
                PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
        addWindow(TYPE_NAVIGATION_BAR, "navBar");

        final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();

        // The app must not control the top bar.
        // The app must not control the status bar.
        assertNotNull(controls);
        assertEquals(1, controls.length);
    }
@@ -137,6 +138,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
    public void testControlsForDispatch_statusBarForceShowNavigation() {
        addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |=
                PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
        addWindow(TYPE_STATUS_BAR, "statusBar");
        addWindow(TYPE_NAVIGATION_BAR, "navBar");

        final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -169,7 +171,8 @@ public class InsetsPolicyTest extends WindowTestsBase {
                .getControllableInsetProvider().getSource().setVisible(false);
        final WindowState app = addWindow(TYPE_APPLICATION, "app");

        final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
        final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
        doNothing().when(policy).startAnimation(anyBoolean(), any());
        policy.updateBarControlTarget(app);
        policy.showTransient(
                IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
@@ -184,7 +187,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
    }

    @Test
    public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
    public void testShowTransientBars_statusBarCanBeTransient_appGetsStatusBarFakeControl() {
        // Adding app window before setting source visibility is to prevent the visibility from
        // being cleared by InsetsSourceProvider.updateVisibility.
        final WindowState app = addWindow(TYPE_APPLICATION, "app");
@@ -194,14 +197,15 @@ public class InsetsPolicyTest extends WindowTestsBase {
        addWindow(TYPE_NAVIGATION_BAR, "navBar")
                .getControllableInsetProvider().getSource().setVisible(true);

        final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
        final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
        doNothing().when(policy).startAnimation(anyBoolean(), any());
        policy.updateBarControlTarget(app);
        policy.showTransient(
                IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
        final InsetsSourceControl[] controls =
                mDisplayContent.getInsetsStateController().getControlsForDispatch(app);

        // The app must get the fake control of the top bar, and must get the real control of the
        // The app must get the fake control of the status bar, and must get the real control of the
        // navigation bar.
        assertEquals(2, controls.length);
        for (int i = controls.length - 1; i >= 0; i--) {
@@ -222,7 +226,8 @@ public class InsetsPolicyTest extends WindowTestsBase {
                .getControllableInsetProvider().getSource().setVisible(false);
        final WindowState app = addWindow(TYPE_APPLICATION, "app");

        final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
        final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
        doNothing().when(policy).startAnimation(anyBoolean(), any());
        policy.updateBarControlTarget(app);
        policy.showTransient(
                IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
Loading