diff options
author | Eric Laurent <elaurent@google.com> | 2021-03-30 17:28:53 +0200 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2021-03-30 17:28:53 +0200 |
commit | 8553181dec49a2a2fb7ff5778b34ca2ec950cf7c (patch) | |
tree | 74206a35f9d4ac0a153b0ec10b6a32cdb41ebb3c | |
parent | 9cc70b16daa5de3b44e9e22190ffa0cd0e3607b3 (diff) | |
download | MusicFX-8553181dec49a2a2fb7ff5778b34ca2ec950cf7c.tar.gz |
Remove need for bluetooth permissionandroid12-dev
Use AudioManager.AudioPlaybackCallback to detect if
music playback happens on headset or not.
This is more reliable than the old method based on deprecated
APIs and does not require the BLUETOOTH premission.
Bug: 183500722
Test: make and play music with Youtube Music
Change-Id: I9c29ea428599face23cd7b78e2d90efaade2db79
-rw-r--r-- | AndroidManifest.xml | 3 | ||||
-rw-r--r-- | src/com/android/musicfx/ActivityMusic.java | 102 |
2 files changed, 59 insertions, 46 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 19a09be..4642aa7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -23,8 +23,7 @@ android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> - <uses-permission - android:name="android.permission.BLUETOOTH"></uses-permission> + <application android:icon="@drawable/icon" android:label="@string/app_name" diff --git a/src/com/android/musicfx/ActivityMusic.java b/src/com/android/musicfx/ActivityMusic.java index 3fb58d4..5222b48 100644 --- a/src/com/android/musicfx/ActivityMusic.java +++ b/src/com/android/musicfx/ActivityMusic.java @@ -30,8 +30,12 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.IntentFilter; +import android.media.AudioAttributes; +import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioManager; +import android.media.AudioManager.AudioPlaybackCallback; +import android.media.AudioPlaybackConfiguration; import android.media.audiofx.AudioEffect; import android.media.audiofx.AudioEffect.Descriptor; import android.media.audiofx.Virtualizer; @@ -61,8 +65,11 @@ import android.widget.Toast; import java.util.Formatter; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.UUID; /** @@ -199,42 +206,56 @@ public class ActivityMusic extends Activity implements OnSeekBarChangeListener { */ private int mAudioSession = AudioEffect.ERROR_BAD_VALUE; - // Broadcast receiver to handle wired and Bluetooth A2dp headset events - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + // Audio Playback monitoring Callback to determine if a headset is used for music playback + private final AudioPlaybackCallback mMyAudioPlaybackCallback = new AudioPlaybackCallback() { @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - final boolean isHeadsetOnPrev = mIsHeadsetOn; - final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - if (action.equals(Intent.ACTION_HEADSET_PLUG)) { - mIsHeadsetOn = (intent.getIntExtra("state", 0) == 1) - || audioManager.isBluetoothA2dpOn(); - } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { - final int deviceClass = ((BluetoothDevice) intent - .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).getBluetoothClass() - .getDeviceClass(); - if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) - || (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { - mIsHeadsetOn = true; - } - } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { - mIsHeadsetOn = audioManager.isBluetoothA2dpOn() || audioManager.isWiredHeadsetOn(); - } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { - final int deviceClass = ((BluetoothDevice) intent - .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).getBluetoothClass() - .getDeviceClass(); - if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) - || (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { - mIsHeadsetOn = audioManager.isWiredHeadsetOn(); - } - } - if (isHeadsetOnPrev != mIsHeadsetOn) { + public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) { + boolean isHeadsetOn = isHeadsetUsedForMedia(configs); + if (isHeadsetOn != mIsHeadsetOn) { + mIsHeadsetOn = isHeadsetOn; updateUIHeadset(); } } }; - /* + private static boolean isConfigForMedia(AudioPlaybackConfiguration apc) { + AudioAttributes attr = apc.getAudioAttributes(); + if (attr.getUsage() == AudioAttributes.USAGE_MEDIA + || attr.getUsage() == AudioAttributes.USAGE_GAME + || attr.getUsage() == AudioAttributes.USAGE_UNKNOWN) { + return true; + } + return false; + } + + public static final Set<Integer> HEADSET_DEVICE_TYPES = new HashSet<>(); + static { + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_WIRED_HEADSET); + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_WIRED_HEADPHONES); + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP); + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_BLUETOOTH_SCO); + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_USB_HEADSET); + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_HEARING_AID); + HEADSET_DEVICE_TYPES.add(AudioDeviceInfo.TYPE_BLE_HEADSET); + } + + private static boolean isConfigForHeadset(AudioPlaybackConfiguration apc) { + AudioDeviceInfo device = apc.getAudioDeviceInfo(); + if (device == null) { + return false; + } + return HEADSET_DEVICE_TYPES.contains(device.getType()); + } + + private static boolean isHeadsetUsedForMedia(List<AudioPlaybackConfiguration> configs) { + for (AudioPlaybackConfiguration config : configs) { + if (config.isActive() && isConfigForMedia(config) && isConfigForHeadset(config)) { + return true; + } + } + return false; + } + /* * Declares and initializes all objects and widgets in the layouts and the CheckBox and SeekBar * onchange methods on creation. * @@ -483,7 +504,6 @@ public class ActivityMusic extends Activity implements OnSeekBarChangeListener { ActionBar.LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT)); ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM); - } else { viewGroup.setVisibility(View.GONE); ((TextView) findViewById(R.id.noEffectsTextView)).setVisibility(View.VISIBLE); @@ -501,18 +521,11 @@ public class ActivityMusic extends Activity implements OnSeekBarChangeListener { super.onResume(); if ((mVirtualizerSupported) || (mBassBoostSupported) || (mEqualizerSupported) || (mPresetReverbSupported)) { - // Listen for broadcast intents that might affect the onscreen UI for headset. - final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); - intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); - intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); - intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY); - registerReceiver(mReceiver, intentFilter); - - // Check if wired or Bluetooth headset is connected/on - final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - mIsHeadsetOn = (audioManager.isWiredHeadsetOn() || audioManager.isBluetoothA2dpOn()); + // Monitor active playback configurations used for media and playing on a headset. + final AudioManager audioManager = (AudioManager) getSystemService(AudioManager.class); + audioManager.registerAudioPlaybackCallback(mMyAudioPlaybackCallback, null); + mIsHeadsetOn = isHeadsetUsedForMedia(audioManager.getActivePlaybackConfigurations()); Log.v(TAG, "onResume: mIsHeadsetOn : " + mIsHeadsetOn); - // Update UI updateUI(); } @@ -527,11 +540,12 @@ public class ActivityMusic extends Activity implements OnSeekBarChangeListener { protected void onPause() { super.onPause(); - // Unregister for broadcast intents. (These affect the visible UI, + // Stop monitoring active playback configurations. (These affect the visible UI, // so we only care about them while we're in the foreground.) if ((mVirtualizerSupported) || (mBassBoostSupported) || (mEqualizerSupported) || (mPresetReverbSupported)) { - unregisterReceiver(mReceiver); + final AudioManager audioManager = (AudioManager) getSystemService(AudioManager.class); + audioManager.unregisterAudioPlaybackCallback(mMyAudioPlaybackCallback); } } |