summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ben Lin <linben@google.com> 2020-08-25 01:44:25 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-08-25 01:44:25 +0000
commitdb02000f83e9637a3d51d26a0e34ba8d3872c2c5 (patch)
treedc6c55bf2b084d98f96e267d1f29edb8574db023
parentae905ec585adef7a8bb31e3c04521ebd10ee9280 (diff)
parentabaefa0c671d0a2f23e4ad4dfcdf080f6020d19f (diff)
Merge "Migrate from PipMenuActivity -> PipMenuView."
-rw-r--r--libs/WindowManager/Shell/res/layout/pip_menu.xml (renamed from libs/WindowManager/Shell/res/layout/pip_menu_activity.xml)0
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java10
-rw-r--r--packages/SystemUI/AndroidManifest.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java375
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java (renamed from packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java)399
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java10
12 files changed, 241 insertions, 688 deletions
diff --git a/libs/WindowManager/Shell/res/layout/pip_menu_activity.xml b/libs/WindowManager/Shell/res/layout/pip_menu.xml
index 2e0a5e09e34f..2e0a5e09e34f 100644
--- a/libs/WindowManager/Shell/res/layout/pip_menu_activity.xml
+++ b/libs/WindowManager/Shell/res/layout/pip_menu.xml
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
index fd6685ffdb8f..6d31a8d69ebe 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
@@ -22,8 +22,6 @@ import android.view.IWindowManager;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.pip.phone.PipMenuActivity;
-import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
import com.android.systemui.wm.DisplaySystemBarsController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
@@ -43,12 +41,4 @@ public class CarWMShellModule {
return new DisplaySystemBarsController(context, wmService, displayController,
mainHandler, transactionPool);
}
-
- /** TODO(b/150319024): PipMenuActivity will move to a Window */
- @SysUISingleton
- @PipMenuActivityClass
- @Provides
- Class<?> providePipMenuActivityClass() {
- return PipMenuActivity.class;
- }
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index af008b996172..7f4f580abf94 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -530,20 +530,6 @@
androidprv:alwaysFocusable="true"
android:excludeFromRecents="true" />
- <activity
- android:name=".pip.phone.PipMenuActivity"
- android:permission="com.android.systemui.permission.SELF"
- android:theme="@style/PipPhoneOverlayControlTheme"
- android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
- android:excludeFromRecents="true"
- android:exported="false"
- android:resizeableActivity="true"
- android:supportsPictureInPicture="true"
- android:stateNotNeeded="true"
- android:taskAffinity=""
- android:launchMode="singleTop"
- androidprv:alwaysFocusable="true" />
-
<!-- started from SliceProvider -->
<activity android:name=".SlicePermissionActivity"
android:theme="@style/Theme.SystemUI.Dialog.Alert"
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 7421ec14398b..c956702c9216 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -49,6 +49,9 @@ import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowManager;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -57,6 +60,7 @@ import android.window.WindowOrganizer;
import com.android.internal.os.SomeArgs;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.pip.phone.PipMenuActivityController;
import com.android.systemui.pip.phone.PipUpdateThread;
import com.android.systemui.stackdivider.SplitScreen;
import com.android.wm.shell.R;
@@ -95,6 +99,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
private static final int MSG_FINISH_RESIZE = 4;
private static final int MSG_RESIZE_USER = 5;
+ private final Context mContext;
private final Handler mMainHandler;
private final Handler mUpdateHandler;
private final PipBoundsHandler mPipBoundsHandler;
@@ -107,6 +112,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
private final Optional<SplitScreen> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
+ private SurfaceControlViewHost mPipViewHost;
+ private SurfaceControl mPipMenuSurface;
// These callbacks are called on the update thread
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
@@ -212,6 +219,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer) {
+ mContext = context;
mMainHandler = new Handler(Looper.getMainLooper());
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
mPipBoundsHandler = boundsHandler;
@@ -504,6 +512,45 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
}
/**
+ * Setup the ViewHost and attach the provided menu view to the ViewHost.
+ */
+ public void attachPipMenuViewHost(View menuView, WindowManager.LayoutParams lp) {
+ if (mPipMenuSurface != null) {
+ Log.e(TAG, "PIP Menu View already created and attached.");
+ return;
+ }
+
+ if (Looper.getMainLooper() != Looper.myLooper()) {
+ throw new RuntimeException("PipMenuView needs to be attached on the main thread.");
+ }
+
+ mPipViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(),
+ (android.os.Binder) null);
+ mPipMenuSurface = mPipViewHost.getSurfacePackage().getSurfaceControl();
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.reparent(mPipMenuSurface, mLeash);
+ transaction.show(mPipMenuSurface);
+ transaction.setRelativeLayer(mPipMenuSurface, mLeash, 1);
+ transaction.apply();
+ mPipViewHost.setView(menuView, lp);
+ }
+
+
+ /**
+ * Releases the PIP Menu's View host, remove it from PIP task surface.
+ */
+ public void detachPipMenuViewHost() {
+ if (mPipMenuSurface != null) {
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.remove(mPipMenuSurface);
+ transaction.apply();
+ mPipMenuSurface = null;
+ mPipViewHost = null;
+ }
+ }
+
+
+ /**
* Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
* Meanwhile this callback is invoked whenever the task is removed. For instance:
* - as a result of removeStacksInWindowingModes from WM
@@ -838,6 +885,12 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
WindowContainerTransaction wct = new WindowContainerTransaction();
prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);
applyFinishBoundsResize(wct, direction);
+ runOnMainHandler(() -> {
+ if (mPipViewHost != null) {
+ mPipViewHost.relayout(PipMenuActivityController.getPipMenuLayoutParams(
+ destinationBounds.width(), destinationBounds.height()));
+ }
+ });
}
private void prepareFinishResizeTransaction(Rect destinationBounds,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index d8864ec72dc3..5ef5b902327e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -49,7 +49,6 @@ import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
-import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
@@ -267,7 +266,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
@Inject
public PipManager(Context context, BroadcastDispatcher broadcastDispatcher,
- @PipMenuActivityClass Class<?> pipMenuActivityClass,
ConfigurationController configController,
DeviceConfigProxy deviceConfig,
DisplayController displayController,
@@ -296,8 +294,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
mPipTaskOrganizer.registerPipTransitionCallback(this);
mInputConsumerController = InputConsumerController.getPipInputConsumer();
mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
- mMenuController = new PipMenuActivityController(context, pipMenuActivityClass,
- mMediaController, mInputConsumerController);
+ mMenuController = new PipMenuActivityController(context,
+ mMediaController, mInputConsumerController, mPipTaskOrganizer);
mTouchHandler = new PipTouchHandler(context, mActivityManager,
mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer,
floatingContentCoordinator, deviceConfig, sysUiState, pipUiEventLogger);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 383f6b3bf79d..873ba26b39ab 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -19,27 +19,20 @@ package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import android.annotation.Nullable;
import android.app.ActivityManager.StackInfo;
-import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.RemoteAction;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.os.Bundle;
import android.os.Debug;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.WindowManager;
+import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController;
@@ -58,30 +51,10 @@ public class PipMenuActivityController {
private static final String TAG = "PipMenuActController";
private static final boolean DEBUG = false;
- public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
- public static final String EXTRA_ACTIONS = "actions";
- public static final String EXTRA_STACK_BOUNDS = "stack_bounds";
- public static final String EXTRA_ALLOW_TIMEOUT = "allow_timeout";
- public static final String EXTRA_WILL_RESIZE_MENU = "resize_menu_on_show";
- public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction";
- public static final String EXTRA_MENU_STATE = "menu_state";
- public static final String EXTRA_SHOW_MENU_WITH_DELAY = "show_menu_with_delay";
- public static final String EXTRA_SHOW_RESIZE_HANDLE = "show_resize_handle";
- public static final String EXTRA_MESSAGE_CALLBACK_WHAT = "message_callback_what";
-
- public static final int MESSAGE_MENU_STATE_CHANGED = 100;
- public static final int MESSAGE_EXPAND_PIP = 101;
- public static final int MESSAGE_DISMISS_PIP = 103;
- public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
- public static final int MESSAGE_SHOW_MENU = 107;
-
public static final int MENU_STATE_NONE = 0;
public static final int MENU_STATE_CLOSE = 1;
public static final int MENU_STATE_FULL = 2;
- // The duration to wait before we consider the start activity as having timed out
- private static final long START_ACTIVITY_REQUEST_TIMEOUT_MS = 300;
-
/**
* A listener interface to receive notification on changes in PIP.
*/
@@ -110,9 +83,8 @@ public class PipMenuActivityController {
void onPipShowMenu();
}
- /** TODO(b/150319024): PipMenuActivity will move to a Window */
- private Class<?> mPipMenuActivityClass;
private Context mContext;
+ private PipTaskOrganizer mPipTaskOrganizer;
private PipMediaController mMediaController;
private InputConsumerController mInputConsumerController;
@@ -121,63 +93,7 @@ public class PipMenuActivityController {
private ParceledListSlice<RemoteAction> mMediaActions;
private int mMenuState;
- // The dismiss fraction update is sent frequently, so use a temporary bundle for the message
- private Bundle mTmpDismissFractionData = new Bundle();
-
- private Runnable mOnAnimationEndRunnable;
- private boolean mStartActivityRequested;
- private long mStartActivityRequestedTime;
- private Messenger mToActivityMessenger;
- private Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_MENU_STATE_CHANGED: {
- final int menuState = msg.arg1;
- final boolean resize = msg.arg2 != 0;
- onMenuStateChanged(menuState, resize,
- getMenuStateChangeFinishedCallback(msg.replyTo, (Bundle) msg.obj));
- break;
- }
- case MESSAGE_EXPAND_PIP: {
- mListeners.forEach(Listener::onPipExpand);
- break;
- }
- case MESSAGE_DISMISS_PIP: {
- mListeners.forEach(Listener::onPipDismiss);
- break;
- }
- case MESSAGE_SHOW_MENU: {
- mListeners.forEach(Listener::onPipShowMenu);
- break;
- }
- case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
- mToActivityMessenger = msg.replyTo;
- setStartActivityRequested(false);
- if (mOnAnimationEndRunnable != null) {
- mOnAnimationEndRunnable.run();
- mOnAnimationEndRunnable = null;
- }
- // Mark the menu as invisible once the activity finishes as well
- if (mToActivityMessenger == null) {
- final boolean resize = msg.arg1 != 0;
- onMenuStateChanged(MENU_STATE_NONE, resize, null /* callback */);
- }
- break;
- }
- }
- }
- };
- private Messenger mMessenger = new Messenger(mHandler);
-
- private Runnable mStartActivityRequestedTimeoutRunnable = () -> {
- setStartActivityRequested(false);
- if (mOnAnimationEndRunnable != null) {
- mOnAnimationEndRunnable.run();
- mOnAnimationEndRunnable = null;
- }
- Log.e(TAG, "Expected start menu activity request timed out");
- };
+ private PipMenuView mPipMenuView;
private ActionListener mMediaActionListener = new ActionListener() {
@Override
@@ -187,39 +103,40 @@ public class PipMenuActivityController {
}
};
- public PipMenuActivityController(Context context, Class<?> pipMenuActivityClass,
- PipMediaController mediaController, InputConsumerController inputConsumerController
+ public PipMenuActivityController(Context context,
+ PipMediaController mediaController, InputConsumerController inputConsumerController,
+ PipTaskOrganizer pipTaskOrganizer
) {
mContext = context;
mMediaController = mediaController;
mInputConsumerController = inputConsumerController;
- mPipMenuActivityClass = pipMenuActivityClass;
+ mPipTaskOrganizer = pipTaskOrganizer;
}
- public boolean isMenuActivityVisible() {
- return mToActivityMessenger != null;
+ public boolean isMenuVisible() {
+ return mPipMenuView != null && mMenuState != MENU_STATE_NONE;
}
public void onActivityPinned() {
+ if (mPipMenuView == null) {
+ WindowManager.LayoutParams lp =
+ getPipMenuLayoutParams(0, 0);
+ mPipMenuView = new PipMenuView(mContext, this);
+ mPipTaskOrganizer.attachPipMenuViewHost(mPipMenuView, lp);
+ }
mInputConsumerController.registerInputConsumer(true /* withSfVsync */);
}
public void onActivityUnpinned() {
hideMenu();
mInputConsumerController.unregisterInputConsumer();
- setStartActivityRequested(false);
+ mPipTaskOrganizer.detachPipMenuViewHost();
+ mPipMenuView = null;
}
public void onPinnedStackAnimationEnded() {
- // Note: Only active menu activities care about this event
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_ANIMATION_ENDED;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu pinned animation ended", e);
- }
+ if (isMenuVisible()) {
+ mPipMenuView.onPipAnimationEnded();
}
}
@@ -236,27 +153,13 @@ public class PipMenuActivityController {
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
public void setDismissFraction(float fraction) {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
- Log.d(TAG, "setDismissFraction() hasActivity=" + (mToActivityMessenger != null)
+ Log.d(TAG, "setDismissFraction() isMenuVisible=" + isMenuVisible
+ " fraction=" + fraction);
}
- if (mToActivityMessenger != null) {
- mTmpDismissFractionData.clear();
- mTmpDismissFractionData.putFloat(EXTRA_DISMISS_FRACTION, fraction);
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_UPDATE_DISMISS_FRACTION;
- m.obj = mTmpDismissFractionData;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to update dismiss fraction", e);
- }
- } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
- // If we haven't requested the start activity, or if it previously took too long to
- // start, then start it
- startMenuActivity(MENU_STATE_NONE, null /* stackBounds */,
- false /* allowMenuTimeout */, false /* resizeMenuOnShow */,
- false /* withDelay */, false /* showResizeHandle */);
+ if (isMenuVisible) {
+ mPipMenuView.updateDismissFraction(fraction);
}
}
@@ -282,27 +185,11 @@ public class PipMenuActivityController {
false /* withDelay */, showResizeHandle);
}
- private Runnable getMenuStateChangeFinishedCallback(@Nullable Messenger replyTo,
- @Nullable Bundle data) {
- if (replyTo == null || data == null) {
- return null;
- }
- return () -> {
- try {
- final Message m = Message.obtain();
- m.what = data.getInt(EXTRA_MESSAGE_CALLBACK_WHAT);
- replyTo.send(m);
- } catch (RemoteException e) {
- // ignored
- }
- };
- }
-
private void showMenuInternal(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
if (DEBUG) {
Log.d(TAG, "showMenu() state=" + menuState
- + " hasActivity=" + (mToActivityMessenger != null)
+ + " isMenuVisible=" + isMenuVisible()
+ " allowMenuTimeout=" + allowMenuTimeout
+ " willResizeMenu=" + willResizeMenu
+ " withDelay=" + withDelay
@@ -310,64 +197,34 @@ public class PipMenuActivityController {
+ " callers=\n" + Debug.getCallers(5, " "));
}
- if (mToActivityMessenger != null) {
- Bundle data = new Bundle();
- data.putInt(EXTRA_MENU_STATE, menuState);
- if (stackBounds != null) {
- data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
- }
- data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
- data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
- data.putBoolean(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
- data.putBoolean(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
- m.obj = data;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to show", e);
- }
- } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
- // If we haven't requested the start activity, or if it previously took too long to
- // start, then start it
- startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
- showResizeHandle);
+ if (mPipMenuView == null) {
+ Log.e(TAG, "PipMenu has not been attached yet.");
+ return;
}
+ mPipMenuView.showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
+ showResizeHandle);
}
/**
* Pokes the menu, indicating that the user is interacting with it.
*/
public void pokeMenu() {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
- Log.d(TAG, "pokeMenu() hasActivity=" + (mToActivityMessenger != null));
+ Log.d(TAG, "pokeMenu() isMenuVisible=" + isMenuVisible);
}
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_POKE_MENU;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify poke menu", e);
- }
+ if (isMenuVisible) {
+ mPipMenuView.pokeMenu();
}
}
private void fadeOutMenu() {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
- Log.d(TAG, "fadeOutMenu() state=" + mMenuState
- + " hasActivity=" + (mToActivityMessenger != null)
- + " callers=\n" + Debug.getCallers(5, " "));
+ Log.d(TAG, "fadeOutMenu() isMenuVisible=" + isMenuVisible);
}
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_FADE_OUT_MENU;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to fade out", e);
- }
+ if (isMenuVisible) {
+ mPipMenuView.fadeOutMenu();
}
}
@@ -375,19 +232,14 @@ public class PipMenuActivityController {
* Hides the menu activity.
*/
public void hideMenu() {
+ final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
Log.d(TAG, "hideMenu() state=" + mMenuState
- + " hasActivity=" + (mToActivityMessenger != null)
+ + " isMenuVisible=" + isMenuVisible
+ " callers=\n" + Debug.getCallers(5, " "));
}
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to hide", e);
- }
+ if (isMenuVisible) {
+ mPipMenuView.hideMenu();
}
}
@@ -395,29 +247,11 @@ public class PipMenuActivityController {
* Hides the menu activity.
*/
public void hideMenu(Runnable onStartCallback, Runnable onEndCallback) {
- if (mStartActivityRequested) {
- // If the menu has been start-requested, but not actually started, then we defer the
- // trigger callback until the menu has started and called back to the controller.
- mOnAnimationEndRunnable = onEndCallback;
- onStartCallback.run();
-
- // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
- // callbacks. Don't continue to wait for the menu to show past some timeout.
- mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
- mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
- START_ACTIVITY_REQUEST_TIMEOUT_MS);
- } else if (mMenuState != MENU_STATE_NONE && mToActivityMessenger != null) {
+ if (isMenuVisible()) {
// If the menu is visible in either the closed or full state, then hide the menu and
// trigger the animation trigger afterwards
onStartCallback.run();
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
- m.obj = onEndCallback;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify hide menu", e);
- }
+ mPipMenuView.hideMenu(onEndCallback);
}
}
@@ -438,6 +272,18 @@ public class PipMenuActivityController {
updateMenuActions();
}
+ void onPipExpand() {
+ mListeners.forEach(Listener::onPipExpand);
+ }
+
+ void onPipDismiss() {
+ mListeners.forEach(Listener::onPipDismiss);
+ }
+
+ void onPipShowMenu() {
+ mListeners.forEach(Listener::onPipShowMenu);
+ }
+
/**
* @return the best set of actions to show in the PiP menu.
*/
@@ -449,47 +295,20 @@ public class PipMenuActivityController {
}
/**
- * Starts the menu activity on the top task of the pinned stack.
+ * Returns a default LayoutParams for the PIP Menu.
+ * @param width the PIP stack width.
+ * @param height the PIP stack height.
*/
- private void startMenuActivity(int menuState, Rect stackBounds, boolean allowMenuTimeout,
- boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
- try {
- StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
- if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
- pinnedStackInfo.taskIds.length > 0) {
- Intent intent = new Intent(mContext, mPipMenuActivityClass);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
- intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
- if (stackBounds != null) {
- intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds);
- }
- intent.putExtra(EXTRA_MENU_STATE, menuState);
- intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
- intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
- intent.putExtra(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
- intent.putExtra(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
- ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
- options.setLaunchTaskId(
- pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
- options.setTaskOverlay(true, true /* canResume */);
- mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
- setStartActivityRequested(true);
- } else {
- Log.e(TAG, "No PIP tasks found");
- }
- } catch (RemoteException e) {
- setStartActivityRequested(false);
- Log.e(TAG, "Error showing PIP menu activity", e);
- }
+ public static WindowManager.LayoutParams getPipMenuLayoutParams(int width, int height) {
+ return new WindowManager.LayoutParams(width, height,
+ WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSLUCENT);
}
/**
- * Updates the PiP menu activity with the best set of actions provided.
+ * Updates the PiP menu with the best set of actions provided.
*/
private void updateMenuActions() {
- if (mToActivityMessenger != null) {
+ if (isMenuVisible()) {
// Fetch the pinned stack bounds
Rect stackBounds = null;
try {
@@ -499,20 +318,10 @@ public class PipMenuActivityController {
stackBounds = pinnedStackInfo.bounds;
}
} catch (RemoteException e) {
- Log.e(TAG, "Error showing PIP menu activity", e);
+ Log.e(TAG, "Error showing PIP menu", e);
}
- Bundle data = new Bundle();
- data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
- data.putParcelable(EXTRA_ACTIONS, resolveMenuActions());
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_UPDATE_ACTIONS;
- m.obj = data;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu activity to update actions", e);
- }
+ mPipMenuView.setActions(stackBounds, resolveMenuActions().getList());
}
}
@@ -524,17 +333,9 @@ public class PipMenuActivityController {
}
/**
- * @return whether the time of the activity request has exceeded the timeout.
- */
- private boolean isStartActivityRequestedElapsed() {
- return (SystemClock.uptimeMillis() - mStartActivityRequestedTime)
- >= START_ACTIVITY_REQUEST_TIMEOUT_MS;
- }
-
- /**
* Handles changes in menu visibility.
*/
- private void onMenuStateChanged(int menuState, boolean resize, Runnable callback) {
+ void onMenuStateChanged(int menuState, boolean resize, Runnable callback) {
if (DEBUG) {
Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
+ " menuState=" + menuState + " resize=" + resize
@@ -556,25 +357,14 @@ public class PipMenuActivityController {
mMenuState = menuState;
}
- private void setStartActivityRequested(boolean requested) {
- mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
- mStartActivityRequested = requested;
- mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0;
- }
-
/**
* Handles a pointer event sent from pip input consumer.
*/
void handlePointerEvent(MotionEvent ev) {
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_POINTER_EVENT;
- m.obj = ev;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not dispatch touch event", e);
- }
+ if (ev.isTouchEvent()) {
+ mPipMenuView.dispatchTouchEvent(ev);
+ } else {
+ mPipMenuView.dispatchGenericMotionEvent(ev);
}
}
@@ -582,15 +372,14 @@ public class PipMenuActivityController {
* Tell the PIP Menu to recalculate its layout given its current position on the display.
*/
public void updateMenuLayout(Rect bounds) {
- if (mToActivityMessenger != null) {
- Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_UPDATE_MENU_LAYOUT;
- m.obj = bounds;
- try {
- mToActivityMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not dispatch touch event", e);
- }
+ final boolean isMenuVisible = isMenuVisible();
+ if (DEBUG) {
+ Log.d(TAG, "updateMenuLayout() state=" + mMenuState
+ + " isMenuVisible=" + isMenuVisible
+ + " callers=\n" + Debug.getCallers(5, " "));
+ }
+ if (isMenuVisible) {
+ mPipMenuView.updateMenuLayout(bounds);
}
}
@@ -598,9 +387,7 @@ public class PipMenuActivityController {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
pw.println(innerPrefix + "mMenuState=" + mMenuState);
- pw.println(innerPrefix + "mToActivityMessenger=" + mToActivityMessenger);
+ pw.println(innerPrefix + "mPipMenuView=" + mPipMenuView);
pw.println(innerPrefix + "mListeners=" + mListeners.size());
- pw.println(innerPrefix + "mStartActivityRequested=" + mStartActivityRequested);
- pw.println(innerPrefix + "mStartActivityRequestedTime=" + mStartActivityRequestedTime);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
index 1b1b2de05883..993bfe04f9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.pip.phone;
@@ -23,15 +23,6 @@ import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTR
import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU_WITH_DELAY;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_RESIZE_HANDLE;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
@@ -41,14 +32,12 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
-import android.content.pm.ParceledListSlice;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
@@ -56,10 +45,6 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
@@ -68,7 +53,6 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -76,32 +60,20 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.android.systemui.Interpolators;
-import com.android.wm.shell.R;
+import com.android.systemui.R;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
/**
- * Translucent activity that gets started on top of a task in PIP to allow the user to control it.
- * TODO(b/150319024): PipMenuActivity will move to a Window
+ * Translucent window that gets started on top of a task in PIP to allow the user to control it.
*/
-public class PipMenuActivity extends Activity {
+public class PipMenuView extends FrameLayout {
- private static final String TAG = "PipMenuActivity";
+ private static final String TAG = "PipMenuView";
private static final int MESSAGE_INVALID_TYPE = -1;
-
- public static final int MESSAGE_SHOW_MENU = 1;
- public static final int MESSAGE_POKE_MENU = 2;
- public static final int MESSAGE_HIDE_MENU = 3;
- public static final int MESSAGE_UPDATE_ACTIONS = 4;
- public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
- public static final int MESSAGE_ANIMATION_ENDED = 6;
- public static final int MESSAGE_POINTER_EVENT = 7;
public static final int MESSAGE_MENU_EXPANDED = 8;
- public static final int MESSAGE_FADE_OUT_MENU = 9;
- public static final int MESSAGE_UPDATE_MENU_LAYOUT = 10;
private static final int INITIAL_DISMISS_DELAY = 3500;
private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -130,85 +102,20 @@ public class PipMenuActivity extends Activity {
private int mBetweenActionPaddingLand;
private AnimatorSet mMenuContainerAnimator;
+ private PipMenuActivityController mController;
private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float alpha = (float) animation.getAnimatedValue();
- mBackgroundDrawable.setAlpha((int) (MENU_BACKGROUND_ALPHA*alpha*255));
+ mBackgroundDrawable.setAlpha((int) (MENU_BACKGROUND_ALPHA * alpha * 255));
}
};
- private Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_SHOW_MENU: {
- final Bundle data = (Bundle) msg.obj;
- showMenu(data.getInt(EXTRA_MENU_STATE),
- data.getParcelable(EXTRA_STACK_BOUNDS),
- data.getBoolean(EXTRA_ALLOW_TIMEOUT),
- data.getBoolean(EXTRA_WILL_RESIZE_MENU),
- data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY),
- data.getBoolean(EXTRA_SHOW_RESIZE_HANDLE));
- break;
- }
- case MESSAGE_POKE_MENU:
- cancelDelayedFinish();
- break;
- case MESSAGE_HIDE_MENU:
- hideMenu((Runnable) msg.obj);
- break;
- case MESSAGE_UPDATE_ACTIONS: {
- final Bundle data = (Bundle) msg.obj;
- final ParceledListSlice<RemoteAction> actions = data.getParcelable(
- EXTRA_ACTIONS);
- setActions(data.getParcelable(EXTRA_STACK_BOUNDS), actions != null
- ? actions.getList() : Collections.emptyList());
- break;
- }
- case MESSAGE_UPDATE_DISMISS_FRACTION: {
- final Bundle data = (Bundle) msg.obj;
- updateDismissFraction(data.getFloat(EXTRA_DISMISS_FRACTION));
- break;
- }
- case MESSAGE_ANIMATION_ENDED: {
- mAllowTouches = true;
- break;
- }
- case MESSAGE_POINTER_EVENT: {
- final MotionEvent ev = (MotionEvent) msg.obj;
- dispatchPointerEvent(ev);
- break;
- }
- case MESSAGE_MENU_EXPANDED : {
- if (mMenuContainerAnimator == null) {
- return;
- }
- mMenuContainerAnimator.setStartDelay(MENU_SHOW_ON_EXPAND_START_DELAY);
- mMenuContainerAnimator.start();
- break;
- }
- case MESSAGE_FADE_OUT_MENU: {
- fadeOutMenu();
- break;
- }
- case MESSAGE_UPDATE_MENU_LAYOUT: {
- if (mPipMenuIconsAlgorithm == null) {
- return;
- }
- final Rect bounds = (Rect) msg.obj;
- mPipMenuIconsAlgorithm.onBoundsChanged(bounds);
- break;
- }
- }
- }
- };
- private Messenger mToControllerMessenger;
- private Messenger mMessenger = new Messenger(mHandler);
+ private Handler mHandler = new Handler();
- private final Runnable mFinishRunnable = this::hideMenu;
+ private final Runnable mHideMenuRunnable = this::hideMenu;
protected View mViewRoot;
protected View mSettingsButton;
@@ -217,17 +124,14 @@ public class PipMenuActivity extends Activity {
protected View mTopEndContainer;
protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- // Set the flags to allow us to watch for outside touches and also hide the menu and start
- // manipulating the PIP in the same touch gesture
- getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
-
- super.onCreate(savedInstanceState);
+ public PipMenuView(Context context, PipMenuActivityController controller) {
+ super(context, null, 0);
+ mContext = context;
+ mController = controller;
- setContentView(R.layout.pip_menu_activity);
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+ inflate(context, R.layout.pip_menu, this);
- mAccessibilityManager = getSystemService(AccessibilityManager.class);
mBackgroundDrawable = new ColorDrawable(Color.BLACK);
mBackgroundDrawable.setAlpha(0);
mViewRoot = findViewById(R.id.background);
@@ -250,26 +154,25 @@ public class PipMenuActivity extends Activity {
expandPip();
}
});
+ // TODO (b/161710689): Remove this once focusability for Windowless window is working
+ findViewById(R.id.expand_button).setFocusable(false);
+ mDismissButton.setFocusable(false);
+ mSettingsButton.setFocusable(false);
+
mResizeHandle = findViewById(R.id.resize_handle);
mResizeHandle.setAlpha(0);
mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land);
- mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(this.getApplicationContext());
+ mPipMenuIconsAlgorithm = new PipMenuIconsAlgorithm(mContext);
mPipMenuIconsAlgorithm.bindViews((ViewGroup) mViewRoot, (ViewGroup) mTopEndContainer,
mResizeHandle, mSettingsButton, mDismissButton);
- updateFromIntent(getIntent());
- setTitle(R.string.pip_menu_title);
- setDisablePreviewScreenshots(true);
-
- // Hide without an animation.
- getWindow().setExitTransition(null);
initAccessibility();
}
private void initAccessibility() {
- getWindow().getDecorView().setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ this.setAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
@@ -280,9 +183,7 @@ public class PipMenuActivity extends Activity {
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
if (action == ACTION_CLICK && mMenuState == MENU_STATE_CLOSE) {
- Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_SHOW_MENU;
- sendMessage(m, "Could not notify controller to show PIP menu");
+ mController.onPipShowMenu();
}
return super.performAccessibilityAction(host, action, args);
}
@@ -299,108 +200,37 @@ public class PipMenuActivity extends Activity {
}
@Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- updateFromIntent(intent);
- }
-
- @Override
- public void onUserInteraction() {
- if (mAllowMenuTimeout) {
- repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
- }
- }
-
- @Override
- protected void onUserLeaveHint() {
- super.onUserLeaveHint();
-
- // If another task is starting on top of the menu, then hide and finish it so that it can be
- // recreated on the top next time it starts
- hideMenu();
- }
-
- @Override
- public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
- super.onTopResumedActivityChanged(isTopResumedActivity);
- if (!isTopResumedActivity && mMenuState != MENU_STATE_NONE) {
- hideMenu();
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- // In cases such as device lock, hide and finish it so that it can be recreated on the top
- // next time it starts, see also {@link #onUserLeaveHint}
- hideMenu();
- cancelDelayedFinish();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- // Fallback, if we are destroyed for any other reason (like when the task is being reset),
- // also reset the callback.
- notifyActivityCallback(null);
- }
-
- @Override
- public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
- if (!isInPictureInPictureMode) {
- finish();
- }
- }
-
- /**
- * Dispatch a pointer event from {@link PipTouchHandler}.
- */
- private void dispatchPointerEvent(MotionEvent event) {
- if (event.isTouchEvent()) {
- dispatchTouchEvent(event);
- } else {
- dispatchGenericMotionEvent(event);
- }
- }
-
- @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!mAllowTouches) {
return false;
}
- // On the first action outside the window, hide the menu
- switch (ev.getAction()) {
- case MotionEvent.ACTION_OUTSIDE:
- hideMenu();
- return true;
+ if (mAllowMenuTimeout) {
+ repostDelayedHide(POST_INTERACTION_DISMISS_DELAY);
}
+
return super.dispatchTouchEvent(ev);
}
@Override
- public void finish() {
- notifyActivityCallback(null);
- super.finish();
- }
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
+ if (mAllowMenuTimeout) {
+ repostDelayedHide(POST_INTERACTION_DISMISS_DELAY);
+ }
- @Override
- public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
- // Do nothing
+ return super.dispatchGenericMotionEvent(event);
}
- private void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
+ void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
mAllowMenuTimeout = allowMenuTimeout;
if (mMenuState != menuState) {
// Disallow touches if the menu needs to resize while showing, and we are transitioning
// to/from a full menu state.
- boolean disallowTouchesUntilAnimationEnd = resizeMenuOnShow &&
- (mMenuState == MENU_STATE_FULL || menuState == MENU_STATE_FULL);
+ boolean disallowTouchesUntilAnimationEnd = resizeMenuOnShow
+ && (mMenuState == MENU_STATE_FULL || menuState == MENU_STATE_FULL);
mAllowTouches = !disallowTouchesUntilAnimationEnd;
- cancelDelayedFinish();
+ cancelDelayedHide();
updateActionViews(stackBounds);
if (mMenuContainerAnimator != null) {
mMenuContainerAnimator.cancel();
@@ -431,22 +261,28 @@ public class PipMenuActivity extends Activity {
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- repostDelayedFinish(INITIAL_DISMISS_DELAY);
+ repostDelayedHide(INITIAL_DISMISS_DELAY);
}
});
}
if (withDelay) {
// starts the menu container animation after window expansion is completed
- notifyMenuStateChange(menuState, resizeMenuOnShow, MESSAGE_MENU_EXPANDED);
+ notifyMenuStateChange(menuState, resizeMenuOnShow, () -> {
+ if (mMenuContainerAnimator == null) {
+ return;
+ }
+ mMenuContainerAnimator.setStartDelay(MENU_SHOW_ON_EXPAND_START_DELAY);
+ mMenuContainerAnimator.start();
+ });
} else {
- notifyMenuStateChange(menuState, resizeMenuOnShow, MESSAGE_INVALID_TYPE);
+ notifyMenuStateChange(menuState, resizeMenuOnShow, null);
mMenuContainerAnimator.start();
}
} else {
// If we are already visible, then just start the delayed dismiss and unregister any
// existing input consumers from the previous drag
if (allowMenuTimeout) {
- repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+ repostDelayedHide(POST_INTERACTION_DISMISS_DELAY);
}
}
}
@@ -456,28 +292,39 @@ public class PipMenuActivity extends Activity {
* and instead, it fades out the controls by setting the alpha to 0 directly without menu
* visibility callbacks invoked.
*/
- private void fadeOutMenu() {
+ void fadeOutMenu() {
mMenuContainer.setAlpha(0f);
mSettingsButton.setAlpha(0f);
mDismissButton.setAlpha(0f);
mResizeHandle.setAlpha(0f);
}
- private void hideMenu() {
+ void pokeMenu() {
+ cancelDelayedHide();
+ }
+
+ void onPipAnimationEnded() {
+ mAllowTouches = true;
+ }
+
+ void updateMenuLayout(Rect bounds) {
+ mPipMenuIconsAlgorithm.onBoundsChanged(bounds);
+ }
+
+ void hideMenu() {
hideMenu(null);
}
- private void hideMenu(Runnable animationEndCallback) {
- hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false /* isDismissing */,
- true /* animate */);
+ void hideMenu(Runnable animationEndCallback) {
+ hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false);
}
private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
- boolean isDismissing, boolean animate) {
+ boolean animate) {
if (mMenuState != MENU_STATE_NONE) {
- cancelDelayedFinish();
+ cancelDelayedHide();
if (notifyMenuVisibility) {
- notifyMenuStateChange(MENU_STATE_NONE, mResize, MESSAGE_INVALID_TYPE);
+ notifyMenuStateChange(MENU_STATE_NONE, mResize, null);
}
mMenuContainerAnimator = new AnimatorSet();
ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
@@ -498,49 +345,13 @@ public class PipMenuActivity extends Activity {
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
-
- if (!isDismissing) {
- // If we are dismissing the PiP, then don't try to pre-emptively finish the
- // menu activity
- finish();
- }
}
});
mMenuContainerAnimator.start();
- } else {
- // If the menu is not visible, just finish now
- finish();
}
}
- private void updateFromIntent(Intent intent) {
- mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
- if (mToControllerMessenger == null) {
- Log.w(TAG, "Controller messenger is null. Stopping.");
- finish();
- return;
- }
- notifyActivityCallback(mMessenger);
-
- ParceledListSlice<RemoteAction> actions = intent.getParcelableExtra(EXTRA_ACTIONS);
- if (actions != null) {
- mActions.clear();
- mActions.addAll(actions.getList());
- }
-
- final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE);
- if (menuState != MENU_STATE_NONE) {
- Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS);
- boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true);
- boolean willResizeMenu = intent.getBooleanExtra(EXTRA_WILL_RESIZE_MENU, false);
- boolean withDelay = intent.getBooleanExtra(EXTRA_SHOW_MENU_WITH_DELAY, false);
- boolean showResizeHandle = intent.getBooleanExtra(EXTRA_SHOW_RESIZE_HANDLE, false);
- showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
- showResizeHandle);
- }
- }
-
- private void setActions(Rect stackBounds, List<RemoteAction> actions) {
+ void setActions(Rect stackBounds, List<RemoteAction> actions) {
mActions.clear();
mActions.addAll(actions);
updateActionViews(stackBounds);
@@ -560,7 +371,7 @@ public class PipMenuActivity extends Activity {
actionsContainer.setVisibility(View.VISIBLE);
if (mActionsGroup != null) {
// Ensure we have as many buttons as actions
- final LayoutInflater inflater = LayoutInflater.from(this);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
while (mActionsGroup.getChildCount() < mActions.size()) {
final ImageButton actionView = (ImageButton) inflater.inflate(
R.layout.pip_menu_action, mActionsGroup, false);
@@ -575,14 +386,14 @@ public class PipMenuActivity extends Activity {
}
// Recreate the layout
- final boolean isLandscapePip = stackBounds != null &&
- (stackBounds.width() > stackBounds.height());
+ final boolean isLandscapePip = stackBounds != null
+ && (stackBounds.width() > stackBounds.height());
for (int i = 0; i < mActions.size(); i++) {
final RemoteAction action = mActions.get(i);
final ImageButton actionView = (ImageButton) mActionsGroup.getChildAt(i);
// TODO: Check if the action drawable has changed before we reload it
- action.getIcon().loadDrawableAsync(this, d -> {
+ action.getIcon().loadDrawableAsync(mContext, d -> {
d.setTint(Color.WHITE);
actionView.setImageDrawable(d);
}, mHandler);
@@ -620,7 +431,7 @@ public class PipMenuActivity extends Activity {
}
}
- private void updateDismissFraction(float fraction) {
+ void updateDismissFraction(float fraction) {
int alpha;
final float menuAlpha = 1 - fraction;
if (mMenuState == MENU_STATE_FULL) {
@@ -639,31 +450,15 @@ public class PipMenuActivity extends Activity {
mBackgroundDrawable.setAlpha(alpha);
}
- private void notifyMenuStateChange(int menuState, boolean resize, int callbackWhat) {
+ private void notifyMenuStateChange(int menuState, boolean resize, Runnable callback) {
mMenuState = menuState;
- mResize = resize;
- Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_MENU_STATE_CHANGED;
- m.arg1 = menuState;
- m.arg2 = resize ? 1 : 0;
- if (callbackWhat != MESSAGE_INVALID_TYPE) {
- // This message could be sent across processes when in secondary user.
- // Make the receiver end sending back via our own Messenger
- m.replyTo = mMessenger;
- final Bundle data = new Bundle(1);
- data.putInt(PipMenuActivityController.EXTRA_MESSAGE_CALLBACK_WHAT, callbackWhat);
- m.obj = data;
- }
- sendMessage(m, "Could not notify controller of PIP menu visibility");
+ mController.onMenuStateChanged(menuState, resize, callback);
}
private void expandPip() {
// Do not notify menu visibility when hiding the menu, the controller will do this when it
// handles the message
- hideMenu(() -> {
- sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
- "Could not notify controller to expand PIP");
- }, false /* notifyMenuVisibility */, false /* isDismissing */, true /* animate */);
+ hideMenu(mController::onPipExpand, false /* notifyMenuVisibility */, true /* animate */);
}
private void dismissPip() {
@@ -673,58 +468,30 @@ public class PipMenuActivity extends Activity {
final boolean animate = mMenuState != MENU_STATE_CLOSE;
// Do not notify menu visibility when hiding the menu, the controller will do this when it
// handles the message
- hideMenu(() -> {
- sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
- "Could not notify controller to dismiss PIP");
- }, false /* notifyMenuVisibility */, true /* isDismissing */, animate);
+ hideMenu(mController::onPipDismiss, false /* notifyMenuVisibility */, animate);
}
private void showSettings() {
final Pair<ComponentName, Integer> topPipActivityInfo =
- PipUtils.getTopPipActivity(this, ActivityManager.getService());
+ PipUtils.getTopPipActivity(mContext, ActivityManager.getService());
if (topPipActivityInfo.first != null) {
final UserHandle user = UserHandle.of(topPipActivityInfo.second);
final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS,
Uri.fromParts("package", topPipActivityInfo.first.getPackageName(), null));
settingsIntent.putExtra(Intent.EXTRA_USER_HANDLE, user);
settingsIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(settingsIntent);
- }
- }
-
- private void notifyActivityCallback(Messenger callback) {
- Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK;
- m.replyTo = callback;
- m.arg1 = mResize ? 1 : 0;
- sendMessage(m, "Could not notify controller of activity finished");
- }
-
- private void sendEmptyMessage(int what, String errorMsg) {
- Message m = Message.obtain();
- m.what = what;
- sendMessage(m, errorMsg);
- }
-
- private void sendMessage(Message m, String errorMsg) {
- if (mToControllerMessenger == null) {
- return;
- }
- try {
- mToControllerMessenger.send(m);
- } catch (RemoteException e) {
- Log.e(TAG, errorMsg, e);
+ mContext.startActivity(settingsIntent);
}
}
- private void cancelDelayedFinish() {
- mHandler.removeCallbacks(mFinishRunnable);
+ private void cancelDelayedHide() {
+ mHandler.removeCallbacks(mHideMenuRunnable);
}
- private void repostDelayedFinish(int delay) {
+ private void repostDelayedHide(int delay) {
int recommendedTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(delay,
FLAG_CONTENT_ICONS | FLAG_CONTENT_CONTROLS);
- mHandler.removeCallbacks(mFinishRunnable);
- mHandler.postDelayed(mFinishRunnable, recommendedTimeout);
+ mHandler.removeCallbacks(mHideMenuRunnable);
+ mHandler.postDelayed(mHideMenuRunnable, recommendedTimeout);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 19138fdba788..dcee2a5b4b20 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -23,6 +23,8 @@ import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import android.view.Choreographer;
@@ -66,6 +68,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private PipMenuActivityController mMenuController;
private PipSnapAlgorithm mSnapAlgorithm;
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+
/** PIP's current bounds on the screen. */
private final Rect mBounds = new Rect();
@@ -128,8 +132,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> {
- mMenuController.updateMenuLayout(newBounds);
- mBounds.set(newBounds);
+ mMainHandler.post(() -> {
+ mMenuController.updateMenuLayout(newBounds);
+ mBounds.set(newBounds);
+ });
};
/**
@@ -253,7 +259,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mTemporaryBounds.set(toBounds);
mPipTaskOrganizer.scheduleUserResizePip(mBounds, mTemporaryBounds,
(Rect newBounds) -> {
- mMenuController.updateMenuLayout(newBounds);
+ mMainHandler.post(() -> {
+ mMenuController.updateMenuLayout(newBounds);
+ });
});
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index 2800bb938149..f6853ecf8ee7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -111,6 +111,7 @@ public class PipResizeGestureHandler {
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
private PipTaskOrganizer mPipTaskOrganizer;
+ private PipMenuActivityController mPipMenuActivityController;
private PipUiEventLogger mPipUiEventLogger;
private int mCtrlType;
@@ -119,7 +120,7 @@ public class PipResizeGestureHandler {
PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig,
PipTaskOrganizer pipTaskOrganizer, Function<Rect, Rect> movementBoundsSupplier,
Runnable updateMovementBoundsRunnable, SysUiState sysUiState,
- PipUiEventLogger pipUiEventLogger) {
+ PipUiEventLogger pipUiEventLogger, PipMenuActivityController menuActivityController) {
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
@@ -129,6 +130,7 @@ public class PipResizeGestureHandler {
mMovementBoundsSupplier = movementBoundsSupplier;
mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
mSysUiState = sysUiState;
+ mPipMenuActivityController = menuActivityController;
mPipUiEventLogger = pipUiEventLogger;
context.getDisplay().getRealSize(mMaxSize);
@@ -298,6 +300,7 @@ public class PipResizeGestureHandler {
float x = ev.getX();
float y = ev.getY();
if (action == MotionEvent.ACTION_DOWN) {
+ final Rect currentPipBounds = mMotionHelper.getBounds();
mLastResizeBounds.setEmpty();
mAllowGesture = isInValidSysUiState() && isWithinTouchRegion((int) x, (int) y);
if (mAllowGesture) {
@@ -305,6 +308,10 @@ public class PipResizeGestureHandler {
mDownPoint.set(x, y);
mLastDownBounds.set(mMotionHelper.getBounds());
}
+ if (!currentPipBounds.contains((int) ev.getX(), (int) ev.getY())
+ && mPipMenuActivityController.isMenuVisible()) {
+ mPipMenuActivityController.hideMenu();
+ }
} else if (mAllowGesture) {
switch (action) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 1b84c1417c51..9693f235a4ff 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -230,7 +230,7 @@ public class PipTouchHandler {
mPipResizeGestureHandler =
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
deviceConfig, pipTaskOrganizer, this::getMovementBounds,
- this::updateMovementBounds, sysUiState, pipUiEventLogger);
+ this::updateMovementBounds, sysUiState, pipUiEventLogger, menuController);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()),
@@ -773,10 +773,7 @@ public class PipTouchHandler {
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
private void updateDismissFraction() {
- // Skip updating the dismiss fraction when the IME is showing. This is to work around an
- // issue where starting the menu activity for the dismiss overlay will steal the window
- // focus, which closes the IME.
- if (mMenuController != null && !mIsImeShowing) {
+ if (mMenuController != null) {
Rect bounds = mMotionHelper.getBounds();
final float target = mInsetBounds.bottom;
float fraction = 0f;
@@ -784,7 +781,7 @@ public class PipTouchHandler {
final float distance = bounds.bottom - target;
fraction = Math.min(distance / bounds.height(), 1f);
}
- if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuActivityVisible()) {
+ if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuVisible()) {
// Update if the fraction > 0, or if fraction == 0 and the menu was already visible
mMenuController.setDismissFraction(fraction);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java b/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java
deleted file mode 100644
index 114c30e625aa..000000000000
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/dagger/PipMenuActivityClass.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.pip.phone.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface PipMenuActivityClass {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 7b4547689c8b..6a2ca44bfc17 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -22,8 +22,6 @@ import android.view.IWindowManager;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.pip.phone.PipMenuActivity;
-import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.stackdivider.SplitScreenController;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -50,14 +48,6 @@ public class WMShellModule {
return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
}
- /** TODO(b/150319024): PipMenuActivity will move to a Window */
- @SysUISingleton
- @PipMenuActivityClass
- @Provides
- static Class<?> providePipMenuActivityClass() {
- return PipMenuActivity.class;
- }
-
@SysUISingleton
@Provides
static SplitScreen provideSplitScreen(Context context,