diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java index ffa6c9921d97e..5f59f5135179a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java @@ -21,9 +21,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.Intent.ACTION_MEDIA_RESOURCE_GRANTED; -import static com.android.wm.shell.pip.tv.PipNotification.ACTION_CLOSE; -import static com.android.wm.shell.pip.tv.PipNotification.ACTION_MENU; - import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.ActivityTaskManager.RootTaskInfo; @@ -61,7 +58,7 @@ import java.util.Objects; * Manages the picture-in-picture (PIP) UI and states. */ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallback, - TvPipMenuController.Delegate { + TvPipMenuController.Delegate, TvPipNotificationController.Delegate { private static final String TAG = "TvPipController"; static final boolean DEBUG = false; @@ -91,7 +88,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac private final PipTaskOrganizer mPipTaskOrganizer; private final PipMediaController mPipMediaController; private final TvPipMenuController mTvPipMenuController; - private final PipNotification mPipNotification; + private final TvPipNotificationController mPipNotificationController; private IActivityTaskManager mActivityTaskManager; private int mState = STATE_NO_PIP; @@ -120,12 +117,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac Log.d(TAG, "mBroadcastReceiver, action: " + intent.getAction()); } switch (intent.getAction()) { - case ACTION_MENU: - showPictureInPictureMenu(); - break; - case ACTION_CLOSE: - closePip(); - break; case ACTION_MEDIA_RESOURCE_GRANTED: String[] packageNames = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); int resourceType = intent.getIntExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE, @@ -190,12 +181,13 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac PipTaskOrganizer pipTaskOrganizer, TvPipMenuController tvPipMenuController, PipMediaController pipMediaController, - PipNotification pipNotification, + TvPipNotificationController tvPipNotificationController, TaskStackListenerImpl taskStackListener, WindowManagerShellWrapper windowManagerShellWrapper) { mContext = context; mPipBoundsState = pipBoundsState; - mPipNotification = pipNotification; + mPipNotificationController = tvPipNotificationController; + mPipNotificationController.setDelegate(this); mPipBoundsAlgorithm = pipBoundsAlgorithm; mPipMediaController = pipMediaController; mTvPipMenuController = tvPipMenuController; @@ -213,8 +205,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mActivityTaskManager = ActivityTaskManager.getService(); final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(ACTION_CLOSE); - intentFilter.addAction(ACTION_MENU); intentFilter.addAction(ACTION_MEDIA_RESOURCE_GRANTED); mContext.registerReceiver(mBroadcastReceiver, intentFilter, UserHandle.USER_ALL); @@ -273,7 +263,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac @Override public void onConfigurationChanged(Configuration newConfig) { loadConfigurationsAndApply(newConfig); - mPipNotification.onConfigurationChanged(mContext); + mPipNotificationController.onConfigurationChanged(mContext); } /** @@ -315,7 +305,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mPinnedStackId = INVALID_STACK_ID; } } - mPipNotification.dismiss(); + mPipNotificationController.dismiss(); mTvPipMenuController.hideMenu(); mHandler.removeCallbacks(mClosePipRunnable); } @@ -334,7 +324,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mPipTaskId = TASK_ID_NO_PIP; mTvPipMenuController.hideMenu(); - mPipNotification.dismiss(); + mPipNotificationController.dismiss(); resizePinnedStack(STATE_NO_PIP); } @@ -359,7 +349,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(); - mPipNotification.show(packageName); + mPipNotificationController.show(packageName); } private void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java similarity index 63% rename from libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java rename to libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java index 5716c7fc71624..a2675431fdddc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java @@ -19,14 +19,17 @@ package com.android.wm.shell.pip.tv; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.res.Resources; import android.graphics.Bitmap; import android.media.MediaMetadata; +import android.os.UserHandle; import android.text.TextUtils; +import android.util.Log; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.wm.shell.R; @@ -39,22 +42,27 @@ import java.util.Objects; *
Once it's created, it will manage the PIP notification UI by itself except for handling
* configuration changes.
*/
-public class PipNotification {
+public class TvPipNotificationController {
+ private static final String TAG = "TvPipNotification";
private static final boolean DEBUG = PipController.DEBUG;
- private static final String TAG = "PipNotification";
- private static final String NOTIFICATION_TAG = PipNotification.class.getSimpleName();
- public static final String NOTIFICATION_CHANNEL_TVPIP = "TPP";
+ // Referenced in com.android.systemui.util.NotificationChannels.
+ public static final String NOTIFICATION_CHANNEL = "TVPIP";
+ private static final String NOTIFICATION_TAG = "TvPip";
- static final String ACTION_MENU = "PipNotification.menu";
- static final String ACTION_CLOSE = "PipNotification.close";
+ private static final String ACTION_SHOW_PIP_MENU =
+ "com.android.wm.shell.pip.tv.notification.action.SHOW_PIP_MENU";
+ private static final String ACTION_CLOSE_PIP =
+ "com.android.wm.shell.pip.tv.notification.action.CLOSE_PIP";
+ private final Context mContext;
private final PackageManager mPackageManager;
private final NotificationManager mNotificationManager;
private final Notification.Builder mNotificationBuilder;
+ private final ActionBroadcastReceiver mActionBroadcastReceiver;
+ private Delegate mDelegate;
private String mDefaultTitle;
- private int mDefaultIconResId;
/** Package name for the application that owns PiP window. */
private String mPackageName;
@@ -62,32 +70,56 @@ public class PipNotification {
private String mMediaTitle;
private Bitmap mArt;
- public PipNotification(Context context, PipMediaController pipMediaController) {
+ public TvPipNotificationController(Context context, PipMediaController pipMediaController) {
+ mContext = context;
mPackageManager = context.getPackageManager();
mNotificationManager = context.getSystemService(NotificationManager.class);
- mNotificationBuilder = new Notification.Builder(context, NOTIFICATION_CHANNEL_TVPIP)
+ mNotificationBuilder = new Notification.Builder(context, NOTIFICATION_CHANNEL)
.setLocalOnly(true)
.setOngoing(false)
.setCategory(Notification.CATEGORY_SYSTEM)
+ .setShowWhen(true)
+ .setSmallIcon(R.drawable.pip_icon)
.extend(new Notification.TvExtender()
- .setContentIntent(createPendingIntent(context, ACTION_MENU))
- .setDeleteIntent(createPendingIntent(context, ACTION_CLOSE)));
+ .setContentIntent(createPendingIntent(context, ACTION_SHOW_PIP_MENU))
+ .setDeleteIntent(createPendingIntent(context, ACTION_CLOSE_PIP)));
+
+ mActionBroadcastReceiver = new ActionBroadcastReceiver();
pipMediaController.addMetadataListener(this::onMediaMetadataChanged);
onConfigurationChanged(context);
}
+ void setDelegate(Delegate delegate) {
+ if (DEBUG) Log.d(TAG, "setDelegate(), delegate=" + delegate);
+ if (mDelegate != null) {
+ throw new IllegalStateException(
+ "The delegate has already been set and should not change.");
+ }
+ if (delegate == null) {
+ throw new IllegalArgumentException("The delegate must not be null.");
+ }
+
+ mDelegate = delegate;
+ }
+
void show(String packageName) {
+ if (mDelegate == null) {
+ throw new IllegalStateException("Delegate is not set.");
+ }
+
mPackageName = packageName;
update();
+ mActionBroadcastReceiver.register();
}
void dismiss() {
mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
mNotified = false;
mPackageName = null;
+ mActionBroadcastReceiver.unregister();
}
private void onMediaMetadataChanged(MediaMetadata metadata) {
@@ -101,11 +133,9 @@ public class PipNotification {
* Called by {@link PipController} when the configuration is changed.
*/
void onConfigurationChanged(Context context) {
- Resources res = context.getResources();
- mDefaultTitle = res.getString(R.string.pip_notification_unknown_title);
- mDefaultIconResId = R.drawable.pip_icon;
+ mDefaultTitle = context.getResources().getString(R.string.pip_notification_unknown_title);
if (mNotified) {
- // update notification
+ // Update the notification.
update();
}
}
@@ -113,9 +143,7 @@ public class PipNotification {
private void update() {
mNotified = true;
mNotificationBuilder
- .setShowWhen(true)
.setWhen(System.currentTimeMillis())
- .setSmallIcon(mDefaultIconResId)
.setContentTitle(getNotificationTitle());
if (mArt != null) {
mNotificationBuilder.setStyle(new Notification.BigPictureStyle()
@@ -178,4 +206,45 @@ public class PipNotification {
return PendingIntent.getBroadcast(context, 0, new Intent(action),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
+
+ private class ActionBroadcastReceiver extends BroadcastReceiver {
+ final IntentFilter mIntentFilter;
+ {
+ mIntentFilter = new IntentFilter();
+ mIntentFilter.addAction(ACTION_CLOSE_PIP);
+ mIntentFilter.addAction(ACTION_SHOW_PIP_MENU);
+ }
+ boolean mRegistered = false;
+
+ void register() {
+ if (mRegistered) return;
+
+ mContext.registerReceiver(this, mIntentFilter, UserHandle.USER_ALL);
+ mRegistered = true;
+ }
+
+ void unregister() {
+ if (!mRegistered) return;
+
+ mContext.unregisterReceiver(this);
+ mRegistered = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (DEBUG) Log.d(TAG, "on(Broadcast)Receive(), action=" + action);
+
+ if (ACTION_SHOW_PIP_MENU.equals(action)) {
+ mDelegate.showPictureInPictureMenu();
+ } else if (ACTION_CLOSE_PIP.equals(action)) {
+ mDelegate.closePip();
+ }
+ }
+ }
+
+ interface Delegate {
+ void showPictureInPictureMenu();
+ void closePip();
+ }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
index 75388bf2a189d..5258e90300750 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
@@ -171,4 +171,4 @@ private val StatusBarNotification.deleteIntent: PendingIntent?
get() = tvExtensions?.getParcelable("delete_intent")
private fun StatusBarNotification.isPipNotificationWithTitle(expectedTitle: String): Boolean =
- tag == "PipNotification" && title == expectedTitle
\ No newline at end of file
+ tag == "TvPip" && title == expectedTitle
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 0d63324966fd2..0ba072e9e72f5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -25,7 +25,7 @@ import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.wm.shell.pip.tv.PipNotification;
+import com.android.wm.shell.pip.tv.TvPipNotificationController;
import java.util.Arrays;
@@ -36,7 +36,7 @@ public class NotificationChannels extends SystemUI {
public static String GENERAL = "GEN";
public static String STORAGE = "DSK";
public static String BATTERY = "BAT";
- public static String TVPIP = PipNotification.NOTIFICATION_CHANNEL_TVPIP;
+ public static String TVPIP = TvPipNotificationController.NOTIFICATION_CHANNEL; // "TVPIP"
public static String HINTS = "HNT";
public NotificationChannels(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index 4d3af9c011539..438704852617b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -33,8 +33,8 @@ import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.pip.tv.PipController;
-import com.android.wm.shell.pip.tv.PipNotification;
import com.android.wm.shell.pip.tv.TvPipMenuController;
+import com.android.wm.shell.pip.tv.TvPipNotificationController;
import java.util.Optional;
@@ -55,7 +55,7 @@ public abstract class TvPipModule {
PipTaskOrganizer pipTaskOrganizer,
TvPipMenuController tvPipMenuController,
PipMediaController pipMediaController,
- PipNotification pipNotification,
+ TvPipNotificationController tvPipNotificationController,
TaskStackListenerImpl taskStackListener,
WindowManagerShellWrapper windowManagerShellWrapper) {
return Optional.of(
@@ -66,18 +66,11 @@ public abstract class TvPipModule {
pipTaskOrganizer,
tvPipMenuController,
pipMediaController,
- pipNotification,
+ tvPipNotificationController,
taskStackListener,
windowManagerShellWrapper));
}
- @WMSingleton
- @Provides
- static PipNotification providePipNotification(Context context,
- PipMediaController pipMediaController) {
- return new PipNotification(context, pipMediaController);
- }
-
@WMSingleton
@Provides
static PipBoundsAlgorithm providePipBoundsHandler(Context context,
@@ -93,7 +86,7 @@ public abstract class TvPipModule {
@WMSingleton
@Provides
- static TvPipMenuController providesPipTvMenuController(
+ static TvPipMenuController providesTvPipMenuController(
Context context,
PipBoundsState pipBoundsState,
SystemWindows systemWindows,
@@ -101,17 +94,24 @@ public abstract class TvPipModule {
return new TvPipMenuController(context, pipBoundsState, systemWindows, pipMediaController);
}
+ @WMSingleton
+ @Provides
+ static TvPipNotificationController provideTvPipNotificationController(Context context,
+ PipMediaController pipMediaController) {
+ return new TvPipNotificationController(context, pipMediaController);
+ }
+
@WMSingleton
@Provides
static PipTaskOrganizer providePipTaskOrganizer(Context context,
- TvPipMenuController tvMenuController,
+ TvPipMenuController tvPipMenuController,
PipBoundsState pipBoundsState,
PipBoundsAlgorithm pipBoundsAlgorithm,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional