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

Commit 9bad0e94 authored by jiabin's avatar jiabin Committed by Jiabin Huang
Browse files

Tracking legacy remote submix active or not in RecordingActivityMonitor.

When enabling Live Caption, remote submix device will be set as fixed
and full volume device in audio service. In that case, volume control
for remote submix will not be forwarded anymore. However, it is expected
to have volume control when the device is on chromecast mirror mode.
To solve the problem, tracking legacy remote submix device is active or
not in RecordingActivityMonitor. When legacy remote submix device is
active, remote submix will not be treated as fixed/full volume device.
In audio policy manager, the remote submix that is used by dynamic
policy will still be fixed volume device.

Bug: 144063329
Test: repo steps in bug
Change-Id: I1cb83c17f34e636763bb989e37ac8e021217cc39
Merged-In: I1cb83c17f34e636763bb989e37ac8e021217cc39
parent 24ebb4f9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -708,6 +708,8 @@ public class AudioSystem
        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);
    }

    public static final String LEGACY_REMOTE_SUBMIX_ADDRESS = "0";

    // device states, must match AudioSystem::device_connection_state
    @UnsupportedAppUsage
    public static final int DEVICE_STATE_UNAVAILABLE = 0;
+32 −15
Original line number Diff line number Diff line
@@ -776,6 +776,8 @@ public class AudioService extends IAudioService.Stub

        mDeviceBroker = new AudioDeviceBroker(mContext, this);

        mRecordMonitor = new RecordingActivityMonitor(mContext);

        // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
        // array initialized by updateStreamVolumeAlias()
        updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
@@ -797,8 +799,6 @@ public class AudioService extends IAudioService.Stub

        mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);

        mRecordMonitor = new RecordingActivityMonitor(mContext);

        readAndSetLowRamDevice();

        mIsCallScreeningModeSupported = AudioSystem.isCallScreeningModeSupported();
@@ -1981,8 +1981,7 @@ public class AudioService extends IAudioService.Stub
        }

        flags &= ~AudioManager.FLAG_FIXED_VOLUME;
        if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
                mFixedVolumeDevices.contains(device)) {
        if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {
            flags |= AudioManager.FLAG_FIXED_VOLUME;

            // Always toggle between max safe volume and 0 for fixed volume devices where safe
@@ -2059,7 +2058,7 @@ public class AudioService extends IAudioService.Stub
                    !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
                Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
                mVolumeController.postDisplaySafeVolumeWarning(flags);
            } else if (!mFullVolumeDevices.contains(device)
            } else if (!isFullVolumeDevice(device)
                    && (streamState.adjustIndex(direction * step, device, caller)
                            || streamState.mIsMuted)) {
                // Post message to set system volume (it in turn will post a
@@ -2121,7 +2120,7 @@ public class AudioService extends IAudioService.Stub
                    if (mHdmiCecSink
                            && streamTypeAlias == AudioSystem.STREAM_MUSIC
                            // vol change on a full volume device
                            && mFullVolumeDevices.contains(device)) {
                            && isFullVolumeDevice(device)) {
                        int keyCode = KeyEvent.KEYCODE_UNKNOWN;
                        switch (direction) {
                            case AudioManager.ADJUST_RAISE:
@@ -2590,8 +2589,7 @@ public class AudioService extends IAudioService.Stub
            }

            flags &= ~AudioManager.FLAG_FIXED_VOLUME;
            if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
                    mFixedVolumeDevices.contains(device)) {
            if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {
                flags |= AudioManager.FLAG_FIXED_VOLUME;

                // volume is either 0 or max allowed for fixed volume devices
@@ -2780,7 +2778,7 @@ public class AudioService extends IAudioService.Stub

        if (streamType == AudioSystem.STREAM_MUSIC) {
            flags = updateFlagsForTvPlatform(flags);
            if (mFullVolumeDevices.contains(device)) {
            if (isFullVolumeDevice(device)) {
                flags &= ~AudioManager.FLAG_SHOW_UI;
            }
        }
@@ -2826,7 +2824,7 @@ public class AudioService extends IAudioService.Stub
                                    int device,
                                    boolean force,
                                    String caller) {
        if (mFullVolumeDevices.contains(device)) {
        if (isFullVolumeDevice(device)) {
            return;
        }
        VolumeStreamState streamState = mStreamStates[streamType];
@@ -3036,7 +3034,7 @@ public class AudioService extends IAudioService.Stub
                index = 0;
            }
            if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
                    mFixedVolumeDevices.contains(device)) {
                    isFixedVolumeDevice(device)) {
                index = mStreamStates[streamType].getMaxIndex();
            }
            return (index + 5) / 10;
@@ -5165,7 +5163,7 @@ public class AudioService extends IAudioService.Stub
            } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                    && isAvrcpAbsVolSupported) {
                index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
            } else if (mFullVolumeDevices.contains(device)) {
            } else if (isFullVolumeDevice(device)) {
                index = (mIndexMax + 5)/10;
            } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                index = (mIndexMax + 5)/10;
@@ -5188,7 +5186,7 @@ public class AudioService extends IAudioService.Stub
                        } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                                && isAvrcpAbsVolSupported) {
                            index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
                        } else if (mFullVolumeDevices.contains(device)) {
                        } else if (isFullVolumeDevice(device)) {
                            index = (mIndexMax + 5)/10;
                        } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                            index = (mIndexMax + 5)/10;
@@ -5389,8 +5387,8 @@ public class AudioService extends IAudioService.Stub
                    for (int i = 0; i < mIndexMap.size(); i++) {
                        int device = mIndexMap.keyAt(i);
                        int index = mIndexMap.valueAt(i);
                        if (mFullVolumeDevices.contains(device)
                                || (mFixedVolumeDevices.contains(device) && index != 0)) {
                        if (isFullVolumeDevice(device)
                                || (isFixedVolumeDevice(device) && index != 0)) {
                            mIndexMap.put(device, mIndexMax);
                        }
                        applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
@@ -8235,4 +8233,23 @@ public class AudioService extends IAudioService.Stub
            new HashMap<IBinder, AudioPolicyProxy>();
    @GuardedBy("mAudioPolicies")
    private int mAudioPolicyCounter = 0;

    //======================
    // Helper functions for full and fixed volume device
    //======================
    private boolean isFixedVolumeDevice(int deviceType) {
        if (deviceType == AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
                && mRecordMonitor.isLegacyRemoteSubmixActive()) {
            return false;
        }
        return mFixedVolumeDevices.contains(deviceType);
    }

    private boolean isFullVolumeDevice(int deviceType) {
        if (deviceType == AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
                && mRecordMonitor.isLegacyRemoteSubmixActive()) {
            return false;
        }
        return mFullVolumeDevices.contains(deviceType);
    }
}
+33 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.audio;

import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecordingConfiguration;
@@ -35,6 +36,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Class to receive and dispatch updates from AudioSystem about recording configurations.
@@ -49,6 +52,16 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
    // playback configurations that do not contain uid/package name information.
    private boolean mHasPublicClients = false;


    // When legacy remote submix device is active, remote submix device should not be fixed and
    // full volume device. When legacy remote submix device is active, there will be a recording
    // activity using device with type as {@link AudioSystem.DEVICE_OUT_REMOTE_SUBMIX} and address
    // as {@link AudioSystem.LEGACY_REMOTE_SUBMIX_ADDRESS}. Cache riid of legacy remote submix
    // since remote submix state is not cached in mRecordStates.
    private AtomicInteger mLegacyRemoteSubmixRiid =
            new AtomicInteger(AudioManager.RECORD_RIID_INVALID);
    private AtomicBoolean mLegacyRemoteSubmixActive = new AtomicBoolean(false);

    static final class RecordingState {
        private final int mRiid;
        private final RecorderDeathHandler mDeathHandler;
@@ -137,6 +150,16 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
        final AudioRecordingConfiguration config = createRecordingConfiguration(
                uid, session, source, recordingInfo,
                portId, silenced, activeSource, clientEffects, effects);
        if (source == MediaRecorder.AudioSource.REMOTE_SUBMIX) {
            final AudioDeviceInfo device = config.getAudioDevice();
            if (AudioSystem.LEGACY_REMOTE_SUBMIX_ADDRESS.equals(device.getAddress())) {
                mLegacyRemoteSubmixRiid.set(riid);
                if (event == AudioManager.RECORD_CONFIG_EVENT_START
                        || event == AudioManager.RECORD_CONFIG_EVENT_UPDATE) {
                    mLegacyRemoteSubmixActive.set(true);
                }
            }
        }
        if (MediaRecorder.isSystemOnlyAudioSource(source)) {
            // still want to log event, it just won't appear in recording configurations;
            sEventLogger.log(new RecordingEvent(event, riid, config).printLog(TAG));
@@ -170,6 +193,9 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
     * Receive an event from the client about a tracked recorder
     */
    public void recorderEvent(int riid, int event) {
        if (mLegacyRemoteSubmixRiid.get() == riid) {
            mLegacyRemoteSubmixActive.set(event == AudioManager.RECORDER_STATE_STARTED);
        }
        int configEvent = event == AudioManager.RECORDER_STATE_STARTED
                ? AudioManager.RECORD_CONFIG_EVENT_START :
                event == AudioManager.RECORDER_STATE_STOPPED
@@ -322,6 +348,13 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
        return configs;
    }

    /**
     * Return true if legacy remote submix device is active. Otherwise, return false.
     */
    boolean isLegacyRemoteSubmixActive() {
        return mLegacyRemoteSubmixActive.get();
    }

    /**
     * Create a recording configuration from the provided parameters
     * @param uid