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

Commit 05dd3ff5 authored by Ikram Gabiyev's avatar Ikram Gabiyev
Browse files

Deprecate use of onActivityHidden() in PiP

We should not rely on onActivityHidden()
callback in PiP to reset the PiP state, such as
the re-entry state and the flags indicating whether
PiP has been moved or resized.

For instance, relying on it can lead to issues with SLEEP
and locking of the screen which causes the PiP activity to stop,
as expected, which then triggers onActivityHidden() resetting the state.
This means unlocking from the keyguard, can move PiP to its default
position, losing previous state.

Instead we should rely on transitions. We make sure to detect
if an incoming transition going through the PipTransition handler
contains a change of mode CLOSE with the same PiP component name.
This triggers the state reset.

The cases where we switch apps entering PiP are already handled
since stopSwipePipToHome and startEnterAnimation check for changes
in component names upon entry as well.

Bug: 299642417
Flag: EXEMPT bugfix
Test: enter multi-activity PiP, move PiP, expand, do a back-gesture
  to remove PiP activity, reopen the activity, and re-enter PiP in
  default bounds.
Test: enter PiP, move PiP, expand, quick-switch to a different PiP app,
  enter PiP into default bounds.
Test: enter PiP, move PiP, lock and unlock the screen, observe same PiP
  position
Change-Id: Id59023be234a8573bbe83d405a7ed5f4c8a4aece
parent c51b65b7
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -42,12 +42,4 @@ oneway interface IPinnedTaskListener {
     * with fromImeAdjustement set to {@code true}.
     */
    void onImeVisibilityChanged(boolean imeVisible, int imeHeight);

    /**
     * Called by the window manager to notify the listener that Activity (was or is in pinned mode)
     * is hidden (either stopped or removed). This is generally used as a signal to reset saved
     * reentry fraction and size.
     * {@param componentName} represents the application component of PiP window.
     */
    void onActivityHidden(in ComponentName componentName);
}
+0 −16
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.wm.shell.pip;

import android.content.ComponentName;
import android.os.RemoteException;
import android.view.IPinnedTaskListener;
import android.view.WindowManagerGlobal;
@@ -70,12 +69,6 @@ public class PinnedStackListenerForwarder {
        }
    }

    private void onActivityHidden(ComponentName componentName) {
        for (PinnedTaskListener listener : mListeners) {
            listener.onActivityHidden(componentName);
        }
    }

    @BinderThread
    private class PinnedTaskListenerImpl extends IPinnedTaskListener.Stub {
        @Override
@@ -91,13 +84,6 @@ public class PinnedStackListenerForwarder {
                PinnedStackListenerForwarder.this.onImeVisibilityChanged(imeVisible, imeHeight);
            });
        }

        @Override
        public void onActivityHidden(ComponentName componentName) {
            mMainExecutor.execute(() -> {
                PinnedStackListenerForwarder.this.onActivityHidden(componentName);
            });
        }
    }

    /**
@@ -108,7 +94,5 @@ public class PinnedStackListenerForwarder {
        public void onMovementBoundsChanged(boolean fromImeAdjustment) {}

        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {}

        public void onActivityHidden(ComponentName componentName) {}
    }
}
+20 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.util.RotationUtils.rotateBounds;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_PIP;
import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -300,6 +301,10 @@ public class PipTransition extends PipTransitionController {
                    finishTransaction);
        }

        if (isCurrentPipActivityClosed(info)) {
            mPipBoundsState.setLastPipComponentName(null /* componentName */);
        }

        return false;
    }

@@ -322,6 +327,21 @@ public class PipTransition extends PipTransitionController {
        return true;
    }

    private boolean isCurrentPipActivityClosed(TransitionInfo info) {
        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
            TransitionInfo.Change change = info.getChanges().get(i);
            boolean isTaskChange = change.getTaskInfo() != null;
            boolean hasComponentNameOfPip = change.getActivityComponent() != null
                    && change.getActivityComponent().equals(
                            mPipBoundsState.getLastPipComponentName());
            if (!isTaskChange && change.getMode() == TRANSIT_CLOSE && hasComponentNameOfPip) {
                return true;
            }
        }
        return false;
    }


    @Override
    public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
+0 −9
Original line number Diff line number Diff line
@@ -367,15 +367,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
                    false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */,
                    null /* windowContainerTransaction */);
        }

        @Override
        public void onActivityHidden(ComponentName componentName) {
            if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
                // The activity was removed, we don't want to restore to the reentry state
                // saved for this component anymore.
                mPipBoundsState.setLastPipComponentName(null);
            }
        }
    }

    /**
+0 −22
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import static org.mockito.Mockito.when;

import static java.lang.Integer.MAX_VALUE;

import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
@@ -234,27 +233,6 @@ public class PipControllerTest extends ShellTestCase {
                mMockOneHandedController, mMockExecutor));
    }

    @Test
    public void onActivityHidden_isLastPipComponentName_clearLastPipComponent() {
        final ComponentName component1 = new ComponentName(mContext, "component1");
        when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);

        mPipController.mPinnedTaskListener.onActivityHidden(component1);

        verify(mMockPipBoundsState).setLastPipComponentName(null);
    }

    @Test
    public void onActivityHidden_isNotLastPipComponentName_lastPipComponentNotCleared() {
        final ComponentName component1 = new ComponentName(mContext, "component1");
        final ComponentName component2 = new ComponentName(mContext, "component2");
        when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);

        mPipController.mPinnedTaskListener.onActivityHidden(component2);

        verify(mMockPipBoundsState, never()).setLastPipComponentName(null);
    }

    @Test
    public void saveReentryState_savesPipBoundsState() {
        final Rect bounds = new Rect(0, 0, 10, 10);
Loading