Refactor .tv.PipNotification
Make TvPipNotificationController (formerly PipNotification) responsible for handling broadcasts sent from the Pip StatusBarNotification. Previouslt TV PipContoller was in charge of that. Also, as mentioned above, rename PipNotification to TvPipNotificationController. Bug: 153784643 Test: atest WMShellFlickerTests:TvPipNotificationTests Change-Id: Iabdf5ee9d464653e233aee9044ac8cbb26478dea
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
* <p>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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
tag == "TvPip" && title == expectedTitle
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<LegacySplitScreen> splitScreenOptional, DisplayController displayController,
|
||||
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
|
||||
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm,
|
||||
tvMenuController, pipSurfaceTransactionHelper, splitScreenOptional,
|
||||
tvPipMenuController, pipSurfaceTransactionHelper, splitScreenOptional,
|
||||
displayController, pipUiEventLogger, shellTaskOrganizer);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user