Loading media/java/android/media/AudioManager.java +12 −2 Original line number Diff line number Diff line Loading @@ -3730,7 +3730,12 @@ public class AudioManager { @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) public void setA2dpSuspended(boolean enable) { AudioSystem.setParameters("A2dpSuspended=" + enable); final IAudioService service = getService(); try { service.setA2dpSuspended(enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Loading @@ -3743,7 +3748,12 @@ public class AudioManager { @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) public void setLeAudioSuspended(boolean enable) { AudioSystem.setParameters("LeAudioSuspended=" + enable); final IAudioService service = getService(); try { service.setLeAudioSuspended(enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Loading media/java/android/media/AudioSystem.java +63 −0 Original line number Diff line number Diff line Loading @@ -1237,6 +1237,9 @@ public class AudioSystem public static final Set<Integer> DEVICE_IN_ALL_SCO_SET; /** @hide */ public static final Set<Integer> DEVICE_IN_ALL_USB_SET; /** @hide */ public static final Set<Integer> DEVICE_IN_ALL_BLE_SET; static { DEVICE_IN_ALL_SET = new HashSet<>(); DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION); Loading Loading @@ -1276,6 +1279,66 @@ public class AudioSystem DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY); DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE); DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET); DEVICE_IN_ALL_BLE_SET = new HashSet<>(); DEVICE_IN_ALL_BLE_SET.add(DEVICE_IN_BLE_HEADSET); } /** @hide */ public static boolean isBluetoothDevice(int deviceType) { return isBluetoothA2dpOutDevice(deviceType) || isBluetoothScoDevice(deviceType) || isBluetoothLeDevice(deviceType); } /** @hide */ public static boolean isBluetoothOutDevice(int deviceType) { return isBluetoothA2dpOutDevice(deviceType) || isBluetoothScoOutDevice(deviceType) || isBluetoothLeOutDevice(deviceType); } /** @hide */ public static boolean isBluetoothInDevice(int deviceType) { return isBluetoothScoInDevice(deviceType) || isBluetoothLeInDevice(deviceType); } /** @hide */ public static boolean isBluetoothA2dpOutDevice(int deviceType) { return DEVICE_OUT_ALL_A2DP_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothScoOutDevice(int deviceType) { return DEVICE_OUT_ALL_SCO_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothScoInDevice(int deviceType) { return DEVICE_IN_ALL_SCO_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothScoDevice(int deviceType) { return isBluetoothScoOutDevice(deviceType) || isBluetoothScoInDevice(deviceType); } /** @hide */ public static boolean isBluetoothLeOutDevice(int deviceType) { return DEVICE_OUT_ALL_BLE_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothLeInDevice(int deviceType) { return DEVICE_IN_ALL_BLE_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothLeDevice(int deviceType) { return isBluetoothLeOutDevice(deviceType) || isBluetoothLeInDevice(deviceType); } /** @hide */ Loading media/java/android/media/IAudioService.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,12 @@ interface IAudioService { void setBluetoothScoOn(boolean on); @EnforcePermission("BLUETOOTH_STACK") void setA2dpSuspended(boolean on); @EnforcePermission("BLUETOOTH_STACK") void setLeAudioSuspended(boolean enable); boolean isBluetoothScoOn(); void setBluetoothA2dpOn(boolean on); Loading services/core/java/com/android/server/audio/AudioDeviceBroker.java +200 −34 Original line number Diff line number Diff line Loading @@ -87,14 +87,14 @@ import java.util.concurrent.atomic.AtomicBoolean; private final @NonNull Context mContext; /** ID for Communication strategy retrieved form audio policy manager */ private int mCommunicationStrategyId = -1; /*package*/ int mCommunicationStrategyId = -1; /** ID for Accessibility strategy retrieved form audio policy manager */ private int mAccessibilityStrategyId = -1; /** Active communication device reported by audio policy manager */ private AudioDeviceInfo mActiveCommunicationDevice; /*package*/ AudioDeviceInfo mActiveCommunicationDevice; /** Last preferred device set for communication strategy */ private AudioDeviceAttributes mPreferredCommunicationDevice; Loading Loading @@ -204,6 +204,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private void init() { setupMessaging(mContext); initAudioHalBluetoothState(); initRoutingStrategyIds(); mPreferredCommunicationDevice = null; updateActiveCommunicationDevice(); Loading Loading @@ -749,6 +750,19 @@ import java.util.concurrent.atomic.AtomicBoolean; mIsLeOutput = false; } BtDeviceInfo(@NonNull BtDeviceInfo src, int state) { mDevice = src.mDevice; mState = state; mProfile = src.mProfile; mSupprNoisy = src.mSupprNoisy; mVolume = src.mVolume; mIsLeOutput = src.mIsLeOutput; mEventSource = src.mEventSource; mAudioSystemDevice = src.mAudioSystemDevice; mMusicDevice = src.mMusicDevice; mCodec = src.mCodec; } // redefine equality op so we can match messages intended for this device @Override public boolean equals(Object o) { Loading Loading @@ -815,7 +829,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * @param info struct with the (dis)connection information */ /*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) { if (data.mInfo.getProfile() == BluetoothProfile.A2DP && data.mPreviousDevice != null if (data.mPreviousDevice != null && data.mPreviousDevice.equals(data.mNewDevice)) { final String name = TextUtils.emptyIfNull(data.mNewDevice.getName()); new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR Loading @@ -824,7 +838,8 @@ import java.util.concurrent.atomic.AtomicBoolean; .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile()) .record(); synchronized (mDeviceStateLock) { postBluetoothA2dpDeviceConfigChange(data.mNewDevice); postBluetoothDeviceConfigChange(createBtDeviceInfo(data, data.mNewDevice, BluetoothProfile.STATE_CONNECTED)); } } else { synchronized (mDeviceStateLock) { Loading @@ -845,10 +860,100 @@ import java.util.concurrent.atomic.AtomicBoolean; } } /** * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn(). */ // Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn(). @GuardedBy("mDeviceStateLock") private boolean mBluetoothScoOn; // value of BT_SCO parameter currently applied to audio HAL. @GuardedBy("mDeviceStateLock") private boolean mBluetoothScoOnApplied; // A2DP suspend state requested by AudioManager.setA2dpSuspended() API. @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpSuspendedExt; // A2DP suspend state requested by AudioDeviceInventory. @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpSuspendedInt; // value of BT_A2dpSuspendedSCO parameter currently applied to audio HAL. @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpSuspendedApplied; // LE Audio suspend state requested by AudioManager.setLeAudioSuspended() API. @GuardedBy("mDeviceStateLock") private boolean mBluetoothLeSuspendedExt; // LE Audio suspend state requested by AudioDeviceInventory. @GuardedBy("mDeviceStateLock") private boolean mBluetoothLeSuspendedInt; // value of LeAudioSuspended parameter currently applied to audio HAL. @GuardedBy("mDeviceStateLock") private boolean mBluetoothLeSuspendedApplied; private void initAudioHalBluetoothState() { mBluetoothScoOnApplied = false; AudioSystem.setParameters("BT_SCO=off"); mBluetoothA2dpSuspendedApplied = false; AudioSystem.setParameters("A2dpSuspended=false"); mBluetoothLeSuspendedApplied = false; AudioSystem.setParameters("LeAudioSuspended=false"); } @GuardedBy("mDeviceStateLock") private void updateAudioHalBluetoothState() { if (mBluetoothScoOn != mBluetoothScoOnApplied) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothScoOn: " + mBluetoothScoOn + ", mBluetoothScoOnApplied: " + mBluetoothScoOnApplied); } if (mBluetoothScoOn) { if (!mBluetoothA2dpSuspendedApplied) { AudioSystem.setParameters("A2dpSuspended=true"); mBluetoothA2dpSuspendedApplied = true; } if (!mBluetoothLeSuspendedApplied) { AudioSystem.setParameters("LeAudioSuspended=true"); mBluetoothLeSuspendedApplied = true; } AudioSystem.setParameters("BT_SCO=on"); } else { AudioSystem.setParameters("BT_SCO=off"); } mBluetoothScoOnApplied = mBluetoothScoOn; } if (!mBluetoothScoOnApplied) { if ((mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt) != mBluetoothA2dpSuspendedApplied) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt + ", mBluetoothA2dpSuspendedApplied: " + mBluetoothA2dpSuspendedApplied); } mBluetoothA2dpSuspendedApplied = mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt; if (mBluetoothA2dpSuspendedApplied) { AudioSystem.setParameters("A2dpSuspended=true"); } else { AudioSystem.setParameters("A2dpSuspended=false"); } } if ((mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt) != mBluetoothLeSuspendedApplied) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothLeSuspendedExt: " + mBluetoothLeSuspendedExt + ", mBluetoothLeSuspendedInt: " + mBluetoothLeSuspendedInt + ", mBluetoothLeSuspendedApplied: " + mBluetoothLeSuspendedApplied); } mBluetoothLeSuspendedApplied = mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt; if (mBluetoothLeSuspendedApplied) { AudioSystem.setParameters("LeAudioSuspended=true"); } else { AudioSystem.setParameters("LeAudioSuspended=false"); } } } } /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Loading @@ -856,10 +961,67 @@ import java.util.concurrent.atomic.AtomicBoolean; } synchronized (mDeviceStateLock) { mBluetoothScoOn = on; updateAudioHalBluetoothState(); postUpdateCommunicationRouteClient(eventSource); } } /*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: " + enable + ", internal: " + internal + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt + ", mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt); } synchronized (mDeviceStateLock) { if (internal) { mBluetoothA2dpSuspendedInt = enable; } else { mBluetoothA2dpSuspendedExt = enable; } updateAudioHalBluetoothState(); } } /*package*/ void clearA2dpSuspended() { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "clearA2dpSuspended"); } synchronized (mDeviceStateLock) { mBluetoothA2dpSuspendedInt = false; mBluetoothA2dpSuspendedExt = false; updateAudioHalBluetoothState(); } } /*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: " + enable + ", internal: " + internal + ", mBluetoothLeSuspendedInt: " + mBluetoothA2dpSuspendedInt + ", mBluetoothLeSuspendedExt: " + mBluetoothA2dpSuspendedExt); } synchronized (mDeviceStateLock) { if (internal) { mBluetoothLeSuspendedInt = enable; } else { mBluetoothLeSuspendedExt = enable; } updateAudioHalBluetoothState(); } } /*package*/ void clearLeAudioSuspended() { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "clearLeAudioSuspended"); } synchronized (mDeviceStateLock) { mBluetoothLeSuspendedInt = false; mBluetoothLeSuspendedExt = false; updateAudioHalBluetoothState(); } } /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { synchronized (mDeviceStateLock) { return mDeviceInventory.startWatchingRoutes(observer); Loading Loading @@ -902,8 +1064,8 @@ import java.util.concurrent.atomic.AtomicBoolean; new AudioModeInfo(mode, pid, uid)); } /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device); /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) { sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info); } /*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode, Loading Loading @@ -1160,6 +1322,10 @@ import java.util.concurrent.atomic.AtomicBoolean; sendIMsgNoDelay(MSG_I_SCO_AUDIO_STATE_CHANGED, SENDMSG_QUEUE, state); } /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) { sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice); } /*package*/ static final class CommunicationDeviceInfo { final @NonNull IBinder mCb; // Identifies the requesting client for death handler final int mPid; // Requester process ID Loading Loading @@ -1235,9 +1401,11 @@ import java.util.concurrent.atomic.AtomicBoolean; } } /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect) { /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect, @Nullable BluetoothDevice btDevice) { synchronized (mDeviceStateLock) { return mDeviceInventory.handleDeviceConnection(attributes, connect, false /*for test*/); return mDeviceInventory.handleDeviceConnection( attributes, connect, false /*for test*/, btDevice); } } Loading Loading @@ -1478,13 +1646,10 @@ import java.util.concurrent.atomic.AtomicBoolean; (String) msg.obj, msg.arg1); } break; case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: synchronized (mDeviceStateLock) { final int a2dpCodec = mBtHelper.getA2dpCodec(btDevice); mDeviceInventory.onBluetoothA2dpDeviceConfigChange( new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), BtHelper.EVENT_DEVICE_CONFIG_CHANGE); mDeviceInventory.onBluetoothDeviceConfigChange( (BtDeviceInfo) msg.obj, BtHelper.EVENT_DEVICE_CONFIG_CHANGE); } break; case MSG_BROADCAST_AUDIO_BECOMING_NOISY: Loading Loading @@ -1642,6 +1807,10 @@ import java.util.concurrent.atomic.AtomicBoolean; final int capturePreset = msg.arg1; mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); } break; case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: { final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; BtHelper.onNotifyPreferredAudioProfileApplied(btDevice); } break; default: Log.wtf(TAG, "Invalid message " + msg.what); } Loading Loading @@ -1677,7 +1846,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_IL_BTA2DP_TIMEOUT = 10; // process change of A2DP device configuration, obj is BluetoothDevice private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11; private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; private static final int MSG_REPORT_NEW_ROUTES = 13; Loading Loading @@ -1717,13 +1886,15 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48; private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49; private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 50; private static boolean isMessageHandledUnderWakelock(int msgId) { switch(msgId) { case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: case MSG_L_SET_BT_ACTIVE_DEVICE: case MSG_IL_BTA2DP_TIMEOUT: case MSG_IL_BTLEAUDIO_TIMEOUT: case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: case MSG_TOGGLE_HDMI: case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: Loading Loading @@ -1815,7 +1986,7 @@ import java.util.concurrent.atomic.AtomicBoolean; case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: case MSG_IL_BTA2DP_TIMEOUT: case MSG_IL_BTLEAUDIO_TIMEOUT: case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: if (sLastDeviceConnectMsgTime >= time) { // add a little delay to make sure messages are ordered as expected time = sLastDeviceConnectMsgTime + 30; Loading @@ -1835,7 +2006,7 @@ import java.util.concurrent.atomic.AtomicBoolean; static { MESSAGES_MUTE_MUSIC = new HashSet<>(); MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE); MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT); MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE); } Loading @@ -1856,7 +2027,7 @@ import java.util.concurrent.atomic.AtomicBoolean; // Do not mute on bluetooth event if music is playing on a wired headset. if ((message == MSG_L_SET_BT_ACTIVE_DEVICE || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT || message == MSG_L_A2DP_DEVICE_CONFIG_CHANGE) || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE) && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET, mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) { Loading Loading @@ -1992,27 +2163,22 @@ import java.util.concurrent.atomic.AtomicBoolean; "updateCommunicationRoute, preferredCommunicationDevice: " + preferredCommunicationDevice + " eventSource: " + eventSource))); if (preferredCommunicationDevice == null || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { AudioSystem.setParameters("BT_SCO=off"); } else { AudioSystem.setParameters("BT_SCO=on"); } if (preferredCommunicationDevice == null) { AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); if (defaultDevice != null) { setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mCommunicationStrategyId, Arrays.asList(defaultDevice)); setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mAccessibilityStrategyId, Arrays.asList(defaultDevice)); } else { removePreferredDevicesForStrategySync(mCommunicationStrategyId); removePreferredDevicesForStrategySync(mAccessibilityStrategyId); mDeviceInventory.removePreferredDevicesForStrategy(mCommunicationStrategyId); mDeviceInventory.removePreferredDevicesForStrategy(mAccessibilityStrategyId); } mDeviceInventory.applyConnectedDevicesRoles(); } else { setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice)); } onUpdatePhoneStrategyDevice(preferredCommunicationDevice); Loading services/core/java/com/android/server/audio/AudioDeviceInventory.java +675 −136 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
media/java/android/media/AudioManager.java +12 −2 Original line number Diff line number Diff line Loading @@ -3730,7 +3730,12 @@ public class AudioManager { @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) public void setA2dpSuspended(boolean enable) { AudioSystem.setParameters("A2dpSuspended=" + enable); final IAudioService service = getService(); try { service.setA2dpSuspended(enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Loading @@ -3743,7 +3748,12 @@ public class AudioManager { @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.BLUETOOTH_STACK) public void setLeAudioSuspended(boolean enable) { AudioSystem.setParameters("LeAudioSuspended=" + enable); final IAudioService service = getService(); try { service.setLeAudioSuspended(enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Loading
media/java/android/media/AudioSystem.java +63 −0 Original line number Diff line number Diff line Loading @@ -1237,6 +1237,9 @@ public class AudioSystem public static final Set<Integer> DEVICE_IN_ALL_SCO_SET; /** @hide */ public static final Set<Integer> DEVICE_IN_ALL_USB_SET; /** @hide */ public static final Set<Integer> DEVICE_IN_ALL_BLE_SET; static { DEVICE_IN_ALL_SET = new HashSet<>(); DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION); Loading Loading @@ -1276,6 +1279,66 @@ public class AudioSystem DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY); DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE); DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET); DEVICE_IN_ALL_BLE_SET = new HashSet<>(); DEVICE_IN_ALL_BLE_SET.add(DEVICE_IN_BLE_HEADSET); } /** @hide */ public static boolean isBluetoothDevice(int deviceType) { return isBluetoothA2dpOutDevice(deviceType) || isBluetoothScoDevice(deviceType) || isBluetoothLeDevice(deviceType); } /** @hide */ public static boolean isBluetoothOutDevice(int deviceType) { return isBluetoothA2dpOutDevice(deviceType) || isBluetoothScoOutDevice(deviceType) || isBluetoothLeOutDevice(deviceType); } /** @hide */ public static boolean isBluetoothInDevice(int deviceType) { return isBluetoothScoInDevice(deviceType) || isBluetoothLeInDevice(deviceType); } /** @hide */ public static boolean isBluetoothA2dpOutDevice(int deviceType) { return DEVICE_OUT_ALL_A2DP_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothScoOutDevice(int deviceType) { return DEVICE_OUT_ALL_SCO_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothScoInDevice(int deviceType) { return DEVICE_IN_ALL_SCO_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothScoDevice(int deviceType) { return isBluetoothScoOutDevice(deviceType) || isBluetoothScoInDevice(deviceType); } /** @hide */ public static boolean isBluetoothLeOutDevice(int deviceType) { return DEVICE_OUT_ALL_BLE_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothLeInDevice(int deviceType) { return DEVICE_IN_ALL_BLE_SET.contains(deviceType); } /** @hide */ public static boolean isBluetoothLeDevice(int deviceType) { return isBluetoothLeOutDevice(deviceType) || isBluetoothLeInDevice(deviceType); } /** @hide */ Loading
media/java/android/media/IAudioService.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,12 @@ interface IAudioService { void setBluetoothScoOn(boolean on); @EnforcePermission("BLUETOOTH_STACK") void setA2dpSuspended(boolean on); @EnforcePermission("BLUETOOTH_STACK") void setLeAudioSuspended(boolean enable); boolean isBluetoothScoOn(); void setBluetoothA2dpOn(boolean on); Loading
services/core/java/com/android/server/audio/AudioDeviceBroker.java +200 −34 Original line number Diff line number Diff line Loading @@ -87,14 +87,14 @@ import java.util.concurrent.atomic.AtomicBoolean; private final @NonNull Context mContext; /** ID for Communication strategy retrieved form audio policy manager */ private int mCommunicationStrategyId = -1; /*package*/ int mCommunicationStrategyId = -1; /** ID for Accessibility strategy retrieved form audio policy manager */ private int mAccessibilityStrategyId = -1; /** Active communication device reported by audio policy manager */ private AudioDeviceInfo mActiveCommunicationDevice; /*package*/ AudioDeviceInfo mActiveCommunicationDevice; /** Last preferred device set for communication strategy */ private AudioDeviceAttributes mPreferredCommunicationDevice; Loading Loading @@ -204,6 +204,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private void init() { setupMessaging(mContext); initAudioHalBluetoothState(); initRoutingStrategyIds(); mPreferredCommunicationDevice = null; updateActiveCommunicationDevice(); Loading Loading @@ -749,6 +750,19 @@ import java.util.concurrent.atomic.AtomicBoolean; mIsLeOutput = false; } BtDeviceInfo(@NonNull BtDeviceInfo src, int state) { mDevice = src.mDevice; mState = state; mProfile = src.mProfile; mSupprNoisy = src.mSupprNoisy; mVolume = src.mVolume; mIsLeOutput = src.mIsLeOutput; mEventSource = src.mEventSource; mAudioSystemDevice = src.mAudioSystemDevice; mMusicDevice = src.mMusicDevice; mCodec = src.mCodec; } // redefine equality op so we can match messages intended for this device @Override public boolean equals(Object o) { Loading Loading @@ -815,7 +829,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * @param info struct with the (dis)connection information */ /*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) { if (data.mInfo.getProfile() == BluetoothProfile.A2DP && data.mPreviousDevice != null if (data.mPreviousDevice != null && data.mPreviousDevice.equals(data.mNewDevice)) { final String name = TextUtils.emptyIfNull(data.mNewDevice.getName()); new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR Loading @@ -824,7 +838,8 @@ import java.util.concurrent.atomic.AtomicBoolean; .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile()) .record(); synchronized (mDeviceStateLock) { postBluetoothA2dpDeviceConfigChange(data.mNewDevice); postBluetoothDeviceConfigChange(createBtDeviceInfo(data, data.mNewDevice, BluetoothProfile.STATE_CONNECTED)); } } else { synchronized (mDeviceStateLock) { Loading @@ -845,10 +860,100 @@ import java.util.concurrent.atomic.AtomicBoolean; } } /** * Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn(). */ // Current Bluetooth SCO audio active state indicated by BtHelper via setBluetoothScoOn(). @GuardedBy("mDeviceStateLock") private boolean mBluetoothScoOn; // value of BT_SCO parameter currently applied to audio HAL. @GuardedBy("mDeviceStateLock") private boolean mBluetoothScoOnApplied; // A2DP suspend state requested by AudioManager.setA2dpSuspended() API. @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpSuspendedExt; // A2DP suspend state requested by AudioDeviceInventory. @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpSuspendedInt; // value of BT_A2dpSuspendedSCO parameter currently applied to audio HAL. @GuardedBy("mDeviceStateLock") private boolean mBluetoothA2dpSuspendedApplied; // LE Audio suspend state requested by AudioManager.setLeAudioSuspended() API. @GuardedBy("mDeviceStateLock") private boolean mBluetoothLeSuspendedExt; // LE Audio suspend state requested by AudioDeviceInventory. @GuardedBy("mDeviceStateLock") private boolean mBluetoothLeSuspendedInt; // value of LeAudioSuspended parameter currently applied to audio HAL. @GuardedBy("mDeviceStateLock") private boolean mBluetoothLeSuspendedApplied; private void initAudioHalBluetoothState() { mBluetoothScoOnApplied = false; AudioSystem.setParameters("BT_SCO=off"); mBluetoothA2dpSuspendedApplied = false; AudioSystem.setParameters("A2dpSuspended=false"); mBluetoothLeSuspendedApplied = false; AudioSystem.setParameters("LeAudioSuspended=false"); } @GuardedBy("mDeviceStateLock") private void updateAudioHalBluetoothState() { if (mBluetoothScoOn != mBluetoothScoOnApplied) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothScoOn: " + mBluetoothScoOn + ", mBluetoothScoOnApplied: " + mBluetoothScoOnApplied); } if (mBluetoothScoOn) { if (!mBluetoothA2dpSuspendedApplied) { AudioSystem.setParameters("A2dpSuspended=true"); mBluetoothA2dpSuspendedApplied = true; } if (!mBluetoothLeSuspendedApplied) { AudioSystem.setParameters("LeAudioSuspended=true"); mBluetoothLeSuspendedApplied = true; } AudioSystem.setParameters("BT_SCO=on"); } else { AudioSystem.setParameters("BT_SCO=off"); } mBluetoothScoOnApplied = mBluetoothScoOn; } if (!mBluetoothScoOnApplied) { if ((mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt) != mBluetoothA2dpSuspendedApplied) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt + ", mBluetoothA2dpSuspendedApplied: " + mBluetoothA2dpSuspendedApplied); } mBluetoothA2dpSuspendedApplied = mBluetoothA2dpSuspendedExt || mBluetoothA2dpSuspendedInt; if (mBluetoothA2dpSuspendedApplied) { AudioSystem.setParameters("A2dpSuspended=true"); } else { AudioSystem.setParameters("A2dpSuspended=false"); } } if ((mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt) != mBluetoothLeSuspendedApplied) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "updateAudioHalBluetoothState() mBluetoothLeSuspendedExt: " + mBluetoothLeSuspendedExt + ", mBluetoothLeSuspendedInt: " + mBluetoothLeSuspendedInt + ", mBluetoothLeSuspendedApplied: " + mBluetoothLeSuspendedApplied); } mBluetoothLeSuspendedApplied = mBluetoothLeSuspendedExt || mBluetoothLeSuspendedInt; if (mBluetoothLeSuspendedApplied) { AudioSystem.setParameters("LeAudioSuspended=true"); } else { AudioSystem.setParameters("LeAudioSuspended=false"); } } } } /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Loading @@ -856,10 +961,67 @@ import java.util.concurrent.atomic.AtomicBoolean; } synchronized (mDeviceStateLock) { mBluetoothScoOn = on; updateAudioHalBluetoothState(); postUpdateCommunicationRouteClient(eventSource); } } /*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: " + enable + ", internal: " + internal + ", mBluetoothA2dpSuspendedInt: " + mBluetoothA2dpSuspendedInt + ", mBluetoothA2dpSuspendedExt: " + mBluetoothA2dpSuspendedExt); } synchronized (mDeviceStateLock) { if (internal) { mBluetoothA2dpSuspendedInt = enable; } else { mBluetoothA2dpSuspendedExt = enable; } updateAudioHalBluetoothState(); } } /*package*/ void clearA2dpSuspended() { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "clearA2dpSuspended"); } synchronized (mDeviceStateLock) { mBluetoothA2dpSuspendedInt = false; mBluetoothA2dpSuspendedExt = false; updateAudioHalBluetoothState(); } } /*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: " + enable + ", internal: " + internal + ", mBluetoothLeSuspendedInt: " + mBluetoothA2dpSuspendedInt + ", mBluetoothLeSuspendedExt: " + mBluetoothA2dpSuspendedExt); } synchronized (mDeviceStateLock) { if (internal) { mBluetoothLeSuspendedInt = enable; } else { mBluetoothLeSuspendedExt = enable; } updateAudioHalBluetoothState(); } } /*package*/ void clearLeAudioSuspended() { if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "clearLeAudioSuspended"); } synchronized (mDeviceStateLock) { mBluetoothLeSuspendedInt = false; mBluetoothLeSuspendedExt = false; updateAudioHalBluetoothState(); } } /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { synchronized (mDeviceStateLock) { return mDeviceInventory.startWatchingRoutes(observer); Loading Loading @@ -902,8 +1064,8 @@ import java.util.concurrent.atomic.AtomicBoolean; new AudioModeInfo(mode, pid, uid)); } /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device); /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) { sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info); } /*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode, Loading Loading @@ -1160,6 +1322,10 @@ import java.util.concurrent.atomic.AtomicBoolean; sendIMsgNoDelay(MSG_I_SCO_AUDIO_STATE_CHANGED, SENDMSG_QUEUE, state); } /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) { sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice); } /*package*/ static final class CommunicationDeviceInfo { final @NonNull IBinder mCb; // Identifies the requesting client for death handler final int mPid; // Requester process ID Loading Loading @@ -1235,9 +1401,11 @@ import java.util.concurrent.atomic.AtomicBoolean; } } /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect) { /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect, @Nullable BluetoothDevice btDevice) { synchronized (mDeviceStateLock) { return mDeviceInventory.handleDeviceConnection(attributes, connect, false /*for test*/); return mDeviceInventory.handleDeviceConnection( attributes, connect, false /*for test*/, btDevice); } } Loading Loading @@ -1478,13 +1646,10 @@ import java.util.concurrent.atomic.AtomicBoolean; (String) msg.obj, msg.arg1); } break; case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: synchronized (mDeviceStateLock) { final int a2dpCodec = mBtHelper.getA2dpCodec(btDevice); mDeviceInventory.onBluetoothA2dpDeviceConfigChange( new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec), BtHelper.EVENT_DEVICE_CONFIG_CHANGE); mDeviceInventory.onBluetoothDeviceConfigChange( (BtDeviceInfo) msg.obj, BtHelper.EVENT_DEVICE_CONFIG_CHANGE); } break; case MSG_BROADCAST_AUDIO_BECOMING_NOISY: Loading Loading @@ -1642,6 +1807,10 @@ import java.util.concurrent.atomic.AtomicBoolean; final int capturePreset = msg.arg1; mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); } break; case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: { final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; BtHelper.onNotifyPreferredAudioProfileApplied(btDevice); } break; default: Log.wtf(TAG, "Invalid message " + msg.what); } Loading Loading @@ -1677,7 +1846,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_IL_BTA2DP_TIMEOUT = 10; // process change of A2DP device configuration, obj is BluetoothDevice private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11; private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; private static final int MSG_REPORT_NEW_ROUTES = 13; Loading Loading @@ -1717,13 +1886,15 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48; private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49; private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 50; private static boolean isMessageHandledUnderWakelock(int msgId) { switch(msgId) { case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: case MSG_L_SET_BT_ACTIVE_DEVICE: case MSG_IL_BTA2DP_TIMEOUT: case MSG_IL_BTLEAUDIO_TIMEOUT: case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: case MSG_TOGGLE_HDMI: case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: Loading Loading @@ -1815,7 +1986,7 @@ import java.util.concurrent.atomic.AtomicBoolean; case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: case MSG_IL_BTA2DP_TIMEOUT: case MSG_IL_BTLEAUDIO_TIMEOUT: case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: if (sLastDeviceConnectMsgTime >= time) { // add a little delay to make sure messages are ordered as expected time = sLastDeviceConnectMsgTime + 30; Loading @@ -1835,7 +2006,7 @@ import java.util.concurrent.atomic.AtomicBoolean; static { MESSAGES_MUTE_MUSIC = new HashSet<>(); MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE); MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE); MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT); MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE); } Loading @@ -1856,7 +2027,7 @@ import java.util.concurrent.atomic.AtomicBoolean; // Do not mute on bluetooth event if music is playing on a wired headset. if ((message == MSG_L_SET_BT_ACTIVE_DEVICE || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT || message == MSG_L_A2DP_DEVICE_CONFIG_CHANGE) || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE) && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET, mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) { Loading Loading @@ -1992,27 +2163,22 @@ import java.util.concurrent.atomic.AtomicBoolean; "updateCommunicationRoute, preferredCommunicationDevice: " + preferredCommunicationDevice + " eventSource: " + eventSource))); if (preferredCommunicationDevice == null || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { AudioSystem.setParameters("BT_SCO=off"); } else { AudioSystem.setParameters("BT_SCO=on"); } if (preferredCommunicationDevice == null) { AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); if (defaultDevice != null) { setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mCommunicationStrategyId, Arrays.asList(defaultDevice)); setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mAccessibilityStrategyId, Arrays.asList(defaultDevice)); } else { removePreferredDevicesForStrategySync(mCommunicationStrategyId); removePreferredDevicesForStrategySync(mAccessibilityStrategyId); mDeviceInventory.removePreferredDevicesForStrategy(mCommunicationStrategyId); mDeviceInventory.removePreferredDevicesForStrategy(mAccessibilityStrategyId); } mDeviceInventory.applyConnectedDevicesRoles(); } else { setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); setPreferredDevicesForStrategySync( mDeviceInventory.setPreferredDevicesForStrategy( mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice)); } onUpdatePhoneStrategyDevice(preferredCommunicationDevice); Loading
services/core/java/com/android/server/audio/AudioDeviceInventory.java +675 −136 File changed.Preview size limit exceeded, changes collapsed. Show changes