summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Laurent <elaurent@google.com> 2022-12-05 14:38:28 +0100
committer Eric Laurent <elaurent@google.com> 2022-12-05 18:12:04 +0100
commit7b4c0d0205eb129ee18afb894f9bbdfa8d53751f (patch)
tree37ce9c862ff1b33484edb428475095db709d14ef
parent329f5f38580e38ea4b4d8c212c3a375349851cc2 (diff)
AudioService: pause media playback when registered policy client dies
Broadcast becoming noisy intent when the client of a registered dynamic audio policy dies with an active media playback rerouted from a remote submix device. This happens for instance when Android Auto app dies with an active projection session. This makes the user experience similar to what happens when disconnecting the Bluetooth A2DP connection from a car kit. Bug: 186581483 Test: manual test with head unit simulator Change-Id: I2d98894145ff87e4711897fd09797c8e941fd0f1
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java22
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java21
2 files changed, 43 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 8aa898edff9a..519429fa5ac0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -10913,6 +10913,21 @@ public class AudioService extends IAudioService.Stub
}
/**
+ * Called by an AudioPolicyProxy when the client dies.
+ * Checks if an active playback for media use case is currently routed to one of the
+ * remote submix devices owned by this dynamic policy and broadcasts a becoming noisy
+ * intend in this case.
+ * @param addresses list of remote submix device addresses to check.
+ */
+ private void onPolicyClientDeath(List<String> addresses) {
+ for (String address : addresses) {
+ if (mPlaybackMonitor.hasActiveMediaPlaybackOnSubmixWithAddress(address)) {
+ mDeviceBroker.postBroadcastBecomingNoisy();
+ return;
+ }
+ }
+ }
+ /**
* Apps with MODIFY_AUDIO_ROUTING can register any policy.
* Apps with an audio capable MediaProjection are allowed to register a RENDER|LOOPBACK policy
* as those policy do not modify the audio routing.
@@ -11622,6 +11637,13 @@ public class AudioService extends IAudioService.Stub
public void binderDied() {
mDynPolicyLogger.enqueue((new EventLogger.StringEvent("AudioPolicy "
+ mPolicyCallback.asBinder() + " died").printLog(TAG)));
+
+ List<String> addresses = new ArrayList<>();
+ for (AudioMix mix : mMixes) {
+ addresses.add(mix.getRegistration());
+ }
+ onPolicyClientDeath(addresses);
+
release();
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 0bc4b20b4643..89dfc1714b4c 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -32,6 +32,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioPlaybackConfiguration.PlayerMuteEvent;
@@ -542,6 +543,26 @@ public final class PlaybackActivityMonitor
return false;
}
+ /**
+ * Return true if an active playback for media use case is currently routed to
+ * a remote submix device with the supplied address.
+ * @param address
+ */
+ public boolean hasActiveMediaPlaybackOnSubmixWithAddress(@NonNull String address) {
+ synchronized (mPlayerLock) {
+ for (AudioPlaybackConfiguration apc : mPlayers.values()) {
+ AudioDeviceInfo device = apc.getAudioDeviceInfo();
+ if (apc.getAudioAttributes().getUsage() == AudioAttributes.USAGE_MEDIA
+ && apc.isActive() && device != null
+ && device.getInternalType() == AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
+ && address.equals(device.getAddress())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
protected void dump(PrintWriter pw) {
// players
pw.println("\nPlaybackActivityMonitor dump time: "