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

Commit 4d8681ff authored by Winson Chung's avatar Winson Chung
Browse files

Workaround to ensure that PIP activities have a visible shadow.

- When the window for the activity enters PIP, update the outline provider
  to override the alpha of the shadow (to be opaque) to ensure that is is
  visible.  Only applies to the task root activity.

Bug: 36741700
Test: Launch YT, ensure that there is a shadow when after it enters PIP
Test: go/wm-smoke
Test: android.server.cts.ActivityManagerPinnedStackTests

Change-Id: If089dae84e4916d3d0e7bbeb316215b46e522e05
parent 2b2221e9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -5790,6 +5790,7 @@ public class Activity extends ContextThemeWrapper
     *
     * @return True if this is the root activity, else false.
     */
    @Override
    public boolean isTaskRoot() {
        try {
            return ActivityManager.getService().getTaskForActivity(mToken, true) >= 0;
@@ -7207,6 +7208,9 @@ public class Activity extends ContextThemeWrapper
                "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode
                        + " " + newConfig);
        mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
        if (mWindow != null) {
            mWindow.onPictureInPictureModeChanged(isInPictureInPictureMode);
        }
        onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
    }

+9 −0
Original line number Diff line number Diff line
@@ -624,6 +624,9 @@ public abstract class Window {

        /** Returns the current stack Id for the window. */
        int getWindowStackId() throws RemoteException;

        /** Returns whether the window belongs to the task root. */
        boolean isTaskRoot();
    }

    /**
@@ -2270,6 +2273,12 @@ public abstract class Window {
     */
    public abstract void onMultiWindowModeChanged();

    /**
     * Called when the activity changes to/from picture-in-picture mode.
     * @hide
     */
    public abstract void onPictureInPictureModeChanged(boolean isInPictureInPictureMode);

    /**
     * Called when the activity just relaunched.
     * @hide
+53 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.policy;

import android.graphics.Outline;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
import com.android.internal.policy.PhoneWindow.PanelFeatureState;
@@ -135,6 +137,16 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
                    com.android.internal.R.id.navigationBarBackground,
                    0 /* hideWindowFlag */);

    // This is used to workaround an issue where the PiP shadow can be transparent if the window
    // background is transparent
    private static final ViewOutlineProvider PIP_OUTLINE_PROVIDER = new ViewOutlineProvider() {
        @Override
        public void getOutline(View view, Outline outline) {
            outline.setRect(0, 0, view.getWidth(), view.getHeight());
            outline.setAlpha(1f);
        }
    };

    // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
    // size calculation takes the shadow size into account. We set the elevation currently
    // to max until the first layout command has been executed.
@@ -142,6 +154,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind

    private boolean mElevationAdjustedForStack = false;

    // Keeps track of the picture-in-picture mode for the view shadow
    private boolean mIsInPictureInPictureMode;

    // Stores the previous outline provider prior to applying PIP_OUTLINE_PROVIDER
    private ViewOutlineProvider mLastOutlineProvider;

    int mDefaultOpacity = PixelFormat.OPAQUE;

    /** The feature ID of the panel, or -1 if this is the application's DecorView */
@@ -1404,6 +1422,41 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        }
    }

    /**
     * Overrides the view outline when the activity enters picture-in-picture to ensure that it has
     * an opaque shadow even if the window background is completely transparent. This only applies
     * to activities that are currently the task root.
     */
    public void updatePictureInPictureOutlineProvider(boolean isInPictureInPictureMode) {
        if (mIsInPictureInPictureMode == isInPictureInPictureMode) {
            return;
        }

        if (isInPictureInPictureMode) {
            final Window.WindowControllerCallback callback =
                    mWindow.getWindowControllerCallback();
            if (callback != null && callback.isTaskRoot()) {
                // Call super implementation directly as we don't want to save the PIP outline
                // provider to be restored
                super.setOutlineProvider(PIP_OUTLINE_PROVIDER);
            }
        } else {
            // Restore the previous outline provider
            if (getOutlineProvider() != mLastOutlineProvider) {
                setOutlineProvider(mLastOutlineProvider);
            }
        }
        mIsInPictureInPictureMode = isInPictureInPictureMode;
    }

    @Override
    public void setOutlineProvider(ViewOutlineProvider provider) {
        super.setOutlineProvider(provider);

        // Save the outline provider set to ensure that we can restore when the activity leaves PiP
        mLastOutlineProvider = provider;
    }

    private void drawableChanged() {
        if (mChanging) {
            return;
+7 −0
Original line number Diff line number Diff line
@@ -728,6 +728,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
        }
    }

    @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
        if (mDecor != null) {
            mDecor.updatePictureInPictureOutlineProvider(isInPictureInPictureMode);
        }
    }

    @Override
    public void reportActivityRelaunched() {
        if (mDecor != null && mDecor.getViewRootImpl() != null) {
+4 −0
Original line number Diff line number Diff line
@@ -721,6 +721,10 @@ public class StatusBarWindowView extends FrameLayout {
        public void onMultiWindowModeChanged() {
        }

        @Override
        public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
        }

        @Override
        public void reportActivityRelaunched() {
        }