Loading media/java/android/media/AudioSystem.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading services/core/java/com/android/server/audio/AudioService.java +32 −15 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -797,8 +799,6 @@ public class AudioService extends IAudioService.Stub mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor); mRecordMonitor = new RecordingActivityMonitor(mContext); readAndSetLowRamDevice(); mIsCallScreeningModeSupported = AudioSystem.isCallScreeningModeSupported(); Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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: Loading Loading @@ -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 Loading Loading @@ -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; } } Loading Loading @@ -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]; Loading Loading @@ -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; Loading Loading @@ -5166,7 +5164,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; Loading @@ -5189,7 +5187,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; Loading Loading @@ -5390,8 +5388,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); Loading Loading @@ -8236,4 +8234,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); } } services/core/java/com/android/server/audio/RecordingActivityMonitor.java +33 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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; Loading Loading @@ -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)); Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading
media/java/android/media/AudioSystem.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
services/core/java/com/android/server/audio/AudioService.java +32 −15 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -797,8 +799,6 @@ public class AudioService extends IAudioService.Stub mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor); mRecordMonitor = new RecordingActivityMonitor(mContext); readAndSetLowRamDevice(); mIsCallScreeningModeSupported = AudioSystem.isCallScreeningModeSupported(); Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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: Loading Loading @@ -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 Loading Loading @@ -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; } } Loading Loading @@ -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]; Loading Loading @@ -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; Loading Loading @@ -5166,7 +5164,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; Loading @@ -5189,7 +5187,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; Loading Loading @@ -5390,8 +5388,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); Loading Loading @@ -8236,4 +8234,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); } }
services/core/java/com/android/server/audio/RecordingActivityMonitor.java +33 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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; Loading Loading @@ -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)); Loading Loading @@ -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 Loading Loading @@ -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 Loading