Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b4c0d02 authored by Eric Laurent's avatar Eric Laurent
Browse files

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
parent 329f5f38
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -10912,6 +10912,21 @@ public class AudioService extends IAudioService.Stub
        return regId;
    }
    /**
     * 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
@@ -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();
        }
+21 −0
Original line number Diff line number Diff line
@@ -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: "