Loading android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java +13 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,19 @@ public class A2dpSinkService extends ProfileService { } } /** * Called by AVRCP controller to establish audio focus. * * In order to perform streaming the A2DP sink must have audio focus. This interface allows the * associated MediaSession to inform the sink of intent to play and then allows streaming to be * started from either the source or the sink endpoint. */ public void requestAudioFocus(BluetoothDevice device, boolean request) { if (mStateMachine != null) { mStateMachine.sendMessage(A2dpSinkStateMachine.EVENT_REQUEST_FOCUS); } } synchronized boolean isA2dpPlaying(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (DBG) { Loading android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java +9 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.Intent; import android.media.AudioFormat; import android.media.AudioManager; import android.os.Handler; import android.os.Message; import android.os.ParcelUuid; Loading Loading @@ -67,6 +68,7 @@ public class A2dpSinkStateMachine extends StateMachine { public static final int EVENT_AVRCP_CT_PAUSE = 302; public static final int EVENT_AVRCP_TG_PLAY = 303; public static final int EVENT_AVRCP_TG_PAUSE = 304; public static final int EVENT_REQUEST_FOCUS = 305; private static final int IS_INVALID_DEVICE = 0; private static final int IS_VALID_DEVICE = 1; Loading Loading @@ -500,8 +502,10 @@ public class A2dpSinkStateMachine extends StateMachine { mStreaming = new A2dpSinkStreamHandler(A2dpSinkStateMachine.this, mContext); } } if (mStreaming.getAudioFocus() == AudioManager.AUDIOFOCUS_NONE) { informAudioFocusStateNative(0); } } @Override public boolean processMessage(Message message) { Loading Loading @@ -586,6 +590,10 @@ public class A2dpSinkStateMachine extends StateMachine { mStreaming.obtainMessage(A2dpSinkStreamHandler.SRC_PAUSE).sendToTarget(); break; case EVENT_REQUEST_FOCUS: mStreaming.obtainMessage(A2dpSinkStreamHandler.REQUEST_FOCUS).sendToTarget(); break; default: return NOT_HANDLED; } Loading android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java +13 −5 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ public class A2dpSinkStreamHandler extends Handler { public static final int SRC_PAUSE = 5; // Pause command was generated from remote device public static final int DISCONNECT = 6; // Remote device was disconnected public static final int AUDIO_FOCUS_CHANGE = 7; // Audio focus callback with associated change public static final int REQUEST_FOCUS = 8; // Request focus when the media service is active // Used to indicate focus lost private static final int STATE_FOCUS_LOST = 0; Loading Loading @@ -159,11 +160,15 @@ public class A2dpSinkStreamHandler extends Handler { stopAvrcpUpdates(); break; case REQUEST_FOCUS: if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) { requestAudioFocus(); } break; case DISCONNECT: // Remote device has disconnected, restore everything to default state. sendAvrcpPause(); stopAvrcpUpdates(); abandonAudioFocus(); mSentPause = false; break; Loading Loading @@ -208,7 +213,6 @@ public class A2dpSinkStreamHandler extends Handler { case AudioManager.AUDIOFOCUS_LOSS: // Permanent loss of focus probably due to another audio app, abandon focus // and stop playback. mAudioFocus = AudioManager.AUDIOFOCUS_NONE; abandonAudioFocus(); sendAvrcpPause(); break; Loading @@ -223,7 +227,7 @@ public class A2dpSinkStreamHandler extends Handler { /** * Utility functions. */ private int requestAudioFocus() { private synchronized int requestAudioFocus() { // Bluetooth A2DP may carry Music, Audio Books, Navigation, or other sounds so mark content // type unknown. AudioAttributes streamAttributes = Loading @@ -249,7 +253,7 @@ public class A2dpSinkStreamHandler extends Handler { } private void abandonAudioFocus() { private synchronized void abandonAudioFocus() { stopFluorideStreaming(); mAudioManager.abandonAudioFocus(mAudioFocusListener); mAudioFocus = AudioManager.AUDIOFOCUS_NONE; Loading Loading @@ -348,6 +352,10 @@ public class A2dpSinkStreamHandler extends Handler { } } synchronized int getAudioFocus() { return mAudioFocus; } private boolean isIotDevice() { return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED); } Loading android/app/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService.java +11 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.util.Log; import android.util.Pair; import com.android.bluetooth.R; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.avrcpcontroller.AvrcpControllerService; import com.android.bluetooth.avrcpcontroller.BrowseTree; Loading Loading @@ -99,6 +100,7 @@ public class A2dpMediaBrowserService extends MediaBrowserService { private AvrcpControllerService mAvrcpCtrlSrvc; private boolean mBrowseConnected = false; private BluetoothDevice mA2dpDevice = null; private A2dpSinkService mA2dpSinkService = null; private Handler mAvrcpCommandQueue; private final Map<String, Result<List<MediaItem>>> mParentIdToRequestMap = new HashMap<>(); Loading Loading @@ -266,6 +268,14 @@ public class A2dpMediaBrowserService extends MediaBrowserService { AvrcpControllerService.PASS_THRU_CMD_ID_STOP).sendToTarget(); } @Override public void onPrepare() { Log.d(TAG, "onPrepare"); if (mA2dpSinkService != null) { mA2dpSinkService.requestAudioFocus(mA2dpDevice, true); } } @Override public void onRewind() { Log.d(TAG, "onRewind"); Loading Loading @@ -390,6 +400,7 @@ public class A2dpMediaBrowserService extends MediaBrowserService { return; } mA2dpDevice = devices.get(0); mA2dpSinkService = A2dpSinkService.getA2dpSinkService(); PlaybackState playbackState = mAvrcpCtrlSrvc.getPlaybackState(mA2dpDevice); // Add actions required for playback and rebuild the object. Loading android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +7 −1 Original line number Diff line number Diff line Loading @@ -544,9 +544,10 @@ class AvrcpControllerStateMachine extends StateMachine { @Override public void enter() { // Setup the timeouts. super.enter(); mCurrInd = 0; mFolderList.clear(); callNativeFunctionForScope(mStartInd, Math.min(mEndInd, mStartInd + GET_FOLDER_ITEMS_PAGINATION_SIZE - 1)); } Loading Loading @@ -745,6 +746,11 @@ class AvrcpControllerStateMachine extends StateMachine { sendMessage(MESSAGE_INTERNAL_MOVE_N_LEVELS_UP); break; case MESSAGE_INTERNAL_CMD_TIMEOUT: broadcastFolderList(BrowseTree.ROOT, EMPTY_MEDIA_ITEM_LIST); transitionTo(mConnected); break; default: Log.d(STATE_TAG, "deferring message " + msg + " to connected!"); deferMessage(msg); Loading Loading
android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java +13 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,19 @@ public class A2dpSinkService extends ProfileService { } } /** * Called by AVRCP controller to establish audio focus. * * In order to perform streaming the A2DP sink must have audio focus. This interface allows the * associated MediaSession to inform the sink of intent to play and then allows streaming to be * started from either the source or the sink endpoint. */ public void requestAudioFocus(BluetoothDevice device, boolean request) { if (mStateMachine != null) { mStateMachine.sendMessage(A2dpSinkStateMachine.EVENT_REQUEST_FOCUS); } } synchronized boolean isA2dpPlaying(BluetoothDevice device) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (DBG) { Loading
android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java +9 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.Intent; import android.media.AudioFormat; import android.media.AudioManager; import android.os.Handler; import android.os.Message; import android.os.ParcelUuid; Loading Loading @@ -67,6 +68,7 @@ public class A2dpSinkStateMachine extends StateMachine { public static final int EVENT_AVRCP_CT_PAUSE = 302; public static final int EVENT_AVRCP_TG_PLAY = 303; public static final int EVENT_AVRCP_TG_PAUSE = 304; public static final int EVENT_REQUEST_FOCUS = 305; private static final int IS_INVALID_DEVICE = 0; private static final int IS_VALID_DEVICE = 1; Loading Loading @@ -500,8 +502,10 @@ public class A2dpSinkStateMachine extends StateMachine { mStreaming = new A2dpSinkStreamHandler(A2dpSinkStateMachine.this, mContext); } } if (mStreaming.getAudioFocus() == AudioManager.AUDIOFOCUS_NONE) { informAudioFocusStateNative(0); } } @Override public boolean processMessage(Message message) { Loading Loading @@ -586,6 +590,10 @@ public class A2dpSinkStateMachine extends StateMachine { mStreaming.obtainMessage(A2dpSinkStreamHandler.SRC_PAUSE).sendToTarget(); break; case EVENT_REQUEST_FOCUS: mStreaming.obtainMessage(A2dpSinkStreamHandler.REQUEST_FOCUS).sendToTarget(); break; default: return NOT_HANDLED; } Loading
android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java +13 −5 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ public class A2dpSinkStreamHandler extends Handler { public static final int SRC_PAUSE = 5; // Pause command was generated from remote device public static final int DISCONNECT = 6; // Remote device was disconnected public static final int AUDIO_FOCUS_CHANGE = 7; // Audio focus callback with associated change public static final int REQUEST_FOCUS = 8; // Request focus when the media service is active // Used to indicate focus lost private static final int STATE_FOCUS_LOST = 0; Loading Loading @@ -159,11 +160,15 @@ public class A2dpSinkStreamHandler extends Handler { stopAvrcpUpdates(); break; case REQUEST_FOCUS: if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) { requestAudioFocus(); } break; case DISCONNECT: // Remote device has disconnected, restore everything to default state. sendAvrcpPause(); stopAvrcpUpdates(); abandonAudioFocus(); mSentPause = false; break; Loading Loading @@ -208,7 +213,6 @@ public class A2dpSinkStreamHandler extends Handler { case AudioManager.AUDIOFOCUS_LOSS: // Permanent loss of focus probably due to another audio app, abandon focus // and stop playback. mAudioFocus = AudioManager.AUDIOFOCUS_NONE; abandonAudioFocus(); sendAvrcpPause(); break; Loading @@ -223,7 +227,7 @@ public class A2dpSinkStreamHandler extends Handler { /** * Utility functions. */ private int requestAudioFocus() { private synchronized int requestAudioFocus() { // Bluetooth A2DP may carry Music, Audio Books, Navigation, or other sounds so mark content // type unknown. AudioAttributes streamAttributes = Loading @@ -249,7 +253,7 @@ public class A2dpSinkStreamHandler extends Handler { } private void abandonAudioFocus() { private synchronized void abandonAudioFocus() { stopFluorideStreaming(); mAudioManager.abandonAudioFocus(mAudioFocusListener); mAudioFocus = AudioManager.AUDIOFOCUS_NONE; Loading Loading @@ -348,6 +352,10 @@ public class A2dpSinkStreamHandler extends Handler { } } synchronized int getAudioFocus() { return mAudioFocus; } private boolean isIotDevice() { return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED); } Loading
android/app/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService.java +11 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.util.Log; import android.util.Pair; import com.android.bluetooth.R; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.avrcpcontroller.AvrcpControllerService; import com.android.bluetooth.avrcpcontroller.BrowseTree; Loading Loading @@ -99,6 +100,7 @@ public class A2dpMediaBrowserService extends MediaBrowserService { private AvrcpControllerService mAvrcpCtrlSrvc; private boolean mBrowseConnected = false; private BluetoothDevice mA2dpDevice = null; private A2dpSinkService mA2dpSinkService = null; private Handler mAvrcpCommandQueue; private final Map<String, Result<List<MediaItem>>> mParentIdToRequestMap = new HashMap<>(); Loading Loading @@ -266,6 +268,14 @@ public class A2dpMediaBrowserService extends MediaBrowserService { AvrcpControllerService.PASS_THRU_CMD_ID_STOP).sendToTarget(); } @Override public void onPrepare() { Log.d(TAG, "onPrepare"); if (mA2dpSinkService != null) { mA2dpSinkService.requestAudioFocus(mA2dpDevice, true); } } @Override public void onRewind() { Log.d(TAG, "onRewind"); Loading Loading @@ -390,6 +400,7 @@ public class A2dpMediaBrowserService extends MediaBrowserService { return; } mA2dpDevice = devices.get(0); mA2dpSinkService = A2dpSinkService.getA2dpSinkService(); PlaybackState playbackState = mAvrcpCtrlSrvc.getPlaybackState(mA2dpDevice); // Add actions required for playback and rebuild the object. Loading
android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +7 −1 Original line number Diff line number Diff line Loading @@ -544,9 +544,10 @@ class AvrcpControllerStateMachine extends StateMachine { @Override public void enter() { // Setup the timeouts. super.enter(); mCurrInd = 0; mFolderList.clear(); callNativeFunctionForScope(mStartInd, Math.min(mEndInd, mStartInd + GET_FOLDER_ITEMS_PAGINATION_SIZE - 1)); } Loading Loading @@ -745,6 +746,11 @@ class AvrcpControllerStateMachine extends StateMachine { sendMessage(MESSAGE_INTERNAL_MOVE_N_LEVELS_UP); break; case MESSAGE_INTERNAL_CMD_TIMEOUT: broadcastFolderList(BrowseTree.ROOT, EMPTY_MEDIA_ITEM_LIST); transitionTo(mConnected); break; default: Log.d(STATE_TAG, "deferring message " + msg + " to connected!"); deferMessage(msg); Loading