summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/res/drawable/pip_custom_close_bg.xml24
-rw-r--r--libs/WindowManager/Shell/res/layout/pip_menu_action.xml8
-rw-r--r--libs/WindowManager/Shell/res/values/colors.xml5
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml4
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java60
9 files changed, 108 insertions, 16 deletions
diff --git a/libs/WindowManager/Shell/res/drawable/pip_custom_close_bg.xml b/libs/WindowManager/Shell/res/drawable/pip_custom_close_bg.xml
new file mode 100644
index 000000000000..39c3fe6f6106
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/pip_custom_close_bg.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid
+ android:color="@color/pip_custom_close_bg" />
+ <size
+ android:width="@dimen/pip_custom_close_bg_size"
+ android:height="@dimen/pip_custom_close_bg_size" />
+</shape>
diff --git a/libs/WindowManager/Shell/res/layout/pip_menu_action.xml b/libs/WindowManager/Shell/res/layout/pip_menu_action.xml
index a733b31d9fb0..b51dd6a00815 100644
--- a/libs/WindowManager/Shell/res/layout/pip_menu_action.xml
+++ b/libs/WindowManager/Shell/res/layout/pip_menu_action.xml
@@ -22,6 +22,14 @@
android:forceHasOverlappingRendering="false">
<ImageView
+ android:id="@+id/custom_close_bg"
+ android:layout_width="@dimen/pip_custom_close_bg_size"
+ android:layout_height="@dimen/pip_custom_close_bg_size"
+ android:layout_gravity="center"
+ android:src="@drawable/pip_custom_close_bg"
+ android:visibility="gone"/>
+
+ <ImageView
android:id="@+id/image"
android:layout_width="@dimen/pip_action_inner_size"
android:layout_height="@dimen/pip_action_inner_size"
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 4606d24d1716..6e750a3d5e34 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -30,6 +30,9 @@
<color name="bubbles_dark">@color/GM2_grey_800</color>
<color name="bubbles_icon_tint">@color/GM2_grey_700</color>
+ <!-- PiP -->
+ <color name="pip_custom_close_bg">#D93025</color>
+
<!-- Compat controls UI -->
<color name="compat_controls_background">@android:color/system_neutral1_800</color>
<color name="compat_controls_text">@android:color/system_neutral1_50</color>
@@ -47,4 +50,4 @@
<color name="splash_screen_bg_light">#FFFFFF</color>
<color name="splash_screen_bg_dark">#000000</color>
<color name="splash_window_background_default">@color/splash_screen_bg_light</color>
-</resources> \ No newline at end of file
+</resources>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index d416c060c86c..8ba41ab60c87 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -46,6 +46,10 @@
<!-- Show PiP enter split icon, which allows apps to directly enter splitscreen from PiP. -->
<bool name="config_pipEnableEnterSplitButton">false</bool>
+ <!-- Time (duration in milliseconds) that the shell waits for an app to close the PiP by itself
+ if a custom action is present before closing it. -->
+ <integer name="config_pipForceCloseDelay">1000</integer>
+
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index a2f9e884b37d..c21381d1486a 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -78,6 +78,9 @@
WindowConfiguration#PINNED_WINDOWING_MODE_ELEVATION_IN_DIP -->
<dimen name="pip_shadow_radius">5dp</dimen>
+ <!-- The width and height of the background for custom action in PiP menu. -->
+ <dimen name="pip_custom_close_bg_size">32dp</dimen>
+
<dimen name="dismiss_target_x_size">24dp</dimen>
<dimen name="floating_dismiss_bottom_margin">50dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
index 9c23a32a7d2b..513ebba59258 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
@@ -110,7 +110,10 @@ public class PipUiEventLogger {
PICTURE_IN_PICTURE_STASH_RIGHT(711),
@UiEvent(doc = "User taps on the settings button in PiP menu")
- PICTURE_IN_PICTURE_SHOW_SETTINGS(933);
+ PICTURE_IN_PICTURE_SHOW_SETTINGS(933),
+
+ @UiEvent(doc = "Closes PiP with app-provided close action")
+ PICTURE_IN_PICTURE_CUSTOM_CLOSE(1058);
private final int mId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index f73b81e9d3f3..8ce8f7382ff3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -121,6 +121,7 @@ public class PhonePipMenuController implements PipMenuController {
private final Optional<SplitScreenController> mSplitScreenController;
private final PipUiEventLogger mPipUiEventLogger;
private ParceledListSlice<RemoteAction> mAppActions;
+ private RemoteAction mCloseAction;
private ParceledListSlice<RemoteAction> mMediaActions;
private SyncRtSurfaceTransactionApplier mApplier;
private int mMenuState;
@@ -459,6 +460,7 @@ public class PhonePipMenuController implements PipMenuController {
public void setAppActions(ParceledListSlice<RemoteAction> appActions,
RemoteAction closeAction) {
mAppActions = appActions;
+ mCloseAction = closeAction;
updateMenuActions();
}
@@ -490,9 +492,8 @@ public class PhonePipMenuController implements PipMenuController {
private void updateMenuActions() {
if (mPipMenuView != null) {
final ParceledListSlice<RemoteAction> menuActions = resolveMenuActions();
- if (menuActions != null) {
- mPipMenuView.setActions(mPipBoundsState.getBounds(), menuActions.getList());
- }
+ mPipMenuView.setActions(mPipBoundsState.getBounds(),
+ menuActions == null ? null : menuActions.getList(), mCloseAction);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java
index f11ae422e837..7f84500e8406 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActionView.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.pip.phone;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -30,6 +31,7 @@ import com.android.wm.shell.R;
*/
public class PipMenuActionView extends FrameLayout {
private ImageView mImageView;
+ private View mCustomCloseBackground;
public PipMenuActionView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -39,10 +41,16 @@ public class PipMenuActionView extends FrameLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mImageView = findViewById(R.id.image);
+ mCustomCloseBackground = findViewById(R.id.custom_close_bg);
}
/** pass through to internal {@link #mImageView} */
public void setImageDrawable(Drawable drawable) {
mImageView.setImageDrawable(drawable);
}
+
+ /** pass through to internal {@link #mCustomCloseBackground} */
+ public void setCustomCloseBackgroundVisibility(@View.Visibility int visibility) {
+ mCustomCloseBackground.setVisibility(visibility);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index c0fa8c0a8898..6390c8984dac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -33,8 +33,10 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.PendingIntent.CanceledException;
+import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -72,6 +74,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
/**
@@ -113,6 +116,7 @@ public class PipMenuView extends FrameLayout {
private boolean mFocusedTaskAllowSplitScreen;
private final List<RemoteAction> mActions = new ArrayList<>();
+ private RemoteAction mCloseAction;
private AccessibilityManager mAccessibilityManager;
private Drawable mBackgroundDrawable;
@@ -151,6 +155,9 @@ public class PipMenuView extends FrameLayout {
protected View mTopEndContainer;
protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
+ // How long the shell will wait for the app to close the PiP if a custom action is set.
+ private final int mPipForceCloseDelay;
+
public PipMenuView(Context context, PhonePipMenuController controller,
ShellExecutor mainExecutor, Handler mainHandler,
Optional<SplitScreenController> splitScreenController,
@@ -166,6 +173,9 @@ public class PipMenuView extends FrameLayout {
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
inflate(context, R.layout.pip_menu, this);
+ mPipForceCloseDelay = context.getResources().getInteger(
+ R.integer.config_pipForceCloseDelay);
+
mBackgroundDrawable = mContext.getDrawable(R.drawable.pip_menu_background);
mBackgroundDrawable.setAlpha(0);
mViewRoot = findViewById(R.id.background);
@@ -437,9 +447,13 @@ public class PipMenuView extends FrameLayout {
return new Size(width, height);
}
- void setActions(Rect stackBounds, List<RemoteAction> actions) {
+ void setActions(Rect stackBounds, @Nullable List<RemoteAction> actions,
+ @Nullable RemoteAction closeAction) {
mActions.clear();
- mActions.addAll(actions);
+ if (actions != null && !actions.isEmpty()) {
+ mActions.addAll(actions);
+ }
+ mCloseAction = closeAction;
if (mMenuState == MENU_STATE_FULL) {
updateActionViews(mMenuState, stackBounds);
}
@@ -492,6 +506,8 @@ public class PipMenuView extends FrameLayout {
final RemoteAction action = mActions.get(i);
final PipMenuActionView actionView =
(PipMenuActionView) mActionsGroup.getChildAt(i);
+ final boolean isCloseAction = mCloseAction != null && Objects.equals(
+ mCloseAction.getActionIntent(), action.getActionIntent());
// TODO: Check if the action drawable has changed before we reload it
action.getIcon().loadDrawableAsync(mContext, d -> {
@@ -500,16 +516,12 @@ public class PipMenuView extends FrameLayout {
actionView.setImageDrawable(d);
}
}, mMainHandler);
+ actionView.setCustomCloseBackgroundVisibility(
+ isCloseAction ? View.VISIBLE : View.GONE);
actionView.setContentDescription(action.getContentDescription());
if (action.isEnabled()) {
- actionView.setOnClickListener(v -> {
- try {
- action.getActionIntent().send();
- } catch (CanceledException e) {
- ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: Failed to send action, %s", TAG, e);
- }
- });
+ actionView.setOnClickListener(
+ v -> onActionViewClicked(action.getActionIntent(), isCloseAction));
}
actionView.setEnabled(action.isEnabled());
actionView.setAlpha(action.isEnabled() ? 1f : DISABLED_ACTION_ALPHA);
@@ -559,6 +571,32 @@ public class PipMenuView extends FrameLayout {
}
}
+ /**
+ * Execute the {@link PendingIntent} attached to the {@link PipMenuActionView}.
+ * If the given {@link PendingIntent} matches {@link #mCloseAction}, we need to make sure
+ * the PiP is removed after a certain timeout in case the app does not respond in a
+ * timely manner.
+ */
+ private void onActionViewClicked(@NonNull PendingIntent intent, boolean isCloseAction) {
+ try {
+ intent.send();
+ } catch (PendingIntent.CanceledException e) {
+ ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: Failed to send action, %s", TAG, e);
+ }
+ if (isCloseAction) {
+ mPipUiEventLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_CUSTOM_CLOSE);
+ mAllowTouches = false;
+ mMainExecutor.executeDelayed(() -> {
+ hideMenu();
+ // TODO: it's unsafe to call onPipDismiss with a delay here since
+ // we may have a different PiP by the time this runnable is executed.
+ mController.onPipDismiss();
+ mAllowTouches = true;
+ }, mPipForceCloseDelay);
+ }
+ }
+
private void enterSplit() {
// Do not notify menu visibility when hiding the menu, the controller will do this when it
// handles the message