From 1ae3e9abc135dc78120a1a65d2f598d8f6595cb6 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Wed, 24 Feb 2021 15:18:58 -0800 Subject: [PATCH] Protect the default media PiP PendingIntent - Add permission when register broadcast receiver - Set receiver package explicitly when constructing PendingIntent - Do not crash if there is no active media session when receive broadcast Bug: 171967947 Test: adb unroot; adb shell am broadcast -a \ com.android.wm.shell.pip.PLAY Change-Id: If9c46aab9d91de633a2628513430a59a6692e59a --- .../wm/shell/pip/PipMediaController.java | 81 ++++++++++--------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java index 6afcc06aa1ae0..3af0ff0dfb363 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java @@ -19,6 +19,8 @@ package com.android.wm.shell.pip; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; +import android.annotation.DrawableRes; +import android.annotation.StringRes; import android.app.PendingIntent; import android.app.RemoteAction; import android.content.BroadcastReceiver; @@ -49,6 +51,7 @@ import java.util.List; * when there is a media session from the top PiP activity. */ public class PipMediaController { + private static final String SYSTEMUI_PERMISSION = "com.android.systemui.permission.SELF"; private static final String ACTION_PLAY = "com.android.wm.shell.pip.PLAY"; private static final String ACTION_PAUSE = "com.android.wm.shell.pip.PAUSE"; @@ -87,18 +90,26 @@ public class PipMediaController { private RemoteAction mNextAction; private RemoteAction mPrevAction; - private BroadcastReceiver mPlayPauseActionReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mMediaActionReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(ACTION_PLAY)) { - mMediaController.getTransportControls().play(); - } else if (action.equals(ACTION_PAUSE)) { - mMediaController.getTransportControls().pause(); - } else if (action.equals(ACTION_NEXT)) { - mMediaController.getTransportControls().skipToNext(); - } else if (action.equals(ACTION_PREV)) { - mMediaController.getTransportControls().skipToPrevious(); + if (mMediaController == null || mMediaController.getTransportControls() == null) { + // no active media session, bail early. + return; + } + switch (intent.getAction()) { + case ACTION_PLAY: + mMediaController.getTransportControls().play(); + break; + case ACTION_PAUSE: + mMediaController.getTransportControls().pause(); + break; + case ACTION_NEXT: + mMediaController.getTransportControls().skipToNext(); + break; + case ACTION_PREV: + mMediaController.getTransportControls().skipToPrevious(); + break; } } }; @@ -131,10 +142,19 @@ public class PipMediaController { mediaControlFilter.addAction(ACTION_PAUSE); mediaControlFilter.addAction(ACTION_NEXT); mediaControlFilter.addAction(ACTION_PREV); - mContext.registerReceiverForAllUsers(mPlayPauseActionReceiver, mediaControlFilter, - null /* permission */, mainHandler); + mContext.registerReceiverForAllUsers(mMediaActionReceiver, mediaControlFilter, + SYSTEMUI_PERMISSION, mainHandler); + + // Creates the standard media buttons that we may show. + mPauseAction = getDefaultRemoteAction(R.string.pip_pause, + R.drawable.pip_ic_pause_white, ACTION_PAUSE); + mPlayAction = getDefaultRemoteAction(R.string.pip_play, + R.drawable.pip_ic_play_arrow_white, ACTION_PLAY); + mNextAction = getDefaultRemoteAction(R.string.pip_skip_to_next, + R.drawable.pip_ic_skip_next_white, ACTION_NEXT); + mPrevAction = getDefaultRemoteAction(R.string.pip_skip_to_prev, + R.drawable.pip_ic_skip_previous_white, ACTION_PREV); - createMediaActions(); mMediaSessionManager = context.getSystemService(MediaSessionManager.class); } @@ -216,32 +236,15 @@ public class PipMediaController { return mediaActions; } - /** - * Creates the standard media buttons that we may show. - */ - private void createMediaActions() { - String pauseDescription = mContext.getString(R.string.pip_pause); - mPauseAction = new RemoteAction(Icon.createWithResource(mContext, - R.drawable.pip_ic_pause_white), pauseDescription, pauseDescription, - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PAUSE), - FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE)); - - String playDescription = mContext.getString(R.string.pip_play); - mPlayAction = new RemoteAction(Icon.createWithResource(mContext, - R.drawable.pip_ic_play_arrow_white), playDescription, playDescription, - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PLAY), - FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE)); - - String nextDescription = mContext.getString(R.string.pip_skip_to_next); - mNextAction = new RemoteAction(Icon.createWithResource(mContext, - R.drawable.pip_ic_skip_next_white), nextDescription, nextDescription, - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NEXT), - FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE)); - - String prevDescription = mContext.getString(R.string.pip_skip_to_prev); - mPrevAction = new RemoteAction(Icon.createWithResource(mContext, - R.drawable.pip_ic_skip_previous_white), prevDescription, prevDescription, - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PREV), + /** @return Default {@link RemoteAction} sends broadcast back to SysUI. */ + private RemoteAction getDefaultRemoteAction(@StringRes int titleAndDescription, + @DrawableRes int icon, String action) { + final String titleAndDescriptionStr = mContext.getString(titleAndDescription); + final Intent intent = new Intent(action); + intent.setPackage(mContext.getPackageName()); + return new RemoteAction(Icon.createWithResource(mContext, icon), + titleAndDescriptionStr, titleAndDescriptionStr, + PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE)); }