diff options
author | Shaowei Shen <shaoweishen@google.com> | 2022-06-22 23:53:24 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2022-06-22 23:53:24 +0000 |
commit | 3a4731d94975df21486c235aa347444126327566 (patch) | |
tree | 6ba1a4ef51d0fb5202d786b255a8d58227594335 | |
parent | 6eaacb50f29459c4bf977f681f9e4d9f33489c4c (diff) | |
parent | 547f613a80f80be6a2155acb956bec45d09bb605 (diff) | |
download | base-3a4731d94975df21486c235aa347444126327566.tar.gz |
Merge "[Output Switcher] Sets TemporaryAllowList when transfer from local to remote (or oppsite way)" into tm-dev
10 files changed, 86 insertions, 15 deletions
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java index 2fcab59cdec7..78214dc27a9f 100644 --- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java +++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java @@ -385,6 +385,12 @@ public class PowerExemptionManager { */ public static final int REASON_ACTIVE_DEVICE_ADMIN = 324; + /** + * Media notification re-generate during transferring. + * @hide + */ + public static final int REASON_MEDIA_NOTIFICATION_TRANSFER = 325; + /** @hide The app requests out-out. */ public static final int REASON_OPT_OUT_REQUESTED = 1000; @@ -465,6 +471,7 @@ public class PowerExemptionManager { REASON_DPO_PROTECTED_APP, REASON_DISALLOW_APPS_CONTROL, REASON_ACTIVE_DEVICE_ADMIN, + REASON_MEDIA_NOTIFICATION_TRANSFER, }) @Retention(RetentionPolicy.SOURCE) public @interface ReasonCode {} @@ -830,6 +837,8 @@ public class PowerExemptionManager { return "ACTIVE_DEVICE_ADMIN"; case REASON_OPT_OUT_REQUESTED: return "REASON_OPT_OUT_REQUESTED"; + case REASON_MEDIA_NOTIFICATION_TRANSFER: + return "REASON_MEDIA_NOTIFICATION_TRANSFER"; default: return "(unknown:" + reasonCode + ")"; } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index aeda20f16515..cd8ca0553add 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -60,6 +60,7 @@ import android.net.ConnectivityManager; import android.net.NetworkScoreManager; import android.net.wifi.WifiManager; import android.os.BatteryStats; +import android.os.PowerExemptionManager; import android.os.PowerManager; import android.os.ServiceManager; import android.os.UserManager; @@ -377,6 +378,13 @@ public class FrameworkServicesModule { /** */ @Provides + @Singleton + static PowerExemptionManager providePowerExemptionManager(Context context) { + return context.getSystemService(PowerExemptionManager.class); + } + + /** */ + @Provides @Main public SharedPreferences provideSharePreferences(Context context) { return Prefs.get(context); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index f0ce30d2dc66..f2f275323d58 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -285,6 +285,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { Log.d(TAG, "This device is already connected! : " + device.getName()); return; } + mController.setTemporaryAllowListExceptionIfNeeded(device); mCurrentActivePosition = -1; mController.connectDevice(device); device.setState(MediaDeviceState.STATE_CONNECTING); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt index 38005db28cf6..0fa326573c9c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt @@ -19,6 +19,7 @@ package com.android.systemui.media.dialog import android.content.Context import android.media.AudioManager import android.media.session.MediaSessionManager +import android.os.PowerExemptionManager import android.view.View import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager @@ -43,7 +44,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor( private val uiEventLogger: UiEventLogger, private val dialogLaunchAnimator: DialogLaunchAnimator, private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>, - private val audioManager: AudioManager + private val audioManager: AudioManager, + private val powerExemptionManager: PowerExemptionManager ) { var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null @@ -54,7 +56,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor( val controller = MediaOutputController(context, packageName, mediaSessionManager, lbm, starter, notifCollection, - dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager) + dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager, + powerExemptionManager) val dialog = MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller) mediaOutputBroadcastDialog = dialog diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 42e9af846322..f8b5edcbd11f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -44,6 +44,7 @@ import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.IBinder; +import android.os.PowerExemptionManager; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -101,6 +102,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final String PAGE_CONNECTED_DEVICES_KEY = "top_level_connected_devices"; + private static final long ALLOWLIST_DURATION_MS = 20000; + private static final String ALLOWLIST_REASON = "mediaoutput:remote_transfer"; + private final String mPackageName; private final Context mContext; private final MediaSessionManager mMediaSessionManager; @@ -114,6 +118,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>(); private final AudioManager mAudioManager; + private final PowerExemptionManager mPowerExemptionManager; private final NearbyMediaDevicesManager mNearbyMediaDevicesManager; private final Map<String, Integer> mNearbyDeviceInfoMap = new ConcurrentHashMap<>(); @@ -147,7 +152,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, CommonNotifCollection notifCollection, DialogLaunchAnimator dialogLaunchAnimator, Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional, - AudioManager audioManager) { + AudioManager audioManager, + PowerExemptionManager powerExemptionManager) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; @@ -155,6 +161,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mActivityStarter = starter; mNotifCollection = notifCollection; mAudioManager = audioManager; + mPowerExemptionManager = powerExemptionManager; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); @@ -776,7 +783,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, MediaOutputController controller = new MediaOutputController(mContext, mPackageName, mMediaSessionManager, mLocalBluetoothManager, mActivityStarter, mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager), - mAudioManager); + mAudioManager, mPowerExemptionManager); MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true, broadcastSender, controller); mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog); @@ -822,6 +829,17 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, broadcast.setBroadcastCode(broadcastCode.getBytes(StandardCharsets.UTF_8)); } + void setTemporaryAllowListExceptionIfNeeded(MediaDevice targetDevice) { + if (mPowerExemptionManager == null || mPackageName == null) { + Log.w(TAG, "powerExemptionManager or package name is null"); + return; + } + mPowerExemptionManager.addToTemporaryAllowList(mPackageName, + PowerExemptionManager.REASON_MEDIA_NOTIFICATION_TRANSFER, + ALLOWLIST_REASON, + ALLOWLIST_DURATION_MS); + } + String getBroadcastMetadata() { LocalBluetoothLeBroadcast broadcast = mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile(); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index 36a46f067fb0..5581fb861e6a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -19,6 +19,7 @@ package com.android.systemui.media.dialog import android.content.Context import android.media.AudioManager import android.media.session.MediaSessionManager +import android.os.PowerExemptionManager import android.view.View import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager @@ -43,7 +44,8 @@ class MediaOutputDialogFactory @Inject constructor( private val uiEventLogger: UiEventLogger, private val dialogLaunchAnimator: DialogLaunchAnimator, private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>, - private val audioManager: AudioManager + private val audioManager: AudioManager, + private val powerExemptionManager: PowerExemptionManager ) { companion object { var mediaOutputDialog: MediaOutputDialog? = null @@ -54,9 +56,11 @@ class MediaOutputDialogFactory @Inject constructor( // Dismiss the previous dialog, if any. mediaOutputDialog?.dismiss() - val controller = MediaOutputController(context, packageName, - mediaSessionManager, lbm, starter, notifCollection, - dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager) + val controller = MediaOutputController( + context, packageName, + mediaSessionManager, lbm, starter, notifCollection, + dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager, + powerExemptionManager) val dialog = MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger) mediaOutputDialog = dialog diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index e3b5059131fa..9eaa20c2afed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -32,6 +32,7 @@ import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.Bundle; +import android.os.PowerExemptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -86,6 +87,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { NearbyMediaDevicesManager.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private final AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; @@ -110,7 +112,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index feed3347f3e2..2bf5f0fcbfcb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -19,6 +19,9 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -34,10 +37,12 @@ import android.graphics.drawable.Icon; import android.media.AudioManager; import android.media.MediaDescription; import android.media.MediaMetadata; +import android.media.MediaRoute2Info; import android.media.NearbyDevice; import android.media.RoutingSessionInfo; import android.media.session.MediaController; import android.media.session.MediaSessionManager; +import android.os.PowerExemptionManager; import android.os.RemoteException; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; @@ -97,6 +102,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class); private ActivityStarter mStarter = mock(ActivityStarter.class); private AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class); private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class); private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( @@ -125,7 +131,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; MediaDescription.Builder builder = new MediaDescription.Builder(); @@ -177,7 +183,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.start(mCb); @@ -206,7 +212,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.start(mCb); @@ -511,7 +517,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotifCollection, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); } @@ -591,4 +597,20 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).isTrue(); } + + @Test + public void setTemporaryAllowListExceptionIfNeeded_fromRemoteToBluetooth_addsAllowList() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); + when(mMediaDevice1.getDeviceType()).thenReturn( + MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE); + when(mMediaDevice1.getFeatures()).thenReturn( + ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_AUDIO_PLAYBACK)); + when(mMediaDevice2.getDeviceType()).thenReturn( + MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE); + + mMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2); + + verify(mPowerExemptionManager).addToTemporaryAllowList(anyString(), anyInt(), anyString(), + anyLong()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index 6786ad0116ea..ef0fc95f95b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -29,6 +29,7 @@ import android.media.MediaRoute2Info; import android.media.session.MediaController; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; +import android.os.PowerExemptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -84,6 +85,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); private final AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private List<MediaController> mMediaControllers = new ArrayList<>(); private MediaOutputDialog mMediaOutputDialog; @@ -103,7 +105,7 @@ public class MediaOutputDialogTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender, mMediaOutputController, mUiEventLogger); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java index 379bb4fd6336..4534ae6448ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import android.media.AudioManager; import android.media.session.MediaSessionManager; +import android.os.PowerExemptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -70,6 +71,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock( NearbyMediaDevicesManager.class); private final AudioManager mAudioManager = mock(AudioManager.class); + private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class); private MediaOutputGroupDialog mMediaOutputGroupDialog; private MediaOutputController mMediaOutputController; @@ -80,7 +82,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, mMediaSessionManager, mLocalBluetoothManager, mStarter, mNotificationEntryManager, mDialogLaunchAnimator, - Optional.of(mNearbyMediaDevicesManager), mAudioManager); + Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender, mMediaOutputController); |