summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt4
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt1
-rw-r--r--services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java175
-rw-r--r--services/core/java/com/android/server/media/DeviceRouteController.java184
-rw-r--r--services/core/java/com/android/server/media/LegacyDeviceRouteController.java184
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java20
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java20
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java15
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java)12
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java54
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java76
18 files changed, 571 insertions, 329 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 259f1e9d4c53..f625a73f222d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -4492,8 +4492,8 @@ package android.app {
method public void openOptionsMenu();
method public void overrideActivityTransition(int, @AnimRes int, @AnimRes int);
method public void overrideActivityTransition(int, @AnimRes int, @AnimRes int, @ColorInt int);
- method public void overridePendingTransition(int, int);
- method public void overridePendingTransition(int, int, int);
+ method @Deprecated public void overridePendingTransition(int, int);
+ method @Deprecated public void overridePendingTransition(int, int, int);
method public void postponeEnterTransition();
method public void recreate();
method public void registerActivityLifecycleCallbacks(@NonNull android.app.Application.ActivityLifecycleCallbacks);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d9c7a27cb95e..125e7270b0e2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6621,7 +6621,9 @@ public class Activity extends ContextThemeWrapper
* the incoming activity. Use 0 for no animation.
* @param exitAnim A resource ID of the animation resource to use for
* the outgoing activity. Use 0 for no animation.
+ * @deprecated Use {@link #overrideActivityTransition(int, int, int)}} instead.
*/
+ @Deprecated
public void overridePendingTransition(int enterAnim, int exitAnim) {
overridePendingTransition(enterAnim, exitAnim, 0);
}
@@ -6644,7 +6646,9 @@ public class Activity extends ContextThemeWrapper
* the outgoing activity. Use 0 for no animation.
* @param backgroundColor The background color to use for the background during the animation if
* the animation requires a background. Set to 0 to not override the default color.
+ * @deprecated Use {@link #overrideActivityTransition(int, int, int, int)}} instead.
*/
+ @Deprecated
public void overridePendingTransition(int enterAnim, int exitAnim, int backgroundColor) {
ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), enterAnim,
exitAnim, backgroundColor);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 8d29901c3a07..bcc37baa5b00 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -143,8 +143,12 @@ public class TransitionAnimationHelper {
Animation a = null;
if (animAttr != 0) {
if (overrideType == ANIM_FROM_STYLE && !isTask) {
- a = loadCustomActivityTransition(animAttr, options, enter, transitionAnimation);
- if (a == null) {
+ final TransitionInfo.AnimationOptions.CustomActivityTransition customTransition =
+ getCustomActivityTransition(animAttr, options);
+ if (customTransition != null) {
+ a = loadCustomActivityTransition(
+ customTransition, options, enter, transitionAnimation);
+ } else {
a = transitionAnimation
.loadAnimationAttr(options.getPackageName(), options.getAnimations(),
animAttr, translucent);
@@ -161,10 +165,8 @@ public class TransitionAnimationHelper {
return a;
}
- static Animation loadCustomActivityTransition(int animAttr,
- TransitionInfo.AnimationOptions options, boolean enter,
- TransitionAnimation transitionAnimation) {
- Animation a = null;
+ static TransitionInfo.AnimationOptions.CustomActivityTransition getCustomActivityTransition(
+ int animAttr, TransitionInfo.AnimationOptions options) {
boolean isOpen = false;
switch (animAttr) {
case R.styleable.WindowAnimation_activityOpenEnterAnimation:
@@ -178,17 +180,19 @@ public class TransitionAnimationHelper {
return null;
}
- final TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim =
- options.getCustomActivityTransition(isOpen);
- if (transitionAnim != null) {
- a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
- enter ? transitionAnim.getCustomEnterResId()
- : transitionAnim.getCustomExitResId());
- if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
- a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
- }
- }
+ return options.getCustomActivityTransition(isOpen);
+ }
+ static Animation loadCustomActivityTransition(
+ @NonNull TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim,
+ TransitionInfo.AnimationOptions options, boolean enter,
+ TransitionAnimation transitionAnimation) {
+ final Animation a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
+ enter ? transitionAnim.getCustomEnterResId()
+ : transitionAnim.getCustomExitResId());
+ if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
+ a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
+ }
return a;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2ad1ab722d55..288f0cc4456d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -966,13 +966,24 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+ if (!handleOnAnimationStart(
+ transit, apps, wallpapers, nonApps, finishedCallback)) {
+ // Usually we rely on animation completion to synchronize occluded status,
+ // but there was no animation to play, so just update it now.
+ setOccluded(true /* isOccluded */, false /* animate */);
+ }
+ }
+
+ private boolean handleOnAnimationStart(int transit, RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+ IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
if (apps == null || apps.length == 0 || apps[0] == null) {
if (DEBUG) {
Log.d(TAG, "No apps provided to the OccludeByDream runner; "
+ "skipping occluding animation.");
}
finishedCallback.onAnimationFinished();
- return;
+ return false;
}
final RemoteAnimationTarget primary = apps[0];
@@ -982,7 +993,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
Log.w(TAG, "The occluding app isn't Dream; "
+ "finishing up. Please check that the config is correct.");
finishedCallback.onAnimationFinished();
- return;
+ return false;
}
final SyncRtSurfaceTransactionApplier applier =
@@ -1031,6 +1042,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mOccludeByDreamAnimator.start();
});
+ return true;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index 030c54fbd87d..9952cfd4e85b 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -62,8 +62,6 @@ constructor(
BluetoothAdapter.OnMetadataChangedListener {
private val stylusCallbacks: CopyOnWriteArrayList<StylusCallback> = CopyOnWriteArrayList()
- private val stylusBatteryCallbacks: CopyOnWriteArrayList<StylusBatteryCallback> =
- CopyOnWriteArrayList()
// This map should only be accessed on the handler
private val inputDeviceAddressMap: MutableMap<Int, String?> = ArrayMap()
@@ -106,14 +104,6 @@ constructor(
stylusCallbacks.remove(callback)
}
- fun registerBatteryCallback(callback: StylusBatteryCallback) {
- stylusBatteryCallbacks.add(callback)
- }
-
- fun unregisterBatteryCallback(callback: StylusBatteryCallback) {
- stylusBatteryCallbacks.remove(callback)
- }
-
override fun onInputDeviceAdded(deviceId: Int) {
if (!hasStarted) return
@@ -195,7 +185,7 @@ constructor(
"${device.address}: $isCharging"
}
- executeStylusBatteryCallbacks { cb ->
+ executeStylusCallbacks { cb ->
cb.onStylusBluetoothChargingStateChanged(inputDeviceId, device, isCharging)
}
}
@@ -221,7 +211,7 @@ constructor(
onStylusUsed()
}
- executeStylusBatteryCallbacks { cb ->
+ executeStylusCallbacks { cb ->
cb.onStylusUsiBatteryStateChanged(deviceId, eventTimeMillis, batteryState)
}
}
@@ -329,10 +319,6 @@ constructor(
stylusCallbacks.forEach(run)
}
- private fun executeStylusBatteryCallbacks(run: (cb: StylusBatteryCallback) -> Unit) {
- stylusBatteryCallbacks.forEach(run)
- }
-
private fun registerBatteryListener(deviceId: Int) {
try {
inputManager.addInputDeviceBatteryListener(deviceId, executor, this)
@@ -378,13 +364,6 @@ constructor(
fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {}
fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {}
fun onStylusFirstUsed() {}
- }
-
- /**
- * Callback interface to receive stylus battery events from the StylusManager. All callbacks are
- * runs on the same background handler.
- */
- interface StylusBatteryCallback {
fun onStylusBluetoothChargingStateChanged(
inputDeviceId: Int,
btDevice: BluetoothDevice,
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
index 27cafb10c07d..3667392b515e 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
@@ -37,7 +37,7 @@ constructor(
private val inputManager: InputManager,
private val stylusUsiPowerUi: StylusUsiPowerUI,
private val featureFlags: FeatureFlags,
-) : CoreStartable, StylusManager.StylusCallback, StylusManager.StylusBatteryCallback {
+) : CoreStartable, StylusManager.StylusCallback {
override fun onStylusAdded(deviceId: Int) {
// On some devices, the addition of a new internal stylus indicates the use of a
@@ -74,7 +74,6 @@ constructor(
stylusUsiPowerUi.init()
stylusManager.registerCallback(this)
- stylusManager.registerBatteryCallback(this)
stylusManager.startListener()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
index f8bf4b91e11a..4525ad27b749 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
@@ -65,8 +65,6 @@ class StylusManagerTest : SysuiTestCase() {
@Mock lateinit var uiEventLogger: UiEventLogger
@Mock lateinit var stylusCallback: StylusManager.StylusCallback
@Mock lateinit var otherStylusCallback: StylusManager.StylusCallback
- @Mock lateinit var stylusBatteryCallback: StylusManager.StylusBatteryCallback
- @Mock lateinit var otherStylusBatteryCallback: StylusManager.StylusBatteryCallback
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var stylusManager: StylusManager
@@ -123,7 +121,6 @@ class StylusManagerTest : SysuiTestCase() {
stylusManager.startListener()
stylusManager.registerCallback(stylusCallback)
- stylusManager.registerBatteryCallback(stylusBatteryCallback)
clearInvocations(inputManager)
}
@@ -434,23 +431,6 @@ class StylusManagerTest : SysuiTestCase() {
}
@Test
- fun onMetadataChanged_multipleRegisteredBatteryCallbacks_executesAll() {
- stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
- stylusManager.registerBatteryCallback(otherStylusBatteryCallback)
-
- stylusManager.onMetadataChanged(
- bluetoothDevice,
- BluetoothDevice.METADATA_MAIN_CHARGING,
- "true".toByteArray()
- )
-
- verify(stylusBatteryCallback, times(1))
- .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
- verify(otherStylusBatteryCallback, times(1))
- .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
- }
-
- @Test
fun onMetadataChanged_chargingStateTrue_executesBatteryCallbacks() {
stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
@@ -460,7 +440,7 @@ class StylusManagerTest : SysuiTestCase() {
"true".toByteArray()
)
- verify(stylusBatteryCallback, times(1))
+ verify(stylusCallback, times(1))
.onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
}
@@ -474,7 +454,7 @@ class StylusManagerTest : SysuiTestCase() {
"false".toByteArray()
)
- verify(stylusBatteryCallback, times(1))
+ verify(stylusCallback, times(1))
.onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, false)
}
@@ -486,7 +466,7 @@ class StylusManagerTest : SysuiTestCase() {
"true".toByteArray()
)
- verifyNoMoreInteractions(stylusBatteryCallback)
+ verifyNoMoreInteractions(stylusCallback)
}
@Test
@@ -499,8 +479,7 @@ class StylusManagerTest : SysuiTestCase() {
"true".toByteArray()
)
- verify(stylusBatteryCallback, never())
- .onStylusBluetoothChargingStateChanged(any(), any(), any())
+ verify(stylusCallback, never()).onStylusBluetoothChargingStateChanged(any(), any(), any())
}
@Test
@@ -614,7 +593,7 @@ class StylusManagerTest : SysuiTestCase() {
fun onBatteryStateChanged_executesBatteryCallbacks() {
stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
- verify(stylusBatteryCallback, times(1))
+ verify(stylusCallback, times(1))
.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
index 82b80f53d6b0..3db0ecc4e8df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
@@ -96,7 +96,6 @@ class StylusUsiPowerStartableTest : SysuiTestCase() {
startable.start()
verify(stylusManager, times(1)).registerCallback(startable)
- verify(stylusManager, times(1)).registerBatteryCallback(startable)
}
@Test
diff --git a/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
new file mode 100644
index 000000000000..961313de0c97
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package com.android.server.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+
+/* package */ final class AudioPoliciesDeviceRouteController implements DeviceRouteController {
+
+ private static final String TAG = "APDeviceRoutesController";
+
+ private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final AudioManager mAudioManager;
+ @NonNull
+ private final IAudioService mAudioService;
+
+ @NonNull
+ private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+ @NonNull
+ private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+ private int mDeviceVolume;
+ private MediaRoute2Info mDeviceRoute;
+
+ @VisibleForTesting
+ /* package */ AudioPoliciesDeviceRouteController(@NonNull Context context,
+ @NonNull AudioManager audioManager,
+ @NonNull IAudioService audioService,
+ @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(audioManager);
+ Objects.requireNonNull(audioService);
+ Objects.requireNonNull(onDeviceRouteChangedListener);
+
+ mContext = context;
+ mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+ mAudioManager = audioManager;
+ mAudioService = audioService;
+
+ AudioRoutesInfo newAudioRoutes = null;
+ try {
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+ }
+
+ mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ }
+
+ @Override
+ public boolean selectRoute(@Nullable Integer type) {
+ // No-op as the controller does not support selection from the outside of the class.
+ return false;
+ }
+
+ @Override
+ @NonNull
+ public synchronized MediaRoute2Info getDeviceRoute() {
+ return mDeviceRoute;
+ }
+
+ @Override
+ public synchronized boolean updateVolume(int volume) {
+ if (mDeviceVolume == volume) {
+ return false;
+ }
+
+ mDeviceVolume = volume;
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+ .setVolume(volume)
+ .build();
+
+ return true;
+ }
+
+ private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+ int name = R.string.default_audio_route_name;
+ int type = TYPE_BUILTIN_SPEAKER;
+
+ if (newRoutes != null) {
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+ type = TYPE_WIRED_HEADPHONES;
+ name = R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ type = TYPE_WIRED_HEADSET;
+ name = R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ type = TYPE_DOCK;
+ name = R.string.default_audio_route_name_dock_speakers;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ type = TYPE_HDMI;
+ name = R.string.default_audio_route_name_external_device;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ type = TYPE_USB_DEVICE;
+ name = R.string.default_audio_route_name_usb;
+ }
+ }
+
+ synchronized (this) {
+ return new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolume(mDeviceVolume)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setType(type)
+ .addFeature(FEATURE_LIVE_AUDIO)
+ .addFeature(FEATURE_LIVE_VIDEO)
+ .addFeature(FEATURE_LOCAL_PLAYBACK)
+ .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+ .build();
+ }
+ }
+
+ private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+ mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+ }
+
+ private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+ @Override
+ public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+ MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ synchronized (AudioPoliciesDeviceRouteController.this) {
+ mDeviceRoute = deviceRoute;
+ }
+ notifyDeviceRouteUpdate(deviceRoute);
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/media/DeviceRouteController.java b/services/core/java/com/android/server/media/DeviceRouteController.java
index 8bd6416a6ddb..d7893eed800b 100644
--- a/services/core/java/com/android/server/media/DeviceRouteController.java
+++ b/services/core/java/com/android/server/media/DeviceRouteController.java
@@ -16,32 +16,14 @@
package com.android.server.media;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
-import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
-import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
-import static android.media.MediaRoute2Info.TYPE_DOCK;
-import static android.media.MediaRoute2Info.TYPE_HDMI;
-import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.AudioManager;
-import android.media.AudioRoutesInfo;
import android.media.IAudioRoutesObserver;
import android.media.IAudioService;
import android.media.MediaRoute2Info;
-import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.Slog;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Objects;
/**
* Controls device routes.
@@ -49,145 +31,65 @@ import java.util.Objects;
* <p>A device route is a system wired route, for example, built-in speaker, wired
* headsets and headphones, dock, hdmi, or usb devices.
*
- * <p>Thread safe.
- *
* @see SystemMediaRoute2Provider
*/
-/* package */ final class DeviceRouteController {
-
- private static final String TAG = "WiredRoutesController";
-
- private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
-
- @NonNull
- private final Context mContext;
- @NonNull
- private final AudioManager mAudioManager;
- @NonNull
- private final IAudioService mAudioService;
-
- @NonNull
- private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
- @NonNull
- private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
-
- private int mDeviceVolume;
- private MediaRoute2Info mDeviceRoute;
+/* package */ interface DeviceRouteController {
+ /**
+ * Returns a new instance of {@link DeviceRouteController}.
+ */
/* package */ static DeviceRouteController createInstance(@NonNull Context context,
@NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
AudioManager audioManager = context.getSystemService(AudioManager.class);
IAudioService audioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
- return new DeviceRouteController(context,
+ return new LegacyDeviceRouteController(context,
audioManager,
audioService,
onDeviceRouteChangedListener);
}
- @VisibleForTesting
- /* package */ DeviceRouteController(@NonNull Context context,
- @NonNull AudioManager audioManager,
- @NonNull IAudioService audioService,
- @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
- Objects.requireNonNull(context);
- Objects.requireNonNull(audioManager);
- Objects.requireNonNull(audioService);
- Objects.requireNonNull(onDeviceRouteChangedListener);
-
- mContext = context;
- mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
-
- mAudioManager = audioManager;
- mAudioService = audioService;
-
- AudioRoutesInfo newAudioRoutes = null;
- try {
- newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
- } catch (RemoteException e) {
- Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
- }
-
- mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
- }
-
+ /**
+ * Select the route with the given built-in or wired {@link MediaRoute2Info.Type}.
+ *
+ * <p>If the type is {@code null} then unselects the route and falls back to the default device
+ * route observed from
+ * {@link com.android.server.audio.AudioService#startWatchingRoutes(IAudioRoutesObserver)}.
+ *
+ * @param type device type. May be {@code null} to unselect currently selected route.
+ * @return whether the selection succeeds. If the selection fails the state of the controller
+ * remains intact.
+ */
+ boolean selectRoute(@Nullable @MediaRoute2Info.Type Integer type);
+
+ /**
+ * Returns currently selected device (built-in or wired) route.
+ *
+ * @return non-null device route.
+ */
@NonNull
- /* package */ synchronized MediaRoute2Info getDeviceRoute() {
- return mDeviceRoute;
- }
-
- /* package */ synchronized boolean updateVolume(int volume) {
- if (mDeviceVolume == volume) {
- return false;
- }
-
- mDeviceVolume = volume;
- mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
- .setVolume(volume)
- .build();
-
- return true;
- }
-
- private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
- int name = R.string.default_audio_route_name;
- int type = TYPE_BUILTIN_SPEAKER;
-
- if (newRoutes != null) {
- if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
- type = TYPE_WIRED_HEADPHONES;
- name = com.android.internal.R.string.default_audio_route_name_headphones;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
- type = TYPE_WIRED_HEADSET;
- name = com.android.internal.R.string.default_audio_route_name_headphones;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
- type = TYPE_DOCK;
- name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
- type = TYPE_HDMI;
- name = com.android.internal.R.string.default_audio_route_name_external_device;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
- type = TYPE_USB_DEVICE;
- name = com.android.internal.R.string.default_audio_route_name_usb;
- }
- }
-
- synchronized (this) {
- return new MediaRoute2Info.Builder(
- DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
- .setVolumeHandling(mAudioManager.isVolumeFixed()
- ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
- : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
- .setVolume(mDeviceVolume)
- .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
- .setType(type)
- .addFeature(FEATURE_LIVE_AUDIO)
- .addFeature(FEATURE_LIVE_VIDEO)
- .addFeature(FEATURE_LOCAL_PLAYBACK)
- .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
- .build();
- }
- }
-
- private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
- mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
- }
-
- /* package */ interface OnDeviceRouteChangedListener {
+ MediaRoute2Info getDeviceRoute();
+
+ /**
+ * Updates device route volume.
+ *
+ * @param volume specifies a volume for the device route or 0 for unknown.
+ * @return {@code true} if updated successfully and {@code false} otherwise.
+ */
+ boolean updateVolume(int volume);
+
+ /**
+ * Interface for receiving events when device route has changed.
+ */
+ interface OnDeviceRouteChangedListener {
+
+ /**
+ * Called when device route has changed.
+ *
+ * @param deviceRoute non-null device route.
+ */
void onDeviceRouteChanged(@NonNull MediaRoute2Info deviceRoute);
}
- private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
-
- @Override
- public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
- MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
- synchronized (DeviceRouteController.this) {
- mDeviceRoute = deviceRoute;
- }
- notifyDeviceRouteUpdate(deviceRoute);
- }
- }
-
}
diff --git a/services/core/java/com/android/server/media/LegacyDeviceRouteController.java b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
new file mode 100644
index 000000000000..971d11f24b9c
--- /dev/null
+++ b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package com.android.server.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * <p>Thread safe.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ final class LegacyDeviceRouteController implements DeviceRouteController {
+
+ private static final String TAG = "LDeviceRouteController";
+
+ private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final AudioManager mAudioManager;
+ @NonNull
+ private final IAudioService mAudioService;
+
+ @NonNull
+ private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+ @NonNull
+ private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+ private int mDeviceVolume;
+ private MediaRoute2Info mDeviceRoute;
+
+ @VisibleForTesting
+ /* package */ LegacyDeviceRouteController(@NonNull Context context,
+ @NonNull AudioManager audioManager,
+ @NonNull IAudioService audioService,
+ @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(audioManager);
+ Objects.requireNonNull(audioService);
+ Objects.requireNonNull(onDeviceRouteChangedListener);
+
+ mContext = context;
+ mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+ mAudioManager = audioManager;
+ mAudioService = audioService;
+
+ AudioRoutesInfo newAudioRoutes = null;
+ try {
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+ }
+
+ mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ }
+
+ @Override
+ public boolean selectRoute(@Nullable Integer type) {
+ // No-op as the controller does not support selection from the outside of the class.
+ return false;
+ }
+
+ @Override
+ @NonNull
+ public synchronized MediaRoute2Info getDeviceRoute() {
+ return mDeviceRoute;
+ }
+
+ @Override
+ public synchronized boolean updateVolume(int volume) {
+ if (mDeviceVolume == volume) {
+ return false;
+ }
+
+ mDeviceVolume = volume;
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+ .setVolume(volume)
+ .build();
+
+ return true;
+ }
+
+ private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+ int name = R.string.default_audio_route_name;
+ int type = TYPE_BUILTIN_SPEAKER;
+
+ if (newRoutes != null) {
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+ type = TYPE_WIRED_HEADPHONES;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ type = TYPE_WIRED_HEADSET;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ type = TYPE_DOCK;
+ name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ type = TYPE_HDMI;
+ name = com.android.internal.R.string.default_audio_route_name_external_device;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ type = TYPE_USB_DEVICE;
+ name = com.android.internal.R.string.default_audio_route_name_usb;
+ }
+ }
+
+ synchronized (this) {
+ return new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolume(mDeviceVolume)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setType(type)
+ .addFeature(FEATURE_LIVE_AUDIO)
+ .addFeature(FEATURE_LIVE_VIDEO)
+ .addFeature(FEATURE_LOCAL_PLAYBACK)
+ .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+ .build();
+ }
+ }
+
+ private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+ mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+ }
+
+ private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+ @Override
+ public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+ MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ synchronized (LegacyDeviceRouteController.this) {
+ mDeviceRoute = deviceRoute;
+ }
+ notifyDeviceRouteUpdate(deviceRoute);
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 53e841d50b33..73440b7f2eec 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -892,6 +892,7 @@ abstract public class ManagedServices {
return allowedComponents;
}
+ @NonNull
protected List<String> getAllowedPackages(int userId) {
final List<String> allowedPackages = new ArrayList<>();
synchronized (mApproved) {
@@ -1181,25 +1182,6 @@ abstract public class ManagedServices {
return installed;
}
- protected Set<String> getAllowedPackages() {
- final Set<String> allowedPackages = new ArraySet<>();
- synchronized (mApproved) {
- for (int k = 0; k < mApproved.size(); k++) {
- ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
- for (int i = 0; i < allowedByType.size(); i++) {
- final ArraySet<String> allowed = allowedByType.valueAt(i);
- for (int j = 0; j < allowed.size(); j++) {
- String pkgName = getPackageName(allowed.valueAt(j));
- if (!TextUtils.isEmpty(pkgName)) {
- allowedPackages.add(pkgName);
- }
- }
- }
- }
- }
- return allowedPackages;
- }
-
private void trimApprovedListsAccordingToInstalledServices(int userId) {
synchronized (mApproved) {
final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0d394570ab8e..53b03d58beae 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2709,16 +2709,18 @@ public class NotificationManagerService extends SystemService {
}
private void sendRegisteredOnlyBroadcast(String action) {
- Intent intent = new Intent(action);
- getContext().sendBroadcastAsUser(intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
- UserHandle.ALL, null);
+ int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true);
+ Intent intent = new Intent(action).addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ for (int userId : userIds) {
+ getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), null);
+ }
// explicitly send the broadcast to all DND packages, even if they aren't currently running
- intent.setFlags(0);
- final Set<String> dndApprovedPackages = mConditionProviders.getAllowedPackages();
- for (String pkg : dndApprovedPackages) {
- intent.setPackage(pkg);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+ for (int userId : userIds) {
+ for (String pkg : mConditionProviders.getAllowedPackages(userId)) {
+ Intent pkgIntent = new Intent(action).setPackage(pkg).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ getContext().sendBroadcastAsUser(pkgIntent, UserHandle.of(userId));
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 45dc49dba2ca..37a59da33ad8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2977,7 +2977,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
case KeyEvent.KEYCODE_H:
- if (down && event.isMetaPressed()) {
+ if (event.isMetaPressed()) {
return handleHomeShortcuts(displayId, focusedToken, event);
}
break;
@@ -3018,11 +3018,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) {
enterStageSplitFromRunningApp(true /* leftOrTop */);
return key_consumed;
- } else if (!down && event.isMetaPressed()) {
- boolean backKeyHandled = backKeyPress();
- if (backKeyHandled) {
- return key_consumed;
- }
}
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
@@ -3031,14 +3026,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return key_consumed;
}
break;
- case KeyEvent.KEYCODE_GRAVE:
- if (!down && event.isMetaPressed()) {
- boolean backKeyHandled = backKeyPress();
- if (backKeyHandled) {
- return key_consumed;
- }
- }
- break;
case KeyEvent.KEYCODE_SLASH:
if (down && repeatCount == 0 && event.isMetaPressed() && !keyguardOn) {
toggleKeyboardShortcutsMenu(event.getDeviceId());
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index f73c68a42ec7..939cf1ae471b 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -888,8 +888,11 @@ public class AppTransition implements Dump {
} else {
int animAttr = mapOpenCloseTransitTypes(transit, enter);
if (animAttr != 0) {
- a = loadCustomActivityAnimation(animAttr, enter, container);
- if (a == null) {
+ final CustomAppTransition customAppTransition =
+ getCustomAppTransition(animAttr, container);
+ if (customAppTransition != null) {
+ a = loadCustomActivityAnimation(customAppTransition, enter, container);
+ } else {
if (canCustomizeAppTransition) {
a = loadAnimationAttr(lp, animAttr, transit);
} else {
@@ -911,7 +914,7 @@ public class AppTransition implements Dump {
return a;
}
- Animation loadCustomActivityAnimation(int animAttr, boolean enter, WindowContainer container) {
+ CustomAppTransition getCustomAppTransition(int animAttr, WindowContainer container) {
ActivityRecord customAnimationSource = container.asActivityRecord();
if (customAnimationSource == null) {
return null;
@@ -927,31 +930,28 @@ public class AppTransition implements Dump {
return null;
}
}
- final CustomAppTransition custom;
switch (animAttr) {
case WindowAnimation_activityOpenEnterAnimation:
case WindowAnimation_activityOpenExitAnimation:
- custom = customAnimationSource.getCustomAnimation(true /* open */);
- break;
+ return customAnimationSource.getCustomAnimation(true /* open */);
case WindowAnimation_activityCloseEnterAnimation:
case WindowAnimation_activityCloseExitAnimation:
- custom = customAnimationSource.getCustomAnimation(false /* open */);
- break;
- default:
- return null;
- }
- if (custom != null) {
- final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
- customAnimationSource.packageName, enter
- ? custom.mEnterAnim : custom.mExitAnim);
- if (a != null && custom.mBackgroundColor != 0) {
- a.setBackdropColor(custom.mBackgroundColor);
- a.setShowBackdrop(true);
- }
- return a;
+ return customAnimationSource.getCustomAnimation(false /* open */);
}
return null;
}
+ private Animation loadCustomActivityAnimation(@NonNull CustomAppTransition custom,
+ boolean enter, WindowContainer container) {
+ final ActivityRecord customAnimationSource = container.asActivityRecord();
+ final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
+ customAnimationSource.packageName, enter
+ ? custom.mEnterAnim : custom.mExitAnim);
+ if (a != null && custom.mBackgroundColor != 0) {
+ a.setBackdropColor(custom.mBackgroundColor);
+ a.setShowBackdrop(true);
+ }
+ return a;
+ }
int getAppRootTaskClipMode() {
return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH)
diff --git a/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
index 24ed42cab63a..24e48517f280 100644
--- a/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
@@ -50,7 +50,7 @@ import java.util.Arrays;
import java.util.Collection;
@RunWith(Enclosed.class)
-public class DeviceRouteControllerTest {
+public class LegacyDeviceRouteControllerTest {
private static final String DEFAULT_ROUTE_NAME = "default_route";
private static final String DEFAULT_HEADPHONES_NAME = "headphone";
@@ -97,7 +97,7 @@ public class DeviceRouteControllerTest {
// Default route should be initialized even when AudioService returns null.
when(mAudioService.startWatchingRoutes(any())).thenReturn(null);
- DeviceRouteController deviceRouteController = new DeviceRouteController(
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
@@ -122,7 +122,7 @@ public class DeviceRouteControllerTest {
AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
when(mAudioService.startWatchingRoutes(any())).thenReturn(fakeBluetoothAudioRoute);
- DeviceRouteController deviceRouteController = new DeviceRouteController(
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
@@ -236,7 +236,7 @@ public class DeviceRouteControllerTest {
when(mResources.getText(mExpectedRouteNameResource))
.thenReturn(mExpectedRouteNameValue);
- DeviceRouteController deviceRouteController = new DeviceRouteController(
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
@@ -269,7 +269,7 @@ public class DeviceRouteControllerTest {
@Captor
private ArgumentCaptor<IAudioRoutesObserver.Stub> mAudioRoutesObserverCaptor;
- private DeviceRouteController mDeviceRouteController;
+ private LegacyDeviceRouteController mDeviceRouteController;
private IAudioRoutesObserver.Stub mAudioRoutesObserver;
@Before
@@ -287,7 +287,7 @@ public class DeviceRouteControllerTest {
when(mAudioService.startWatchingRoutes(mAudioRoutesObserverCaptor.capture()))
.thenReturn(audioRoutesInfo);
- mDeviceRouteController = new DeviceRouteController(
+ mDeviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 6f37e601abce..ce076217f37b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -24,6 +24,8 @@ import static android.service.notification.NotificationListenerService.META_DATA
import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -1201,28 +1203,11 @@ public class ManagedServicesTest extends UiServiceTestCase {
mIpm, approvalLevel);
loadXml(service);
- List<String> allowedPackagesForUser0 = new ArrayList<>();
- allowedPackagesForUser0.add("this.is.a.package.name");
- allowedPackagesForUser0.add("another.package");
- allowedPackagesForUser0.add("secondary");
-
- List<String> actual = service.getAllowedPackages(0);
- assertEquals(3, actual.size());
- for (String pkg : allowedPackagesForUser0) {
- assertTrue(actual.contains(pkg));
- }
-
- List<String> allowedPackagesForUser10 = new ArrayList<>();
- allowedPackagesForUser10.add("this.is.another.package");
- allowedPackagesForUser10.add("package");
- allowedPackagesForUser10.add("this.is.another.package");
- allowedPackagesForUser10.add("component");
-
- actual = service.getAllowedPackages(10);
- assertEquals(4, actual.size());
- for (String pkg : allowedPackagesForUser10) {
- assertTrue(actual.contains(pkg));
- }
+ assertThat(service.getAllowedPackages(0)).containsExactly("this.is.a.package.name",
+ "another.package", "secondary");
+ assertThat(service.getAllowedPackages(10)).containsExactly("this.is.another.package",
+ "package", "this.is.another.package", "component");
+ assertThat(service.getAllowedPackages(999)).isEmpty();
}
}
@@ -1263,31 +1248,6 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
@Test
- public void testGetAllowedPackages() throws Exception {
- ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
- mIpm, APPROVAL_BY_COMPONENT);
- loadXml(service);
- service.mApprovalLevel = APPROVAL_BY_PACKAGE;
- loadXml(service);
-
- List<String> allowedPackages = new ArrayList<>();
- allowedPackages.add("this.is.a.package.name");
- allowedPackages.add("another.package");
- allowedPackages.add("secondary");
- allowedPackages.add("this.is.another.package");
- allowedPackages.add("package");
- allowedPackages.add("component");
- allowedPackages.add("bananas!");
- allowedPackages.add("non.user.set.package");
-
- Set<String> actual = service.getAllowedPackages();
- assertEquals(allowedPackages.size(), actual.size());
- for (String pkg : allowedPackages) {
- assertTrue(actual.contains(pkg));
- }
- }
-
- @Test
public void testOnUserRemoved() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index f08d0f5f71a4..354420f46c2f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -29,6 +29,7 @@ import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
import static android.app.Notification.FLAG_NO_CLEAR;
import static android.app.Notification.FLAG_ONGOING_EVENT;
import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
+import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
@@ -50,7 +51,6 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
-
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -237,6 +237,7 @@ import com.android.server.utils.quota.MultiRateLimiter;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
+import com.google.android.collect.Lists;
import com.google.common.collect.ImmutableList;
import org.junit.After;
@@ -245,10 +246,13 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.BufferedInputStream;
@@ -440,6 +444,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
mContext.addMockSystemService(NotificationManager.class, mMockNm);
+ doNothing().when(mContext).sendBroadcastAsUser(any(), any());
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
setDpmAppOppsExemptFromDismissal(false);
@@ -7828,6 +7833,75 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void onZenModeChanged_sendsBroadcasts() throws Exception {
+ when(mAmi.getCurrentUserId()).thenReturn(100);
+ when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102});
+ when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() {
+ @Override
+ public List<String> answer(InvocationOnMock invocation) {
+ int userId = invocation.getArgument(0);
+ switch (userId) {
+ case 100:
+ return Lists.newArrayList("a", "b", "c");
+ case 101:
+ return Lists.newArrayList();
+ case 102:
+ return Lists.newArrayList("b");
+ default:
+ throw new IllegalArgumentException(
+ "Why would you ask for packages of userId " + userId + "?");
+ }
+ }
+ });
+
+ mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
+ "testing!");
+ waitForIdle();
+
+ InOrder inOrder = inOrder(mContext);
+ // Verify broadcasts for registered receivers
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+ new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+ new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+ new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null));
+
+ // Verify broadcast for packages that manage DND.
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
+ }
+
+ private static Intent eqIntent(Intent wanted) {
+ return ArgumentMatchers.argThat(
+ new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Intent argument) {
+ return wanted.filterEquals(argument)
+ && wanted.getFlags() == argument.getFlags();
+ }
+
+ @Override
+ public String toString() {
+ return wanted.toString();
+ }
+ });
+ }
+
+ @Test
public void testAreNotificationsEnabledForPackage() throws Exception {
mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
mUid);