Loading android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java +1 −3 Original line number Diff line number Diff line Loading @@ -258,12 +258,10 @@ public class A2dpSinkStreamHandler extends Handler { new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) .build(); // Bluetooth ducking is handled at the native layer so tell the Audio Manger to notify the // focus change listener via .setWillPauseWhenDucked(). // Bluetooth ducking is handled at the native layer at the request of AudioManager. AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).setAudioAttributes( streamAttributes) .setWillPauseWhenDucked(true) .setOnAudioFocusChangeListener(mAudioFocusListener, this) .build(); int focusRequestStatus = mAudioManager.requestAudioFocus(focusRequest); Loading android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java +96 −22 Original line number Diff line number Diff line Loading @@ -638,7 +638,10 @@ public class AvrcpControllerService extends ProfileService { return true; } void removeStateMachine(AvrcpControllerStateMachine stateMachine) { /** * Remove state machine from device map once it is no longer needed. */ public void removeStateMachine(AvrcpControllerStateMachine stateMachine) { mDeviceStateMap.remove(stateMachine.getDevice()); } Loading Loading @@ -705,39 +708,110 @@ public class AvrcpControllerService extends ProfileService { private native void cleanupNative(); static native boolean sendPassThroughCommandNative(byte[] address, int keyCode, int keyState); /** * Send button press commands to addressed device * * @param keyCode key code as defined in AVRCP specification * @param keyState 0 = key pressed, 1 = key released * @return command was sent */ public native boolean sendPassThroughCommandNative(byte[] address, int keyCode, int keyState); static native boolean sendGroupNavigationCommandNative(byte[] address, int keyCode, /** * Send group navigation commands * * @param keyCode next/previous * @param keyState state * @return command was sent */ public native boolean sendGroupNavigationCommandNative(byte[] address, int keyCode, int keyState); static native void setPlayerApplicationSettingValuesNative(byte[] address, byte numAttrib, byte[] atttibIds, byte[] attribVal); /** * Change player specific settings such as shuffle * * @param numAttrib number of settings being sent * @param attribIds list of settings to be changed * @param attribVal list of settings values */ public native void setPlayerApplicationSettingValuesNative(byte[] address, byte numAttrib, byte[] attribIds, byte[] attribVal); /* This api is used to send response to SET_ABS_VOL_CMD */ static native void sendAbsVolRspNative(byte[] address, int absVol, int label); /** * Send response to set absolute volume * * @param absVol new volume * @param label label */ public native void sendAbsVolRspNative(byte[] address, int absVol, int label); /* This api is used to inform remote for any volume level changes */ static native void sendRegisterAbsVolRspNative(byte[] address, byte rspType, int absVol, /** * Register for any volume level changes * * @param rspType type of response * @param absVol current volume * @param label label */ public native void sendRegisterAbsVolRspNative(byte[] address, byte rspType, int absVol, int label); /* API used to fetch the playback state */ static native void getPlaybackStateNative(byte[] address); /** * Fetch the playback state */ public native void getPlaybackStateNative(byte[] address); /* API used to fetch the current now playing list */ static native void getNowPlayingListNative(byte[] address, int start, int end); /** * Fetch the current now playing list * * @param start first index to retrieve * @param end last index to retrieve */ public native void getNowPlayingListNative(byte[] address, int start, int end); /* API used to fetch the current folder's listing */ static native void getFolderListNative(byte[] address, int start, int end); /** * Fetch the current folder's listing * * @param start first index to retrieve * @param end last index to retrieve */ public native void getFolderListNative(byte[] address, int start, int end); /* API used to fetch the listing of players */ static native void getPlayerListNative(byte[] address, int start, int end); /** * Fetch the listing of players * * @param start first index to retrieve * @param end last index to retrieve */ public native void getPlayerListNative(byte[] address, int start, int end); /* API used to change the folder */ static native void changeFolderPathNative(byte[] address, byte direction, long uid); /** * Change the current browsed folder * * @param direction up/down * @param uid folder unique id */ public native void changeFolderPathNative(byte[] address, byte direction, long uid); static native void playItemNative(byte[] address, byte scope, long uid, int uidCounter); /** * Play item with provided uid * * @param scope scope of item to played * @param uid song unique id * @param uidCounter counter */ public native void playItemNative(byte[] address, byte scope, long uid, int uidCounter); static native void setBrowsedPlayerNative(byte[] address, int playerId); /** * Set a specific player for browsing * * @param playerId player number */ public native void setBrowsedPlayerNative(byte[] address, int playerId); static native void setAddressedPlayerNative(byte[] address, int playerId); /** * Set a specific player for handling playback commands * * @param playerId player number */ public native void setAddressedPlayerNative(byte[] address, int playerId); } android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +19 −7 Original line number Diff line number Diff line Loading @@ -533,6 +533,18 @@ class AvrcpControllerStateMachine extends StateMachine { } break; case CONNECT: case DISCONNECT: case MSG_AVRCP_PASSTHRU: case MESSAGE_PROCESS_SET_ABS_VOL_CMD: case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION: case MESSAGE_PROCESS_TRACK_CHANGED: case MESSAGE_PROCESS_PLAY_POS_CHANGED: case MESSAGE_PROCESS_PLAY_STATUS_CHANGED: case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION: // All of these messages should be handled by parent state immediately. return false; default: logD(STATE_TAG + " deferring message " + msg.what + " to connected!"); Loading @@ -547,15 +559,15 @@ class AvrcpControllerStateMachine extends StateMachine { + ITEM_PAGE_SIZE) - 1; switch (target.getScope()) { case AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST: AvrcpControllerService.getPlayerListNative(mDeviceAddress, mService.getPlayerListNative(mDeviceAddress, start, end); break; case AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING: AvrcpControllerService.getNowPlayingListNative( mService.getNowPlayingListNative( mDeviceAddress, start, end); break; case AvrcpControllerService.BROWSE_SCOPE_VFS: AvrcpControllerService.getFolderListNative(mDeviceAddress, mService.getFolderListNative(mDeviceAddress, start, end); break; default: Loading Loading @@ -589,7 +601,7 @@ class AvrcpControllerStateMachine extends StateMachine { } else if (mNextStep.isPlayer()) { logD("NAVIGATING Player " + mNextStep.toString()); if (mNextStep.isBrowsable()) { AvrcpControllerService.setBrowsedPlayerNative( mService.setBrowsedPlayerNative( mDeviceAddress, (int) mNextStep.getBluetoothID()); } else { logD("Player doesn't support browsing"); Loading @@ -601,14 +613,14 @@ class AvrcpControllerStateMachine extends StateMachine { mNextStep = mBrowseTree.getCurrentBrowsedFolder().getParent(); mBrowseTree.getCurrentBrowsedFolder().setCached(false); AvrcpControllerService.changeFolderPathNative( mService.changeFolderPathNative( mDeviceAddress, AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_UP, 0); } else { logD("NAVIGATING DOWN " + mNextStep.toString()); AvrcpControllerService.changeFolderPathNative( mService.changeFolderPathNative( mDeviceAddress, AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_DOWN, mNextStep.getBluetoothID()); Loading Loading @@ -648,7 +660,7 @@ class AvrcpControllerStateMachine extends StateMachine { mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, newIndex, AudioManager.FLAG_SHOW_UI); } AvrcpControllerService.sendAbsVolRspNative(mDeviceAddress, absVol, label); mService.sendAbsVolRspNative(mDeviceAddress, absVol, label); } MediaSession.Callback mSessionCallbacks = new MediaSession.Callback() { Loading android/app/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java +13 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.bluetooth.avrcpcontroller; import android.media.MediaMetadata; import android.media.browse.MediaBrowser.MediaItem; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Bundle; Loading Loading @@ -170,6 +171,18 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { } } /** * Get object for controlling playback */ public static synchronized MediaController.TransportControls getTransportControls() { if (sBluetoothMediaBrowserService != null) { return sBluetoothMediaBrowserService.mSession.getController().getTransportControls(); } else { Log.w(TAG, "transportControls Unavailable"); return null; } } /** * Set Media session active whenever we have Focus of any kind */ Loading android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java 0 → 100644 +407 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java +1 −3 Original line number Diff line number Diff line Loading @@ -258,12 +258,10 @@ public class A2dpSinkStreamHandler extends Handler { new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) .build(); // Bluetooth ducking is handled at the native layer so tell the Audio Manger to notify the // focus change listener via .setWillPauseWhenDucked(). // Bluetooth ducking is handled at the native layer at the request of AudioManager. AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).setAudioAttributes( streamAttributes) .setWillPauseWhenDucked(true) .setOnAudioFocusChangeListener(mAudioFocusListener, this) .build(); int focusRequestStatus = mAudioManager.requestAudioFocus(focusRequest); Loading
android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java +96 −22 Original line number Diff line number Diff line Loading @@ -638,7 +638,10 @@ public class AvrcpControllerService extends ProfileService { return true; } void removeStateMachine(AvrcpControllerStateMachine stateMachine) { /** * Remove state machine from device map once it is no longer needed. */ public void removeStateMachine(AvrcpControllerStateMachine stateMachine) { mDeviceStateMap.remove(stateMachine.getDevice()); } Loading Loading @@ -705,39 +708,110 @@ public class AvrcpControllerService extends ProfileService { private native void cleanupNative(); static native boolean sendPassThroughCommandNative(byte[] address, int keyCode, int keyState); /** * Send button press commands to addressed device * * @param keyCode key code as defined in AVRCP specification * @param keyState 0 = key pressed, 1 = key released * @return command was sent */ public native boolean sendPassThroughCommandNative(byte[] address, int keyCode, int keyState); static native boolean sendGroupNavigationCommandNative(byte[] address, int keyCode, /** * Send group navigation commands * * @param keyCode next/previous * @param keyState state * @return command was sent */ public native boolean sendGroupNavigationCommandNative(byte[] address, int keyCode, int keyState); static native void setPlayerApplicationSettingValuesNative(byte[] address, byte numAttrib, byte[] atttibIds, byte[] attribVal); /** * Change player specific settings such as shuffle * * @param numAttrib number of settings being sent * @param attribIds list of settings to be changed * @param attribVal list of settings values */ public native void setPlayerApplicationSettingValuesNative(byte[] address, byte numAttrib, byte[] attribIds, byte[] attribVal); /* This api is used to send response to SET_ABS_VOL_CMD */ static native void sendAbsVolRspNative(byte[] address, int absVol, int label); /** * Send response to set absolute volume * * @param absVol new volume * @param label label */ public native void sendAbsVolRspNative(byte[] address, int absVol, int label); /* This api is used to inform remote for any volume level changes */ static native void sendRegisterAbsVolRspNative(byte[] address, byte rspType, int absVol, /** * Register for any volume level changes * * @param rspType type of response * @param absVol current volume * @param label label */ public native void sendRegisterAbsVolRspNative(byte[] address, byte rspType, int absVol, int label); /* API used to fetch the playback state */ static native void getPlaybackStateNative(byte[] address); /** * Fetch the playback state */ public native void getPlaybackStateNative(byte[] address); /* API used to fetch the current now playing list */ static native void getNowPlayingListNative(byte[] address, int start, int end); /** * Fetch the current now playing list * * @param start first index to retrieve * @param end last index to retrieve */ public native void getNowPlayingListNative(byte[] address, int start, int end); /* API used to fetch the current folder's listing */ static native void getFolderListNative(byte[] address, int start, int end); /** * Fetch the current folder's listing * * @param start first index to retrieve * @param end last index to retrieve */ public native void getFolderListNative(byte[] address, int start, int end); /* API used to fetch the listing of players */ static native void getPlayerListNative(byte[] address, int start, int end); /** * Fetch the listing of players * * @param start first index to retrieve * @param end last index to retrieve */ public native void getPlayerListNative(byte[] address, int start, int end); /* API used to change the folder */ static native void changeFolderPathNative(byte[] address, byte direction, long uid); /** * Change the current browsed folder * * @param direction up/down * @param uid folder unique id */ public native void changeFolderPathNative(byte[] address, byte direction, long uid); static native void playItemNative(byte[] address, byte scope, long uid, int uidCounter); /** * Play item with provided uid * * @param scope scope of item to played * @param uid song unique id * @param uidCounter counter */ public native void playItemNative(byte[] address, byte scope, long uid, int uidCounter); static native void setBrowsedPlayerNative(byte[] address, int playerId); /** * Set a specific player for browsing * * @param playerId player number */ public native void setBrowsedPlayerNative(byte[] address, int playerId); static native void setAddressedPlayerNative(byte[] address, int playerId); /** * Set a specific player for handling playback commands * * @param playerId player number */ public native void setAddressedPlayerNative(byte[] address, int playerId); }
android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +19 −7 Original line number Diff line number Diff line Loading @@ -533,6 +533,18 @@ class AvrcpControllerStateMachine extends StateMachine { } break; case CONNECT: case DISCONNECT: case MSG_AVRCP_PASSTHRU: case MESSAGE_PROCESS_SET_ABS_VOL_CMD: case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION: case MESSAGE_PROCESS_TRACK_CHANGED: case MESSAGE_PROCESS_PLAY_POS_CHANGED: case MESSAGE_PROCESS_PLAY_STATUS_CHANGED: case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION: // All of these messages should be handled by parent state immediately. return false; default: logD(STATE_TAG + " deferring message " + msg.what + " to connected!"); Loading @@ -547,15 +559,15 @@ class AvrcpControllerStateMachine extends StateMachine { + ITEM_PAGE_SIZE) - 1; switch (target.getScope()) { case AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST: AvrcpControllerService.getPlayerListNative(mDeviceAddress, mService.getPlayerListNative(mDeviceAddress, start, end); break; case AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING: AvrcpControllerService.getNowPlayingListNative( mService.getNowPlayingListNative( mDeviceAddress, start, end); break; case AvrcpControllerService.BROWSE_SCOPE_VFS: AvrcpControllerService.getFolderListNative(mDeviceAddress, mService.getFolderListNative(mDeviceAddress, start, end); break; default: Loading Loading @@ -589,7 +601,7 @@ class AvrcpControllerStateMachine extends StateMachine { } else if (mNextStep.isPlayer()) { logD("NAVIGATING Player " + mNextStep.toString()); if (mNextStep.isBrowsable()) { AvrcpControllerService.setBrowsedPlayerNative( mService.setBrowsedPlayerNative( mDeviceAddress, (int) mNextStep.getBluetoothID()); } else { logD("Player doesn't support browsing"); Loading @@ -601,14 +613,14 @@ class AvrcpControllerStateMachine extends StateMachine { mNextStep = mBrowseTree.getCurrentBrowsedFolder().getParent(); mBrowseTree.getCurrentBrowsedFolder().setCached(false); AvrcpControllerService.changeFolderPathNative( mService.changeFolderPathNative( mDeviceAddress, AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_UP, 0); } else { logD("NAVIGATING DOWN " + mNextStep.toString()); AvrcpControllerService.changeFolderPathNative( mService.changeFolderPathNative( mDeviceAddress, AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_DOWN, mNextStep.getBluetoothID()); Loading Loading @@ -648,7 +660,7 @@ class AvrcpControllerStateMachine extends StateMachine { mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, newIndex, AudioManager.FLAG_SHOW_UI); } AvrcpControllerService.sendAbsVolRspNative(mDeviceAddress, absVol, label); mService.sendAbsVolRspNative(mDeviceAddress, absVol, label); } MediaSession.Callback mSessionCallbacks = new MediaSession.Callback() { Loading
android/app/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java +13 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.bluetooth.avrcpcontroller; import android.media.MediaMetadata; import android.media.browse.MediaBrowser.MediaItem; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Bundle; Loading Loading @@ -170,6 +171,18 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { } } /** * Get object for controlling playback */ public static synchronized MediaController.TransportControls getTransportControls() { if (sBluetoothMediaBrowserService != null) { return sBluetoothMediaBrowserService.mSession.getController().getTransportControls(); } else { Log.w(TAG, "transportControls Unavailable"); return null; } } /** * Set Media session active whenever we have Focus of any kind */ Loading
android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java 0 → 100644 +407 −0 File added.Preview size limit exceeded, changes collapsed. Show changes