summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2021-03-30 17:28:53 +0200
committerEric Laurent <elaurent@google.com>2021-03-30 17:28:53 +0200
commit8553181dec49a2a2fb7ff5778b34ca2ec950cf7c (patch)
tree74206a35f9d4ac0a153b0ec10b6a32cdb41ebb3c
parent9cc70b16daa5de3b44e9e22190ffa0cd0e3607b3 (diff)
downloadMusicFX-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.xml3
-rw-r--r--src/com/android/musicfx/ActivityMusic.java102
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);
}
}