TV Pip fixes after menu migration to Window
Moving TV Pip menu from an Activity to a Window caused NPE in TvPipMenuController when referencing PipMenuView. This change fixes the NPE as well as does initial refactoring in TV Pip implementation, such as removing .tv.PipController.Listener and .tv.PipContoller.suspend(resume)PipResizing methods. Bug: 174818743 Bug: 171956642 Test: atest WMShellFlickerTests:TvPipBasicTest Change-Id: Ifcd6c777a561421b45703300e3eccb44c13e2172
This commit is contained in:
@@ -37,7 +37,6 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
@@ -56,8 +55,6 @@ import com.android.wm.shell.pip.PipBoundsState;
|
||||
import com.android.wm.shell.pip.PipMediaController;
|
||||
import com.android.wm.shell.pip.PipTaskOrganizer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -87,42 +84,21 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
private static final int TASK_ID_NO_PIP = -1;
|
||||
private static final int INVALID_RESOURCE_TYPE = -1;
|
||||
|
||||
public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH = 0x1;
|
||||
|
||||
/**
|
||||
* PIPed activity is playing a media and it can be paused.
|
||||
*/
|
||||
static final int PLAYBACK_STATE_PLAYING = 0;
|
||||
/**
|
||||
* PIPed activity has a paused media and it can be played.
|
||||
*/
|
||||
static final int PLAYBACK_STATE_PAUSED = 1;
|
||||
/**
|
||||
* Users are unable to control PIPed activity's media playback.
|
||||
*/
|
||||
static final int PLAYBACK_STATE_UNAVAILABLE = 2;
|
||||
|
||||
private static final int CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS = 3000;
|
||||
|
||||
private int mSuspendPipResizingReason;
|
||||
|
||||
private final Context mContext;
|
||||
private final PipBoundsState mPipBoundsState;
|
||||
private final PipBoundsAlgorithm mPipBoundsAlgorithm;
|
||||
private final PipTaskOrganizer mPipTaskOrganizer;
|
||||
private final PipMediaController mPipMediaController;
|
||||
private final TvPipMenuController mTvPipMenuController;
|
||||
private final PipNotification mPipNotification;
|
||||
|
||||
private IActivityTaskManager mActivityTaskManager;
|
||||
private int mState = STATE_NO_PIP;
|
||||
private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP;
|
||||
private final Handler mHandler = new Handler();
|
||||
private List<Listener> mListeners = new ArrayList<>();
|
||||
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
private int mPipTaskId = TASK_ID_NO_PIP;
|
||||
private int mPinnedStackId = INVALID_STACK_ID;
|
||||
private String[] mLastPackagesResourceGranted;
|
||||
private PipNotification mPipNotification;
|
||||
private ParceledListSlice<RemoteAction> mCustomActions;
|
||||
private WindowManagerShellWrapper mWindowManagerShellWrapper;
|
||||
private int mResizeAnimationDuration;
|
||||
@@ -135,9 +111,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
private boolean mImeVisible;
|
||||
private int mImeHeightAdjustment;
|
||||
|
||||
private final Runnable mResizePinnedStackRunnable =
|
||||
() -> resizePinnedStack(mResumeResizePinnedStackRunnableState);
|
||||
private final Runnable mClosePipRunnable = () -> closePip();
|
||||
private final Runnable mClosePipRunnable = this::closePip;
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -244,8 +218,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
mPipTaskOrganizer.registerPipTransitionCallback(this);
|
||||
mActivityTaskManager = ActivityTaskManager.getService();
|
||||
|
||||
addListener(mPipNotification);
|
||||
|
||||
final IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(ACTION_CLOSE);
|
||||
intentFilter.addAction(ACTION_MENU);
|
||||
@@ -347,9 +319,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
mPinnedStackId = INVALID_STACK_ID;
|
||||
}
|
||||
}
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onPipActivityClosed();
|
||||
}
|
||||
mPipNotification.dismiss();
|
||||
mTvPipMenuController.hideMenu();
|
||||
mHandler.removeCallbacks(mClosePipRunnable);
|
||||
}
|
||||
|
||||
@@ -360,9 +331,9 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
if (DEBUG) Log.d(TAG, "movePipToFullscreen(), current state=" + getStateDescription());
|
||||
|
||||
mPipTaskId = TASK_ID_NO_PIP;
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onMoveToFullscreen();
|
||||
}
|
||||
mTvPipMenuController.hideMenu();
|
||||
mPipNotification.dismiss();
|
||||
|
||||
resizePinnedStack(STATE_NO_PIP);
|
||||
}
|
||||
|
||||
@@ -386,9 +357,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
// Set state to STATE_PIP so we show it when the pinned stack animation ends.
|
||||
mState = STATE_PIP;
|
||||
mPipMediaController.onActivityPinned();
|
||||
for (int i = mListeners.size() - 1; i >= 0; i--) {
|
||||
mListeners.get(i).onPipEntered(packageName);
|
||||
}
|
||||
mPipNotification.show(packageName);
|
||||
}
|
||||
|
||||
private void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
|
||||
@@ -434,62 +403,18 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspends resizing operation on the Pip until {@link #resumePipResizing} is called
|
||||
*
|
||||
* @param reason The reason for suspending resizing operations on the Pip.
|
||||
*/
|
||||
public void suspendPipResizing(int reason) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"suspendPipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
|
||||
}
|
||||
mSuspendPipResizingReason |= reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes resizing operation on the Pip that was previously suspended.
|
||||
*
|
||||
* @param reason The reason resizing operations on the Pip was suspended.
|
||||
*/
|
||||
public void resumePipResizing(int reason) {
|
||||
if ((mSuspendPipResizingReason & reason) == 0) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"resumePipResizing() reason=" + reason + " callers=" + Debug.getCallers(2));
|
||||
}
|
||||
mSuspendPipResizingReason &= ~reason;
|
||||
mHandler.post(mResizePinnedStackRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the Pip to the appropriate size for the input state.
|
||||
*
|
||||
* @param state In Pip state also used to determine the new size for the Pip.
|
||||
*/
|
||||
public void resizePinnedStack(int state) {
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "resizePinnedStack() state=" + stateToName(state) + ", current state="
|
||||
+ getStateDescription(), new Exception());
|
||||
}
|
||||
|
||||
boolean wasStateNoPip = (mState == STATE_NO_PIP);
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onPipResizeAboutToStart();
|
||||
}
|
||||
if (mSuspendPipResizingReason != 0) {
|
||||
mResumeResizePinnedStackRunnableState = state;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "resizePinnedStack() deferring"
|
||||
+ " mSuspendPipResizingReason=" + mSuspendPipResizingReason
|
||||
+ " mResumeResizePinnedStackRunnableState="
|
||||
+ stateToName(mResumeResizePinnedStackRunnableState));
|
||||
}
|
||||
return;
|
||||
}
|
||||
final boolean wasStateNoPip = (mState == STATE_NO_PIP);
|
||||
mTvPipMenuController.hideMenu();
|
||||
mState = state;
|
||||
final Rect newBounds;
|
||||
switch (mState) {
|
||||
@@ -517,44 +442,19 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current state, or the pending state if the state change was previously suspended.
|
||||
* @return the current state.
|
||||
*/
|
||||
private int getState() {
|
||||
if (mSuspendPipResizingReason != 0) {
|
||||
return mResumeResizePinnedStackRunnableState;
|
||||
}
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows PIP menu UI by launching {@link PipMenuActivity}. It also locates the pinned
|
||||
* stack to the centered PIP bound {@link R.config_centeredPictureInPictureBounds}.
|
||||
*/
|
||||
private void showPipMenu() {
|
||||
if (DEBUG) Log.d(TAG, "showPipMenu(), current state=" + getStateDescription());
|
||||
|
||||
mState = STATE_PIP_MENU;
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onShowPipMenu();
|
||||
}
|
||||
|
||||
mTvPipMenuController.showMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Listener} to PipController.
|
||||
*/
|
||||
void addListener(Listener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link Listener} from PipController.
|
||||
*/
|
||||
void removeListener(Listener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if PIP is shown.
|
||||
*/
|
||||
@@ -626,33 +526,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A listener interface to receive notification on changes in PIP.
|
||||
*/
|
||||
public interface Listener {
|
||||
/**
|
||||
* Invoked when an activity is pinned and PIP manager is set corresponding information.
|
||||
* Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
|
||||
* because there's no guarantee for the PIP manager be return relavent information
|
||||
* correctly. (e.g. {@link Pip.isPipShown}).
|
||||
*/
|
||||
void onPipEntered(String packageName);
|
||||
/** Invoked when a PIPed activity is closed. */
|
||||
void onPipActivityClosed();
|
||||
/** Invoked when the PIP menu gets shown. */
|
||||
void onShowPipMenu();
|
||||
/** Invoked when the PIPed activity is about to return back to the fullscreen. */
|
||||
void onMoveToFullscreen();
|
||||
/** Invoked when we are above to start resizing the Pip. */
|
||||
void onPipResizeAboutToStart();
|
||||
}
|
||||
|
||||
private String getStateDescription() {
|
||||
if (mSuspendPipResizingReason == 0) {
|
||||
return stateToName(mState);
|
||||
}
|
||||
return stateToName(mResumeResizePinnedStackRunnableState) + " (while " + stateToName(mState)
|
||||
+ " is suspended)";
|
||||
return stateToName(mState);
|
||||
}
|
||||
|
||||
private static String stateToName(int state) {
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.wm.shell.pip.tv;
|
||||
|
||||
import static android.view.KeyEvent.ACTION_UP;
|
||||
import static android.view.KeyEvent.KEYCODE_BACK;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.annotation.Nullable;
|
||||
@@ -36,25 +39,22 @@ import java.util.Collections;
|
||||
/**
|
||||
* The Menu View that shows controls of the PiP. Always fullscreen.
|
||||
*/
|
||||
public class PipMenuView extends FrameLayout implements PipController.Listener {
|
||||
public class PipMenuView extends FrameLayout {
|
||||
private static final String TAG = "PipMenuView";
|
||||
private static final boolean DEBUG = PipController.DEBUG;
|
||||
|
||||
private final PipController mPipController;
|
||||
private final Animator mFadeInAnimation;
|
||||
private final Animator mFadeOutAnimation;
|
||||
private final PipControlsViewController mPipControlsViewController;
|
||||
private boolean mRestorePipSizeWhenClose;
|
||||
@Nullable
|
||||
private OnBackPressListener mOnBackPressListener;
|
||||
|
||||
public PipMenuView(Context context, PipController pipController) {
|
||||
super(context, null, 0);
|
||||
mPipController = pipController;
|
||||
|
||||
inflate(context, R.layout.tv_pip_menu, this);
|
||||
|
||||
mPipControlsViewController = new PipControlsViewController(
|
||||
findViewById(R.id.pip_controls), mPipController);
|
||||
mRestorePipSizeWhenClose = true;
|
||||
findViewById(R.id.pip_controls), pipController);
|
||||
mFadeInAnimation = AnimatorInflater.loadAnimator(
|
||||
mContext, R.anim.tv_pip_menu_fade_in_animation);
|
||||
mFadeInAnimation.setTarget(mPipControlsViewController.getView());
|
||||
@@ -63,16 +63,6 @@ public class PipMenuView extends FrameLayout implements PipController.Listener {
|
||||
mFadeOutAnimation.setTarget(mPipControlsViewController.getView());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
|
||||
&& event.getAction() == KeyEvent.ACTION_UP) {
|
||||
restorePipAndFinish();
|
||||
return true;
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
SurfaceControl getWindowSurfaceControl() {
|
||||
final ViewRootImpl root = getViewRootImpl();
|
||||
@@ -87,53 +77,39 @@ public class PipMenuView extends FrameLayout implements PipController.Listener {
|
||||
}
|
||||
|
||||
void showMenu() {
|
||||
mPipController.addListener(this);
|
||||
mFadeInAnimation.start();
|
||||
setAlpha(1.0f);
|
||||
try {
|
||||
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
|
||||
getViewRootImpl().getInputToken(), true /* grantFocus */);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to update focus as menu appears", e);
|
||||
}
|
||||
grantWindowFocus(true);
|
||||
}
|
||||
|
||||
void hideMenu() {
|
||||
mPipController.removeListener(this);
|
||||
mPipController.resumePipResizing(
|
||||
PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
|
||||
mFadeOutAnimation.start();
|
||||
setAlpha(0.0f);
|
||||
grantWindowFocus(false);
|
||||
}
|
||||
|
||||
private void grantWindowFocus(boolean grantFocus) {
|
||||
try {
|
||||
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(null /* window */,
|
||||
getViewRootImpl().getInputToken(), false /* grantFocus */);
|
||||
getViewRootImpl().getInputToken(), grantFocus);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to update focus as menu disappears", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void restorePipAndFinish() {
|
||||
if (DEBUG) Log.d(TAG, "restorePipAndFinish()");
|
||||
void setOnBackPressListener(OnBackPressListener onBackPressListener) {
|
||||
mOnBackPressListener = onBackPressListener;
|
||||
}
|
||||
|
||||
if (mRestorePipSizeWhenClose) {
|
||||
if (DEBUG) Log.d(TAG, " > restoring to the default position");
|
||||
|
||||
// When PIP menu activity is closed, restore to the default position.
|
||||
mPipController.resizePinnedStack(PipController.STATE_PIP);
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (event.getKeyCode() == KEYCODE_BACK && event.getAction() == ACTION_UP
|
||||
&& mOnBackPressListener != null) {
|
||||
mOnBackPressListener.onBackPress();
|
||||
return true;
|
||||
} else {
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
hideMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipEntered(String packageName) {
|
||||
if (DEBUG) Log.d(TAG, "onPipEntered(), packageName=" + packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipActivityClosed() {
|
||||
if (DEBUG) Log.d(TAG, "onPipActivityClosed()");
|
||||
|
||||
hideMenu();
|
||||
}
|
||||
|
||||
void setAppActions(ParceledListSlice<RemoteAction> actions) {
|
||||
@@ -144,27 +120,7 @@ public class PipMenuView extends FrameLayout implements PipController.Listener {
|
||||
hasCustomActions ? actions.getList() : Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowPipMenu() {
|
||||
if (DEBUG) Log.d(TAG, "onShowPipMenu()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveToFullscreen() {
|
||||
if (DEBUG) Log.d(TAG, "onMoveToFullscreen()");
|
||||
|
||||
// Moving PIP to fullscreen is implemented by resizing PINNED_STACK with null bounds.
|
||||
// This conflicts with restoring PIP position, so disable it.
|
||||
mRestorePipSizeWhenClose = false;
|
||||
hideMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipResizeAboutToStart() {
|
||||
if (DEBUG) Log.d(TAG, "onPipResizeAboutToStart()");
|
||||
|
||||
hideMenu();
|
||||
mPipController.suspendPipResizing(
|
||||
PipController.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
|
||||
interface OnBackPressListener {
|
||||
void onBackPress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.Objects;
|
||||
* <p>Once it's created, it will manage the PIP notification UI by itself except for handling
|
||||
* configuration changes.
|
||||
*/
|
||||
public class PipNotification implements PipController.Listener {
|
||||
public class PipNotification {
|
||||
private static final boolean DEBUG = PipController.DEBUG;
|
||||
private static final String TAG = "PipNotification";
|
||||
|
||||
@@ -79,38 +79,21 @@ public class PipNotification implements PipController.Listener {
|
||||
onConfigurationChanged(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipEntered(String packageName) {
|
||||
void show(String packageName) {
|
||||
mPackageName = packageName;
|
||||
notifyPipNotification();
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipActivityClosed() {
|
||||
dismissPipNotification();
|
||||
void dismiss() {
|
||||
mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
|
||||
mNotified = false;
|
||||
mPackageName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowPipMenu() {
|
||||
// no-op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveToFullscreen() {
|
||||
dismissPipNotification();
|
||||
mPackageName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPipResizeAboutToStart() {
|
||||
// no-op.
|
||||
}
|
||||
|
||||
private void onMediaMetadataChanged(MediaMetadata metadata) {
|
||||
if (updateMediaControllerMetadata(metadata) && mNotified) {
|
||||
// update notification
|
||||
notifyPipNotification();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,11 +106,11 @@ public class PipNotification implements PipController.Listener {
|
||||
mDefaultIconResId = R.drawable.pip_icon;
|
||||
if (mNotified) {
|
||||
// update notification
|
||||
notifyPipNotification();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyPipNotification() {
|
||||
private void update() {
|
||||
mNotified = true;
|
||||
mNotificationBuilder
|
||||
.setShowWhen(true)
|
||||
@@ -144,11 +127,6 @@ public class PipNotification implements PipController.Listener {
|
||||
mNotificationBuilder.build());
|
||||
}
|
||||
|
||||
private void dismissPipNotification() {
|
||||
mNotified = false;
|
||||
mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
|
||||
}
|
||||
|
||||
private boolean updateMediaControllerMetadata(MediaMetadata metadata) {
|
||||
String title = null;
|
||||
Bitmap art = null;
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP;
|
||||
import android.app.RemoteAction;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.wm.shell.common.SystemWindows;
|
||||
@@ -31,6 +32,8 @@ import com.android.wm.shell.pip.PipMenuController;
|
||||
* Manages the visibility of the PiP Menu as user interacts with PiP.
|
||||
*/
|
||||
public class TvPipMenuController implements PipMenuController {
|
||||
private static final String TAG = "TvPipMenuController";
|
||||
private static final boolean DEBUG = PipController.DEBUG;
|
||||
|
||||
private final Context mContext;
|
||||
private final SystemWindows mSystemWindows;
|
||||
@@ -52,6 +55,8 @@ public class TvPipMenuController implements PipMenuController {
|
||||
|
||||
@Override
|
||||
public void showMenu() {
|
||||
if (DEBUG) Log.d(TAG, "showMenu()");
|
||||
|
||||
if (mMenuView != null) {
|
||||
mSystemWindows.updateViewLayout(mMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE,
|
||||
mPipBoundsState.getDisplayBounds().width(),
|
||||
@@ -68,27 +73,62 @@ public class TvPipMenuController implements PipMenuController {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attach(SurfaceControl leash) {
|
||||
if (mMenuView == null) {
|
||||
mMenuView = new PipMenuView(mContext, mPipController);
|
||||
mSystemWindows.addView(mMenuView,
|
||||
getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
|
||||
0, SHELL_ROOT_LAYER_PIP);
|
||||
mLeash = leash;
|
||||
void hideMenu() {
|
||||
if (DEBUG) Log.d(TAG, "hideMenu()");
|
||||
|
||||
if (isMenuVisible()) {
|
||||
mMenuView.hideMenu();
|
||||
mPipController.resizePinnedStack(PipController.STATE_PIP);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attach(SurfaceControl leash) {
|
||||
mLeash = leash;
|
||||
attachPipMenuView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
hideMenu();
|
||||
detachPipMenuView();
|
||||
mLeash = null;
|
||||
}
|
||||
|
||||
private void attachPipMenuView() {
|
||||
if (DEBUG) Log.d(TAG, "attachPipMenuView()");
|
||||
|
||||
if (mMenuView != null) {
|
||||
detachPipMenuView();
|
||||
}
|
||||
|
||||
mMenuView = new PipMenuView(mContext, mPipController);
|
||||
mMenuView.setOnBackPressListener(this::hideMenu);
|
||||
mSystemWindows.addView(mMenuView,
|
||||
getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
|
||||
0, SHELL_ROOT_LAYER_PIP);
|
||||
}
|
||||
|
||||
private void detachPipMenuView() {
|
||||
if (DEBUG) Log.d(TAG, "detachPipMenuView()");
|
||||
|
||||
if (mMenuView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSystemWindows.removeView(mMenuView);
|
||||
mMenuView = null;
|
||||
mLeash = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAppActions(ParceledListSlice<RemoteAction> appActions) {
|
||||
mMenuView.setAppActions(appActions);
|
||||
if (DEBUG) Log.d(TAG, "setAppActions(), actions=" + appActions);
|
||||
|
||||
if (mMenuView != null) {
|
||||
mMenuView.setAppActions(appActions);
|
||||
} else {
|
||||
Log.w(TAG, "Cannot set remote actions, there is no View");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user