Loading services/core/java/com/android/server/audio/AudioDeviceBroker.java +11 −6 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private final @NonNull AudioService mAudioService; private final @NonNull Context mContext; private final @NonNull AudioSystemAdapter mAudioSystem; /** ID for Communication strategy retrieved form audio policy manager */ private int mCommunicationStrategyId = -1; Loading Loading @@ -156,12 +157,14 @@ import java.util.concurrent.atomic.AtomicBoolean; public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L; //------------------------------------------------------------------- /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) { /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, @NonNull AudioSystemAdapter audioSystem) { mContext = context; mAudioService = service; mBtHelper = new BtHelper(this); mDeviceInventory = new AudioDeviceInventory(this); mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext); mAudioSystem = audioSystem; init(); } Loading @@ -170,12 +173,14 @@ import java.util.concurrent.atomic.AtomicBoolean; * in system_server */ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, @NonNull AudioDeviceInventory mockDeviceInventory, @NonNull SystemServerAdapter mockSystemServer) { @NonNull SystemServerAdapter mockSystemServer, @NonNull AudioSystemAdapter audioSystem) { mContext = context; mAudioService = service; mBtHelper = new BtHelper(this); mDeviceInventory = mockDeviceInventory; mSystemServer = mockSystemServer; mAudioSystem = audioSystem; init(); } Loading Loading @@ -450,7 +455,7 @@ import java.util.concurrent.atomic.AtomicBoolean; AudioAttributes attr = AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType( AudioSystem.STREAM_VOICE_CALL); List<AudioDeviceAttributes> devices = AudioSystem.getDevicesForAttributes( List<AudioDeviceAttributes> devices = mAudioSystem.getDevicesForAttributes( attr, false /* forVolume */); if (devices.isEmpty()) { if (mAudioService.isPlatformVoice()) { Loading Loading @@ -1225,7 +1230,7 @@ import java.util.concurrent.atomic.AtomicBoolean; Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<" + fromA2dp + ">, eventSource<" + eventSource + ">)"); } AudioSystem.setForceUse(useCase, config); mAudioSystem.setForceUse(useCase, config); } private void onSendBecomingNoisyIntent() { Loading Loading @@ -1863,9 +1868,9 @@ import java.util.concurrent.atomic.AtomicBoolean; if (preferredCommunicationDevice == null || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { AudioSystem.setParameters("BT_SCO=off"); mAudioSystem.setParameters("BT_SCO=off"); } else { AudioSystem.setParameters("BT_SCO=on"); mAudioSystem.setParameters("BT_SCO=on"); } if (preferredCommunicationDevice == null) { AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); Loading services/core/java/com/android/server/audio/AudioService.java +32 −13 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.audio.AudioServiceEvents.DeviceVolumeEvent; import com.android.server.audio.AudioServiceEvents.PhoneStateEvent; import com.android.server.audio.AudioServiceEvents.VolChangedBroadcastEvent; import com.android.server.audio.AudioServiceEvents.VolumeEvent; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal.UserRestrictionsListener; Loading Loading @@ -1205,7 +1206,7 @@ public class AudioService extends IAudioService.Stub mUseFixedVolume = mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); mDeviceBroker = new AudioDeviceBroker(mContext, this); mDeviceBroker = new AudioDeviceBroker(mContext, this, mAudioSystem); mRecordMonitor = new RecordingActivityMonitor(mContext); mRecordMonitor.registerRecordingCallback(mVoiceRecordingActivityMonitor, true); Loading Loading @@ -1637,7 +1638,7 @@ public class AudioService extends IAudioService.Stub synchronized (mSettingsLock) { final int forDock = mDockAudioMediaEnabled ? AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE; AudioSystem.FORCE_DIGITAL_DOCK : AudioSystem.FORCE_NONE; mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied"); sendEncodedSurroundMode(mContentResolver, "onAudioServerDied"); sendEnabledSurroundFormats(mContentResolver, true); Loading Loading @@ -2258,9 +2259,10 @@ public class AudioService extends IAudioService.Stub SENDMSG_QUEUE, AudioSystem.FOR_DOCK, mDockAudioMediaEnabled ? AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, AudioSystem.FORCE_DIGITAL_DOCK : AudioSystem.FORCE_NONE, new String("readDockAudioSettings"), 0); } Loading Loading @@ -3741,19 +3743,30 @@ public class AudioService extends IAudioService.Stub Objects.requireNonNull(ada); Objects.requireNonNull(callingPackage); AudioService.sVolumeLogger.loglogi("setDeviceVolume" + " from:" + callingPackage + " " + vi + " " + ada, TAG); if (!vi.hasStreamType()) { Log.e(TAG, "Unsupported non-stream type based VolumeInfo", new Exception()); return; } int index = vi.getVolumeIndex(); if (index == VolumeInfo.INDEX_NOT_SET && !vi.hasMuteCommand()) { throw new IllegalArgumentException( "changing device volume requires a volume index or mute command"); } // force a cache clear to force reevaluating stream type to audio device selection // that can interfere with the sending of the VOLUME_CHANGED_ACTION intent // TODO change cache management to not rely only on invalidation, but on "do not trust" // moments when routing is in flux. mAudioSystem.clearRoutingCache(); // log the current device that will be used when evaluating the sending of the // VOLUME_CHANGED_ACTION intent to see if the current device is the one being modified final int currDev = getDeviceForStream(vi.getStreamType()); AudioService.sVolumeLogger.log(new DeviceVolumeEvent(vi.getStreamType(), index, ada, currDev, callingPackage)); // TODO handle unmuting of current audio device // if a stream is not muted but the VolumeInfo is for muting, set the volume index // for the device to min volume Loading Loading @@ -3837,11 +3850,11 @@ public class AudioService extends IAudioService.Stub return; } final AudioEventLogger.Event event = (device == null) ? new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType, index/*val1*/, flags/*val2*/, callingPackage) : new DeviceVolumeEvent(streamType, index, device, callingPackage); sVolumeLogger.log(event); if (device == null) { // call was already logged in setDeviceVolume() sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType, index/*val1*/, flags/*val2*/, callingPackage)); } setStreamVolume(streamType, index, flags, device, callingPackage, callingPackage, attributionTag, Binder.getCallingUid(), callingOrSelfHasAudioSettingsPermission()); Loading Loading @@ -4242,8 +4255,12 @@ public class AudioService extends IAudioService.Stub maybeSendSystemAudioStatusCommand(false); } } if (ada == null) { // only non-null when coming here from setDeviceVolume // TODO change test to check early if device is current device or not sendVolumeUpdate(streamType, oldIndex, index, flags, device); } } Loading Loading @@ -7982,6 +7999,8 @@ public class AudioService extends IAudioService.Stub mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS, mStreamVolumeAlias[mStreamType]); AudioService.sVolumeLogger.log(new VolChangedBroadcastEvent( mStreamType, mStreamVolumeAlias[mStreamType], index)); sendBroadcastToAll(mVolumeChanged); } } Loading Loading @@ -10155,7 +10174,7 @@ public class AudioService extends IAudioService.Stub static final int LOG_NB_EVENTS_PHONE_STATE = 20; static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 50; static final int LOG_NB_EVENTS_FORCE_USE = 20; static final int LOG_NB_EVENTS_VOLUME = 40; static final int LOG_NB_EVENTS_VOLUME = 100; static final int LOG_NB_EVENTS_DYN_POLICY = 10; static final int LOG_NB_EVENTS_SPATIAL = 30; Loading services/core/java/com/android/server/audio/AudioServiceEvents.java +27 −2 Original line number Diff line number Diff line Loading @@ -147,19 +147,42 @@ public class AudioServiceEvents { } } static final class VolChangedBroadcastEvent extends AudioEventLogger.Event { final int mStreamType; final int mAliasStreamType; final int mIndex; VolChangedBroadcastEvent(int stream, int alias, int index) { mStreamType = stream; mAliasStreamType = alias; mIndex = index; } @Override public String eventToString() { return new StringBuilder("sending VOLUME_CHANGED stream:") .append(AudioSystem.streamToString(mStreamType)) .append(" index:").append(mIndex) .append(" alias:").append(AudioSystem.streamToString(mAliasStreamType)) .toString(); } } static final class DeviceVolumeEvent extends AudioEventLogger.Event { final int mStream; final int mVolIndex; final String mDeviceNativeType; final String mDeviceAddress; final String mCaller; final int mDeviceForStream; DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device, String callingPackage) { int deviceForStream, String callingPackage) { mStream = streamType; mVolIndex = index; mDeviceNativeType = "0x" + Integer.toHexString(device.getInternalType()); mDeviceAddress = device.getAddress(); mDeviceForStream = deviceForStream; mCaller = callingPackage; // log metrics new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME_EVENT) Loading @@ -180,7 +203,9 @@ public class AudioServiceEvents { .append(" index:").append(mVolIndex) .append(" device:").append(mDeviceNativeType) .append(" addr:").append(mDeviceAddress) .append(") from ").append(mCaller).toString(); .append(") from ").append(mCaller) .append(" currDevForStream:Ox").append(Integer.toHexString(mDeviceForStream)) .toString(); } } Loading services/core/java/com/android/server/audio/AudioSystemAdapter.java +8 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,13 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, } } public void clearRoutingCache() { if (DEBUG_CACHE) { Log.d(TAG, "---- routing cache clear (from java) ----------"); } invalidateRoutingCache(); } /** * Implementation of AudioSystem.VolumeRangeInitRequestCallback */ Loading Loading @@ -337,6 +344,7 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, * @return */ public int setParameters(String keyValuePairs) { invalidateRoutingCache(); return AudioSystem.setParameters(keyValuePairs); } Loading services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ public class AudioDeviceBrokerTest { mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem)); mSpySystemServer = spy(new NoOpSystemServerAdapter()); mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory, mSpySystemServer); mSpySystemServer, mSpyAudioSystem); mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); Loading Loading
services/core/java/com/android/server/audio/AudioDeviceBroker.java +11 −6 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private final @NonNull AudioService mAudioService; private final @NonNull Context mContext; private final @NonNull AudioSystemAdapter mAudioSystem; /** ID for Communication strategy retrieved form audio policy manager */ private int mCommunicationStrategyId = -1; Loading Loading @@ -156,12 +157,14 @@ import java.util.concurrent.atomic.AtomicBoolean; public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L; //------------------------------------------------------------------- /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) { /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, @NonNull AudioSystemAdapter audioSystem) { mContext = context; mAudioService = service; mBtHelper = new BtHelper(this); mDeviceInventory = new AudioDeviceInventory(this); mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext); mAudioSystem = audioSystem; init(); } Loading @@ -170,12 +173,14 @@ import java.util.concurrent.atomic.AtomicBoolean; * in system_server */ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service, @NonNull AudioDeviceInventory mockDeviceInventory, @NonNull SystemServerAdapter mockSystemServer) { @NonNull SystemServerAdapter mockSystemServer, @NonNull AudioSystemAdapter audioSystem) { mContext = context; mAudioService = service; mBtHelper = new BtHelper(this); mDeviceInventory = mockDeviceInventory; mSystemServer = mockSystemServer; mAudioSystem = audioSystem; init(); } Loading Loading @@ -450,7 +455,7 @@ import java.util.concurrent.atomic.AtomicBoolean; AudioAttributes attr = AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType( AudioSystem.STREAM_VOICE_CALL); List<AudioDeviceAttributes> devices = AudioSystem.getDevicesForAttributes( List<AudioDeviceAttributes> devices = mAudioSystem.getDevicesForAttributes( attr, false /* forVolume */); if (devices.isEmpty()) { if (mAudioService.isPlatformVoice()) { Loading Loading @@ -1225,7 +1230,7 @@ import java.util.concurrent.atomic.AtomicBoolean; Log.v(TAG, "onSetForceUse(useCase<" + useCase + ">, config<" + config + ">, fromA2dp<" + fromA2dp + ">, eventSource<" + eventSource + ">)"); } AudioSystem.setForceUse(useCase, config); mAudioSystem.setForceUse(useCase, config); } private void onSendBecomingNoisyIntent() { Loading Loading @@ -1863,9 +1868,9 @@ import java.util.concurrent.atomic.AtomicBoolean; if (preferredCommunicationDevice == null || preferredCommunicationDevice.getType() != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { AudioSystem.setParameters("BT_SCO=off"); mAudioSystem.setParameters("BT_SCO=off"); } else { AudioSystem.setParameters("BT_SCO=on"); mAudioSystem.setParameters("BT_SCO=on"); } if (preferredCommunicationDevice == null) { AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); Loading
services/core/java/com/android/server/audio/AudioService.java +32 −13 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.audio.AudioServiceEvents.DeviceVolumeEvent; import com.android.server.audio.AudioServiceEvents.PhoneStateEvent; import com.android.server.audio.AudioServiceEvents.VolChangedBroadcastEvent; import com.android.server.audio.AudioServiceEvents.VolumeEvent; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal.UserRestrictionsListener; Loading Loading @@ -1205,7 +1206,7 @@ public class AudioService extends IAudioService.Stub mUseFixedVolume = mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); mDeviceBroker = new AudioDeviceBroker(mContext, this); mDeviceBroker = new AudioDeviceBroker(mContext, this, mAudioSystem); mRecordMonitor = new RecordingActivityMonitor(mContext); mRecordMonitor.registerRecordingCallback(mVoiceRecordingActivityMonitor, true); Loading Loading @@ -1637,7 +1638,7 @@ public class AudioService extends IAudioService.Stub synchronized (mSettingsLock) { final int forDock = mDockAudioMediaEnabled ? AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE; AudioSystem.FORCE_DIGITAL_DOCK : AudioSystem.FORCE_NONE; mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied"); sendEncodedSurroundMode(mContentResolver, "onAudioServerDied"); sendEnabledSurroundFormats(mContentResolver, true); Loading Loading @@ -2258,9 +2259,10 @@ public class AudioService extends IAudioService.Stub SENDMSG_QUEUE, AudioSystem.FOR_DOCK, mDockAudioMediaEnabled ? AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, AudioSystem.FORCE_DIGITAL_DOCK : AudioSystem.FORCE_NONE, new String("readDockAudioSettings"), 0); } Loading Loading @@ -3741,19 +3743,30 @@ public class AudioService extends IAudioService.Stub Objects.requireNonNull(ada); Objects.requireNonNull(callingPackage); AudioService.sVolumeLogger.loglogi("setDeviceVolume" + " from:" + callingPackage + " " + vi + " " + ada, TAG); if (!vi.hasStreamType()) { Log.e(TAG, "Unsupported non-stream type based VolumeInfo", new Exception()); return; } int index = vi.getVolumeIndex(); if (index == VolumeInfo.INDEX_NOT_SET && !vi.hasMuteCommand()) { throw new IllegalArgumentException( "changing device volume requires a volume index or mute command"); } // force a cache clear to force reevaluating stream type to audio device selection // that can interfere with the sending of the VOLUME_CHANGED_ACTION intent // TODO change cache management to not rely only on invalidation, but on "do not trust" // moments when routing is in flux. mAudioSystem.clearRoutingCache(); // log the current device that will be used when evaluating the sending of the // VOLUME_CHANGED_ACTION intent to see if the current device is the one being modified final int currDev = getDeviceForStream(vi.getStreamType()); AudioService.sVolumeLogger.log(new DeviceVolumeEvent(vi.getStreamType(), index, ada, currDev, callingPackage)); // TODO handle unmuting of current audio device // if a stream is not muted but the VolumeInfo is for muting, set the volume index // for the device to min volume Loading Loading @@ -3837,11 +3850,11 @@ public class AudioService extends IAudioService.Stub return; } final AudioEventLogger.Event event = (device == null) ? new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType, index/*val1*/, flags/*val2*/, callingPackage) : new DeviceVolumeEvent(streamType, index, device, callingPackage); sVolumeLogger.log(event); if (device == null) { // call was already logged in setDeviceVolume() sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType, index/*val1*/, flags/*val2*/, callingPackage)); } setStreamVolume(streamType, index, flags, device, callingPackage, callingPackage, attributionTag, Binder.getCallingUid(), callingOrSelfHasAudioSettingsPermission()); Loading Loading @@ -4242,8 +4255,12 @@ public class AudioService extends IAudioService.Stub maybeSendSystemAudioStatusCommand(false); } } if (ada == null) { // only non-null when coming here from setDeviceVolume // TODO change test to check early if device is current device or not sendVolumeUpdate(streamType, oldIndex, index, flags, device); } } Loading Loading @@ -7982,6 +7999,8 @@ public class AudioService extends IAudioService.Stub mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS, mStreamVolumeAlias[mStreamType]); AudioService.sVolumeLogger.log(new VolChangedBroadcastEvent( mStreamType, mStreamVolumeAlias[mStreamType], index)); sendBroadcastToAll(mVolumeChanged); } } Loading Loading @@ -10155,7 +10174,7 @@ public class AudioService extends IAudioService.Stub static final int LOG_NB_EVENTS_PHONE_STATE = 20; static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 50; static final int LOG_NB_EVENTS_FORCE_USE = 20; static final int LOG_NB_EVENTS_VOLUME = 40; static final int LOG_NB_EVENTS_VOLUME = 100; static final int LOG_NB_EVENTS_DYN_POLICY = 10; static final int LOG_NB_EVENTS_SPATIAL = 30; Loading
services/core/java/com/android/server/audio/AudioServiceEvents.java +27 −2 Original line number Diff line number Diff line Loading @@ -147,19 +147,42 @@ public class AudioServiceEvents { } } static final class VolChangedBroadcastEvent extends AudioEventLogger.Event { final int mStreamType; final int mAliasStreamType; final int mIndex; VolChangedBroadcastEvent(int stream, int alias, int index) { mStreamType = stream; mAliasStreamType = alias; mIndex = index; } @Override public String eventToString() { return new StringBuilder("sending VOLUME_CHANGED stream:") .append(AudioSystem.streamToString(mStreamType)) .append(" index:").append(mIndex) .append(" alias:").append(AudioSystem.streamToString(mAliasStreamType)) .toString(); } } static final class DeviceVolumeEvent extends AudioEventLogger.Event { final int mStream; final int mVolIndex; final String mDeviceNativeType; final String mDeviceAddress; final String mCaller; final int mDeviceForStream; DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device, String callingPackage) { int deviceForStream, String callingPackage) { mStream = streamType; mVolIndex = index; mDeviceNativeType = "0x" + Integer.toHexString(device.getInternalType()); mDeviceAddress = device.getAddress(); mDeviceForStream = deviceForStream; mCaller = callingPackage; // log metrics new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME_EVENT) Loading @@ -180,7 +203,9 @@ public class AudioServiceEvents { .append(" index:").append(mVolIndex) .append(" device:").append(mDeviceNativeType) .append(" addr:").append(mDeviceAddress) .append(") from ").append(mCaller).toString(); .append(") from ").append(mCaller) .append(" currDevForStream:Ox").append(Integer.toHexString(mDeviceForStream)) .toString(); } } Loading
services/core/java/com/android/server/audio/AudioSystemAdapter.java +8 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,13 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, } } public void clearRoutingCache() { if (DEBUG_CACHE) { Log.d(TAG, "---- routing cache clear (from java) ----------"); } invalidateRoutingCache(); } /** * Implementation of AudioSystem.VolumeRangeInitRequestCallback */ Loading Loading @@ -337,6 +344,7 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback, * @return */ public int setParameters(String keyValuePairs) { invalidateRoutingCache(); return AudioSystem.setParameters(keyValuePairs); } Loading
services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ public class AudioDeviceBrokerTest { mSpyDevInventory = spy(new AudioDeviceInventory(mSpyAudioSystem)); mSpySystemServer = spy(new NoOpSystemServerAdapter()); mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory, mSpySystemServer); mSpySystemServer, mSpyAudioSystem); mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); Loading