diff options
Diffstat (limited to 'src/com/android/bluetooth/avrcpcontroller')
6 files changed, 324 insertions, 271 deletions
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java index 64e63df00..56684cd7c 100644 --- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java +++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java @@ -172,9 +172,11 @@ public class AvrcpControllerService extends ProfileService { } } + // If we don't find a node in the tree then do not have any way to browse for the contents. + // Return an empty list instead. if (requestedNode == null) { if (DBG) Log.d(TAG, "Didn't find a node"); - return null; + return new ArrayList(0); } else { if (!requestedNode.isCached()) { if (DBG) Log.d(TAG, "node is not cached"); @@ -412,9 +414,10 @@ public class AvrcpControllerService extends ProfileService { if (stateMachine != null) { PlayerApplicationSettings supportedSettings = PlayerApplicationSettings.makeSupportedSettings(playerAttribRsp); + stateMachine.sendMessage( + AvrcpControllerStateMachine.MESSAGE_PROCESS_SUPPORTED_APPLICATION_SETTINGS, + supportedSettings); } - /* Do nothing */ - } private synchronized void onPlayerAppSettingChanged(byte[] address, byte[] playerAttribRsp, @@ -426,10 +429,12 @@ public class AvrcpControllerService extends ProfileService { AvrcpControllerStateMachine stateMachine = getStateMachine(device); if (stateMachine != null) { - PlayerApplicationSettings desiredSettings = + PlayerApplicationSettings currentSettings = PlayerApplicationSettings.makeSettings(playerAttribRsp); + stateMachine.sendMessage( + AvrcpControllerStateMachine.MESSAGE_PROCESS_CURRENT_APPLICATION_SETTINGS, + currentSettings); } - /* Do nothing */ } // Browsing related JNI callbacks. @@ -711,7 +716,7 @@ public class AvrcpControllerService extends ProfileService { /** * Send button press commands to addressed device * - * @param keyCode key code as defined in AVRCP specification + * @param keyCode key code as defined in AVRCP specification * @param keyState 0 = key pressed, 1 = key released * @return command was sent */ @@ -720,7 +725,7 @@ public class AvrcpControllerService extends ProfileService { /** * Send group navigation commands * - * @param keyCode next/previous + * @param keyCode next/previous * @param keyState state * @return command was sent */ @@ -741,7 +746,7 @@ public class AvrcpControllerService extends ProfileService { * Send response to set absolute volume * * @param absVol new volume - * @param label label + * @param label label */ public native void sendAbsVolRspNative(byte[] address, int absVol, int label); @@ -749,8 +754,8 @@ public class AvrcpControllerService extends ProfileService { * Register for any volume level changes * * @param rspType type of response - * @param absVol current volume - * @param label label + * @param absVol current volume + * @param label label */ public native void sendRegisterAbsVolRspNative(byte[] address, byte rspType, int absVol, int label); @@ -764,7 +769,7 @@ public class AvrcpControllerService extends ProfileService { * Fetch the current now playing list * * @param start first index to retrieve - * @param end last index to retrieve + * @param end last index to retrieve */ public native void getNowPlayingListNative(byte[] address, int start, int end); @@ -772,7 +777,7 @@ public class AvrcpControllerService extends ProfileService { * Fetch the current folder's listing * * @param start first index to retrieve - * @param end last index to retrieve + * @param end last index to retrieve */ public native void getFolderListNative(byte[] address, int start, int end); @@ -780,7 +785,7 @@ public class AvrcpControllerService extends ProfileService { * Fetch the listing of players * * @param start first index to retrieve - * @param end last index to retrieve + * @param end last index to retrieve */ public native void getPlayerListNative(byte[] address, int start, int end); @@ -788,15 +793,15 @@ public class AvrcpControllerService extends ProfileService { * Change the current browsed folder * * @param direction up/down - * @param uid folder unique id + * @param uid folder unique id */ public native void changeFolderPathNative(byte[] address, byte direction, long uid); /** * Play item with provided uid * - * @param scope scope of item to played - * @param uid song unique id + * @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); diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java index 66571c4e7..c319364c1 100644 --- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java @@ -24,10 +24,10 @@ import android.content.Intent; import android.media.AudioManager; import android.media.MediaMetadata; import android.media.browse.MediaBrowser.MediaItem; -import android.media.session.MediaSession; -import android.media.session.PlaybackState; import android.os.Bundle; import android.os.Message; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; import android.util.Log; import android.util.SparseArray; @@ -42,6 +42,7 @@ import com.android.internal.util.StateMachine; import java.util.ArrayList; import java.util.List; + /** * Provides Bluetooth AVRCP Controller State Machine responsible for all remote control connections * and interactions with a remote controlable device. @@ -76,11 +77,15 @@ class AvrcpControllerStateMachine extends StateMachine { static final int MESSAGE_PROCESS_SET_ADDRESSED_PLAYER = 214; static final int MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED = 215; static final int MESSAGE_PROCESS_NOW_PLAYING_CONTENTS_CHANGED = 216; + static final int MESSAGE_PROCESS_SUPPORTED_APPLICATION_SETTINGS = 217; + static final int MESSAGE_PROCESS_CURRENT_APPLICATION_SETTINGS = 218; //300->399 Events for Browsing static final int MESSAGE_GET_FOLDER_ITEMS = 300; static final int MESSAGE_PLAY_ITEM = 301; static final int MSG_AVRCP_PASSTHRU = 302; + static final int MSG_AVRCP_SET_SHUFFLE = 303; + static final int MSG_AVRCP_SET_REPEAT = 304; static final int MESSAGE_INTERNAL_ABS_VOL_TIMEOUT = 404; @@ -218,26 +223,19 @@ class AvrcpControllerStateMachine extends StateMachine { mService.sBrowseTree.mRootNode.addChild(mBrowseTree.mRootNode); BluetoothMediaBrowserService.notifyChanged(mService .sBrowseTree.mRootNode); - BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState()); mBrowsingConnected = true; } synchronized void onBrowsingDisconnected() { if (!mBrowsingConnected) return; - mAddressedPlayer.setPlayStatus(PlaybackState.STATE_ERROR); + mAddressedPlayer.setPlayStatus(PlaybackStateCompat.STATE_ERROR); mAddressedPlayer.updateCurrentTrack(null); mBrowseTree.mNowPlayingNode.setCached(false); BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mNowPlayingNode); - PlaybackState.Builder pbb = new PlaybackState.Builder(); - pbb.setState(PlaybackState.STATE_ERROR, PlaybackState.PLAYBACK_POSITION_UNKNOWN, - 1.0f).setActions(0); - pbb.setErrorMessage(mService.getString(R.string.bluetooth_disconnected)); - BluetoothMediaBrowserService.notifyChanged(pbb.build()); mService.sBrowseTree.mRootNode.removeChild( mBrowseTree.mRootNode); BluetoothMediaBrowserService.notifyChanged(mService .sBrowseTree.mRootNode); - BluetoothMediaBrowserService.trackChanged(null); mBrowsingConnected = false; } @@ -298,8 +296,9 @@ class AvrcpControllerStateMachine extends StateMachine { @Override public void enter() { if (mMostRecentState == BluetoothProfile.STATE_CONNECTING) { - broadcastConnectionStateChanged(BluetoothProfile.STATE_CONNECTED); BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks); + BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState()); + broadcastConnectionStateChanged(BluetoothProfile.STATE_CONNECTED); } else { logD("ReEnteringConnected"); } @@ -315,14 +314,14 @@ class AvrcpControllerStateMachine extends StateMachine { removeMessages(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT); sendMessageDelayed(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT, ABS_VOL_TIMEOUT_MILLIS); - setAbsVolume(msg.arg1, msg.arg2); + handleAbsVolumeRequest(msg.arg1, msg.arg2); return true; case MESSAGE_PROCESS_REGISTER_ABS_VOL_NOTIFICATION: mVolumeNotificationLabel = msg.arg1; mService.sendRegisterAbsVolRspNative(mDeviceAddress, NOTIFICATION_RSP_TYPE_INTERIM, - getAbsVolumeResponse(), mVolumeNotificationLabel); + getAbsVolume(), mVolumeNotificationLabel); return true; case MESSAGE_GET_FOLDER_ITEMS: @@ -338,6 +337,14 @@ class AvrcpControllerStateMachine extends StateMachine { passThru(msg.arg1); return true; + case MSG_AVRCP_SET_REPEAT: + setRepeat(msg.arg1); + return true; + + case MSG_AVRCP_SET_SHUFFLE: + setShuffle(msg.arg1); + return true; + case MESSAGE_PROCESS_TRACK_CHANGED: mAddressedPlayer.updateCurrentTrack((MediaMetadata) msg.obj); BluetoothMediaBrowserService.trackChanged((MediaMetadata) msg.obj); @@ -347,11 +354,14 @@ class AvrcpControllerStateMachine extends StateMachine { mAddressedPlayer.setPlayStatus(msg.arg1); BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState()); if (mAddressedPlayer.getPlaybackState().getState() - == PlaybackState.STATE_PLAYING - && A2dpSinkService.getFocusState() == AudioManager.AUDIOFOCUS_NONE - && !shouldRequestFocus()) { + == PlaybackStateCompat.STATE_PLAYING + && A2dpSinkService.getFocusState() == AudioManager.AUDIOFOCUS_NONE) { + if (shouldRequestFocus()) { + mSessionCallbacks.onPrepare(); + } else { sendMessage(MSG_AVRCP_PASSTHRU, AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE); + } } return true; @@ -378,6 +388,18 @@ class AvrcpControllerStateMachine extends StateMachine { } return true; + case MESSAGE_PROCESS_SUPPORTED_APPLICATION_SETTINGS: + mAddressedPlayer.setSupportedPlayerApplicationSettings( + (PlayerApplicationSettings) msg.obj); + BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState()); + return true; + + case MESSAGE_PROCESS_CURRENT_APPLICATION_SETTINGS: + mAddressedPlayer.setCurrentPlayerApplicationSettings( + (PlayerApplicationSettings) msg.obj); + BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState()); + return true; + case DISCONNECT: transitionTo(mDisconnecting); return true; @@ -435,6 +457,20 @@ class AvrcpControllerStateMachine extends StateMachine { return (cmd == AvrcpControllerService.PASS_THRU_CMD_ID_REWIND) || (cmd == AvrcpControllerService.PASS_THRU_CMD_ID_FF); } + + private void setRepeat(int repeatMode) { + mService.setPlayerApplicationSettingValuesNative(mDeviceAddress, (byte) 1, + new byte[]{PlayerApplicationSettings.REPEAT_STATUS}, new byte[]{ + PlayerApplicationSettings.mapAvrcpPlayerSettingstoBTattribVal( + PlayerApplicationSettings.REPEAT_STATUS, repeatMode)}); + } + + private void setShuffle(int shuffleMode) { + mService.setPlayerApplicationSettingValuesNative(mDeviceAddress, (byte) 1, + new byte[]{PlayerApplicationSettings.SHUFFLE_STATUS}, new byte[]{ + PlayerApplicationSettings.mapAvrcpPlayerSettingstoBTattribVal( + PlayerApplicationSettings.SHUFFLE_STATUS, shuffleMode)}); + } } // Handle the get folder listing action @@ -554,7 +590,7 @@ class AvrcpControllerStateMachine extends StateMachine { case MESSAGE_GET_FOLDER_ITEMS: if (!mBrowseNode.equals(msg.obj)) { if (shouldAbort(mBrowseNode.getScope(), - ((BrowseTree.BrowseNode) msg.obj).getScope())) { + ((BrowseTree.BrowseNode) msg.obj).getScope())) { mAbort = true; } deferMessage(msg); @@ -576,8 +612,8 @@ class AvrcpControllerStateMachine extends StateMachine { * necessary. * * @return true: a new folder in the same scope - * a new player while fetching contents of a folder - * false: other cases, specifically Now Playing while fetching a folder + * a new player while fetching contents of a folder + * false: other cases, specifically Now Playing while fetching a folder */ private boolean shouldAbort(int currentScope, int fetchScope) { if ((currentScope == fetchScope) @@ -674,31 +710,60 @@ class AvrcpControllerStateMachine extends StateMachine { @Override public void enter() { onBrowsingDisconnected(); + BluetoothMediaBrowserService.trackChanged(null); + BluetoothMediaBrowserService.addressedPlayerChanged(null); broadcastConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTING); transitionTo(mDisconnected); } } + /** + * Handle a request to align our local volume with the volume of a remote device. If + * we're assuming the source volume is fixed then a response of ABS_VOL_MAX will always be + * sent and no volume adjustment action will be taken on the sink side. + * + * @param absVol A volume level based on a domain of [0, ABS_VOL_MAX] + * @param label Volume notification label + */ + private void handleAbsVolumeRequest(int absVol, int label) { + logD("handleAbsVolumeRequest: absVol = " + absVol + ", label = " + label); + if (mIsVolumeFixed) { + logD("Source volume is assumed to be fixed, responding with max volume"); + absVol = ABS_VOL_BASE; + } else { + mVolumeChangedNotificationsToIgnore++; + removeMessages(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT); + sendMessageDelayed(MESSAGE_INTERNAL_ABS_VOL_TIMEOUT, + ABS_VOL_TIMEOUT_MILLIS); + setAbsVolume(absVol); + } + mService.sendAbsVolRspNative(mDeviceAddress, absVol, label); + } + + /** + * Align our volume with a requested absolute volume level + * + * @param absVol A volume level based on a domain of [0, ABS_VOL_MAX] + */ + private void setAbsVolume(int absVol) { + int maxLocalVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + int curLocalVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + int reqLocalVolume = (maxLocalVolume * absVol) / ABS_VOL_BASE; + logD("setAbsVolme: absVol = " + absVol + ", reqLocal = " + reqLocalVolume + + ", curLocal = " + curLocalVolume + ", maxLocal = " + maxLocalVolume); - private void setAbsVolume(int absVol, int label) { - int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - int currIndex = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); - int newIndex = (maxVolume * absVol) / ABS_VOL_BASE; - logD(" setAbsVolume =" + absVol + " maxVol = " + maxVolume - + " cur = " + currIndex + " new = " + newIndex); /* * In some cases change in percentage is not sufficient enough to warrant * change in index values which are in range of 0-15. For such cases * no action is required */ - if (newIndex != currIndex) { - mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, newIndex, + if (reqLocalVolume != curLocalVolume) { + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, reqLocalVolume, AudioManager.FLAG_SHOW_UI); } - mService.sendAbsVolRspNative(mDeviceAddress, getAbsVolumeResponse(), label); } - private int getAbsVolumeResponse() { + private int getAbsVolume() { if (mIsVolumeFixed) { return ABS_VOL_BASE; } @@ -708,7 +773,7 @@ class AvrcpControllerStateMachine extends StateMachine { return newIndex; } - MediaSession.Callback mSessionCallbacks = new MediaSession.Callback() { + MediaSessionCompat.Callback mSessionCallbacks = new MediaSessionCompat.Callback() { @Override public void onPlay() { logD("onPlay"); @@ -781,6 +846,19 @@ class AvrcpControllerStateMachine extends StateMachine { BrowseTree.BrowseNode node = mBrowseTree.findBrowseNodeByID(mediaId); sendMessage(MESSAGE_PLAY_ITEM, node); } + + @Override + public void onSetRepeatMode(int repeatMode) { + logD("onSetRepeatMode"); + sendMessage(MSG_AVRCP_SET_REPEAT, repeatMode); + } + + @Override + public void onSetShuffleMode(int shuffleMode) { + logD("onSetShuffleMode"); + sendMessage(MSG_AVRCP_SET_SHUFFLE, shuffleMode); + + } }; protected void broadcastConnectionStateChanged(int currentState) { diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java index bed38d905..4736acffa 100644 --- a/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java +++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java @@ -17,8 +17,9 @@ package com.android.bluetooth.avrcpcontroller; import android.media.MediaMetadata; -import android.media.session.PlaybackState; import android.os.SystemClock; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; import android.util.Log; import java.util.Arrays; @@ -41,27 +42,31 @@ class AvrcpPlayer { public static final int FEATURE_PREVIOUS = 48; public static final int FEATURE_BROWSING = 59; - private int mPlayStatus = PlaybackState.STATE_NONE; - private long mPlayTime = PlaybackState.PLAYBACK_POSITION_UNKNOWN; + private int mPlayStatus = PlaybackStateCompat.STATE_NONE; + private long mPlayTime = PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN; private long mPlayTimeUpdate = 0; private float mPlaySpeed = 1; private int mId; private String mName = ""; private int mPlayerType; - private byte[] mPlayerFeatures; - private long mAvailableActions; + private byte[] mPlayerFeatures = new byte[16]; + private long mAvailableActions = PlaybackStateCompat.ACTION_PREPARE; private MediaMetadata mCurrentTrack; - private PlaybackState mPlaybackState; + private PlaybackStateCompat mPlaybackStateCompat; + private PlayerApplicationSettings mSupportedPlayerApplicationSettings = + new PlayerApplicationSettings(); + private PlayerApplicationSettings mCurrentPlayerApplicationSettings; AvrcpPlayer() { mId = INVALID_ID; //Set Default Actions in case Player data isn't available. - mAvailableActions = PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY - | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS - | PlaybackState.ACTION_STOP; - PlaybackState.Builder playbackStateBuilder = new PlaybackState.Builder() + mAvailableActions = PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY + | PlaybackStateCompat.ACTION_SKIP_TO_NEXT + | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS + | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_PREPARE; + PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder() .setActions(mAvailableActions); - mPlaybackState = playbackStateBuilder.build(); + mPlaybackStateCompat = playbackStateBuilder.build(); } AvrcpPlayer(int id, String name, byte[] playerFeatures, int playStatus, int playerType) { @@ -70,10 +75,10 @@ class AvrcpPlayer { mPlayStatus = playStatus; mPlayerType = playerType; mPlayerFeatures = Arrays.copyOf(playerFeatures, playerFeatures.length); - updateAvailableActions(); - PlaybackState.Builder playbackStateBuilder = new PlaybackState.Builder() + PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder() .setActions(mAvailableActions); - mPlaybackState = playbackStateBuilder.build(); + mPlaybackStateCompat = playbackStateBuilder.build(); + updateAvailableActions(); } public int getId() { @@ -87,7 +92,8 @@ class AvrcpPlayer { public void setPlayTime(int playTime) { mPlayTime = playTime; mPlayTimeUpdate = SystemClock.elapsedRealtime(); - mPlaybackState = new PlaybackState.Builder(mPlaybackState).setState(mPlayStatus, mPlayTime, + mPlaybackStateCompat = new PlaybackStateCompat.Builder(mPlaybackStateCompat).setState( + mPlayStatus, mPlayTime, mPlaySpeed).build(); } @@ -97,30 +103,48 @@ class AvrcpPlayer { public void setPlayStatus(int playStatus) { mPlayTime += mPlaySpeed * (SystemClock.elapsedRealtime() - - mPlaybackState.getLastPositionUpdateTime()); + - mPlaybackStateCompat.getLastPositionUpdateTime()); mPlayStatus = playStatus; switch (mPlayStatus) { - case PlaybackState.STATE_STOPPED: + case PlaybackStateCompat.STATE_STOPPED: mPlaySpeed = 0; break; - case PlaybackState.STATE_PLAYING: + case PlaybackStateCompat.STATE_PLAYING: mPlaySpeed = 1; break; - case PlaybackState.STATE_PAUSED: + case PlaybackStateCompat.STATE_PAUSED: mPlaySpeed = 0; break; - case PlaybackState.STATE_FAST_FORWARDING: + case PlaybackStateCompat.STATE_FAST_FORWARDING: mPlaySpeed = 3; break; - case PlaybackState.STATE_REWINDING: + case PlaybackStateCompat.STATE_REWINDING: mPlaySpeed = -3; break; } - mPlaybackState = new PlaybackState.Builder(mPlaybackState).setState(mPlayStatus, mPlayTime, + mPlaybackStateCompat = new PlaybackStateCompat.Builder(mPlaybackStateCompat).setState( + mPlayStatus, mPlayTime, mPlaySpeed).build(); } + public void setSupportedPlayerApplicationSettings( + PlayerApplicationSettings playerApplicationSettings) { + mSupportedPlayerApplicationSettings = playerApplicationSettings; + updateAvailableActions(); + } + + public void setCurrentPlayerApplicationSettings( + PlayerApplicationSettings playerApplicationSettings) { + Log.d(TAG, "Settings changed"); + mCurrentPlayerApplicationSettings = playerApplicationSettings; + MediaSessionCompat session = BluetoothMediaBrowserService.getSession(); + session.setRepeatMode(mCurrentPlayerApplicationSettings.getSetting( + PlayerApplicationSettings.REPEAT_STATUS)); + session.setShuffleMode(mCurrentPlayerApplicationSettings.getSetting( + PlayerApplicationSettings.SHUFFLE_STATUS)); + } + public int getPlayStatus() { return mPlayStatus; } @@ -131,17 +155,22 @@ class AvrcpPlayer { return (mPlayerFeatures[byteNumber] & bitMask) == bitMask; } - public PlaybackState getPlaybackState() { + public boolean supportsSetting(int settingType, int settingValue) { + return mSupportedPlayerApplicationSettings.supportsSetting(settingType, settingValue); + } + + public PlaybackStateCompat getPlaybackState() { if (DBG) { Log.d(TAG, "getPlayBackState state " + mPlayStatus + " time " + mPlayTime); } - return mPlaybackState; + return mPlaybackStateCompat; } public synchronized void updateCurrentTrack(MediaMetadata update) { if (update != null) { long trackNumber = update.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER); - mPlaybackState = new PlaybackState.Builder(mPlaybackState).setActiveQueueItemId( + mPlaybackStateCompat = new PlaybackStateCompat.Builder( + mPlaybackStateCompat).setActiveQueueItemId( trackNumber - 1).build(); } mCurrentTrack = update; @@ -153,26 +182,37 @@ class AvrcpPlayer { private void updateAvailableActions() { if (supportsFeature(FEATURE_PLAY)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_PLAY; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_PLAY; } if (supportsFeature(FEATURE_STOP)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_STOP; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_STOP; } if (supportsFeature(FEATURE_PAUSE)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_PAUSE; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_PAUSE; } if (supportsFeature(FEATURE_REWIND)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_REWIND; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_REWIND; } if (supportsFeature(FEATURE_FAST_FORWARD)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_FAST_FORWARD; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_FAST_FORWARD; } if (supportsFeature(FEATURE_FORWARD)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_SKIP_TO_NEXT; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_SKIP_TO_NEXT; } if (supportsFeature(FEATURE_PREVIOUS)) { - mAvailableActions = mAvailableActions | PlaybackState.ACTION_SKIP_TO_PREVIOUS; + mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; } + if (mSupportedPlayerApplicationSettings.supportsSetting( + PlayerApplicationSettings.REPEAT_STATUS)) { + mAvailableActions |= PlaybackStateCompat.ACTION_SET_REPEAT_MODE; + } + if (mSupportedPlayerApplicationSettings.supportsSetting( + PlayerApplicationSettings.SHUFFLE_STATUS)) { + mAvailableActions |= PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE; + } + mPlaybackStateCompat = new PlaybackStateCompat.Builder(mPlaybackStateCompat) + .setActions(mAvailableActions).build(); + if (DBG) Log.d(TAG, "Supported Actions = " + mAvailableActions); } } diff --git a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java index 304d5a2c9..a0b1224ee 100644 --- a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java +++ b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java @@ -16,15 +16,22 @@ package com.android.bluetooth.avrcpcontroller; +import android.app.PendingIntent; +import android.content.Intent; 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; -import android.service.media.MediaBrowserService; +import android.support.v4.media.MediaBrowserCompat; +import android.support.v4.media.MediaDescriptionCompat; +import android.support.v4.media.MediaMetadataCompat; +import android.support.v4.media.session.MediaControllerCompat; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; import android.util.Log; +import androidx.media.MediaBrowserServiceCompat; + +import com.android.bluetooth.BluetoothPrefs; import com.android.bluetooth.R; import java.util.ArrayList; @@ -37,45 +44,48 @@ import java.util.List; * The applications are expected to use MediaBrowser (see API) and all the music * browsing/playback/metadata can be controlled via MediaBrowser and MediaController. * - * The current behavior of MediaSession exposed by this service is as follows: - * 1. MediaSession is active (i.e. SystemUI and other overview UIs can see updates) when device is - * connected and first starts playing. Before it starts playing we do not active the session. + * The current behavior of MediaSessionCompat exposed by this service is as follows: + * 1. MediaSessionCompat is active (i.e. SystemUI and other overview UIs can see updates) when + * device is connected and first starts playing. Before it starts playing we do not activate the + * session. * 1.1 The session is active throughout the duration of connection. * 2. The session is de-activated when the device disconnects. It will be connected again when (1) * happens. */ -public class BluetoothMediaBrowserService extends MediaBrowserService { +public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat { private static final String TAG = "BluetoothMediaBrowserService"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static BluetoothMediaBrowserService sBluetoothMediaBrowserService; - private MediaSession mSession; + private MediaSessionCompat mSession; // Browsing related structures. - private List<MediaSession.QueueItem> mMediaQueue = new ArrayList<>(); + private List<MediaSessionCompat.QueueItem> mMediaQueue = new ArrayList<>(); + + // Error messaging extras + public static final String ERROR_RESOLUTION_ACTION_INTENT = + "android.media.extras.ERROR_RESOLUTION_ACTION_INTENT"; + public static final String ERROR_RESOLUTION_ACTION_LABEL = + "android.media.extras.ERROR_RESOLUTION_ACTION_LABEL"; /** - * Initialize this BluetoothMediaBrowserService, creating our MediaSession, MediaPlayer and - * MediaMetaData, and setting up mechanisms to talk with the AvrcpControllerService. + * Initialize this BluetoothMediaBrowserService, creating our MediaSessionCompat, MediaPlayer + * and MediaMetaData, and setting up mechanisms to talk with the AvrcpControllerService. */ @Override public void onCreate() { if (DBG) Log.d(TAG, "onCreate"); super.onCreate(); - // Create and configure the MediaSession - mSession = new MediaSession(this, TAG); + // Create and configure the MediaSessionCompat + mSession = new MediaSessionCompat(this, TAG); setSessionToken(mSession.getSessionToken()); - mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS - | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); + mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS + | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); mSession.setQueueTitle(getString(R.string.bluetooth_a2dp_sink_queue_name)); mSession.setQueue(mMediaQueue); - PlaybackState.Builder playbackStateBuilder = new PlaybackState.Builder(); - playbackStateBuilder.setState(PlaybackState.STATE_ERROR, - PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f).setActions(0); - playbackStateBuilder.setErrorMessage(getString(R.string.bluetooth_disconnected)); - mSession.setPlaybackState(playbackStateBuilder.build()); + setErrorPlaybackState(); sBluetoothMediaBrowserService = this; } @@ -89,11 +99,30 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { } } + private void setErrorPlaybackState() { + Bundle extras = new Bundle(); + extras.putString(ERROR_RESOLUTION_ACTION_LABEL, + getString(R.string.bluetooth_connect_action)); + Intent launchIntent = new Intent(); + launchIntent.setAction(BluetoothPrefs.BLUETOOTH_SETTING_ACTION); + launchIntent.addCategory(BluetoothPrefs.BLUETOOTH_SETTING_CATEGORY); + PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, + launchIntent, PendingIntent.FLAG_UPDATE_CURRENT); + extras.putParcelable(ERROR_RESOLUTION_ACTION_INTENT, pendingIntent); + PlaybackStateCompat errorState = new PlaybackStateCompat.Builder() + .setErrorMessage(getString(R.string.bluetooth_disconnected)) + .setExtras(extras) + .setState(PlaybackStateCompat.STATE_ERROR, 0, 0) + .build(); + mSession.setPlaybackState(errorState); + } + @Override public synchronized void onLoadChildren(final String parentMediaId, - final Result<List<MediaItem>> result) { + final Result<List<MediaBrowserCompat.MediaItem>> result) { if (DBG) Log.d(TAG, "onLoadChildren parentMediaId=" + parentMediaId); - List<MediaItem> contents = getContents(parentMediaId); + List<MediaBrowserCompat.MediaItem> contents = + MediaBrowserCompat.MediaItem.fromMediaItemList(getContents(parentMediaId)); if (contents == null) { result.detach(); } else { @@ -112,7 +141,8 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { mMediaQueue.clear(); if (songList != null) { for (MediaItem song : songList) { - mMediaQueue.add(new MediaSession.QueueItem(song.getDescription(), + mMediaQueue.add(new MediaSessionCompat.QueueItem( + MediaDescriptionCompat.fromMediaDescription(song.getDescription()), mMediaQueue.size())); } } @@ -129,8 +159,11 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { } } - static synchronized void addressedPlayerChanged(MediaSession.Callback callback) { + static synchronized void addressedPlayerChanged(MediaSessionCompat.Callback callback) { if (sBluetoothMediaBrowserService != null) { + if (callback == null) { + sBluetoothMediaBrowserService.setErrorPlaybackState(); + } sBluetoothMediaBrowserService.mSession.setCallback(callback); } else { Log.w(TAG, "addressedPlayerChanged Unavailable"); @@ -139,13 +172,14 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { static synchronized void trackChanged(MediaMetadata mediaMetadata) { if (sBluetoothMediaBrowserService != null) { - sBluetoothMediaBrowserService.mSession.setMetadata(mediaMetadata); + sBluetoothMediaBrowserService.mSession.setMetadata( + MediaMetadataCompat.fromMediaMetadata(mediaMetadata)); } else { Log.w(TAG, "trackChanged Unavailable"); } } - static synchronized void notifyChanged(PlaybackState playbackState) { + static synchronized void notifyChanged(PlaybackStateCompat playbackState) { Log.d(TAG, "notifyChanged PlaybackState" + playbackState); if (sBluetoothMediaBrowserService != null) { sBluetoothMediaBrowserService.mSession.setPlaybackState(playbackState); @@ -181,19 +215,19 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { */ public static synchronized int getPlaybackState() { if (sBluetoothMediaBrowserService != null) { - PlaybackState currentPlaybackState = + PlaybackStateCompat currentPlaybackState = sBluetoothMediaBrowserService.mSession.getController().getPlaybackState(); if (currentPlaybackState != null) { return currentPlaybackState.getState(); } } - return PlaybackState.STATE_ERROR; + return PlaybackStateCompat.STATE_ERROR; } /** * Get object for controlling playback */ - public static synchronized MediaController.TransportControls getTransportControls() { + public static synchronized MediaControllerCompat.TransportControls getTransportControls() { if (sBluetoothMediaBrowserService != null) { return sBluetoothMediaBrowserService.mSession.getController().getTransportControls(); } else { @@ -212,4 +246,16 @@ public class BluetoothMediaBrowserService extends MediaBrowserService { Log.w(TAG, "setActive Unavailable"); } } + + /** + * Get Media session for updating state + */ + public static synchronized MediaSessionCompat getSession() { + if (sBluetoothMediaBrowserService != null) { + return sBluetoothMediaBrowserService.mSession; + } else { + Log.w(TAG, "getSession Unavailable"); + return null; + } + } } diff --git a/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java b/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java index accea2a70..923282d34 100644 --- a/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java +++ b/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java @@ -100,7 +100,7 @@ public class BrowseTree { } BrowseNode getTrackFromNowPlayingList(int trackNumber) { - return mNowPlayingNode.mChildren.get(trackNumber); + return mNowPlayingNode.getChild(trackNumber); } // Each node of the tree is represented by Folder ID, Folder Name and the children. @@ -218,6 +218,13 @@ public class BrowseTree { return mChildren; } + synchronized BrowseNode getChild(int index) { + if (index < 0 || index >= mChildren.size()) { + return null; + } + return mChildren.get(index); + } + synchronized BrowseNode getParent() { return mParent; } diff --git a/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettings.java b/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettings.java index c34a2d7d0..362548e5f 100644 --- a/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettings.java +++ b/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettings.java @@ -16,12 +16,11 @@ package com.android.bluetooth.avrcpcontroller; -import android.bluetooth.BluetoothAvrcpPlayerSettings; +import android.support.v4.media.session.PlaybackStateCompat; import android.util.Log; +import android.util.SparseArray; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; /* * Contains information Player Application Setting extended from BluetootAvrcpPlayerSettings @@ -32,10 +31,10 @@ class PlayerApplicationSettings { /* * Values for SetPlayerApplicationSettings from AVRCP Spec V1.6 Appendix F. */ - private static final byte JNI_ATTRIB_EQUALIZER_STATUS = 0x01; - private static final byte JNI_ATTRIB_REPEAT_STATUS = 0x02; - private static final byte JNI_ATTRIB_SHUFFLE_STATUS = 0x03; - private static final byte JNI_ATTRIB_SCAN_STATUS = 0x04; + static final byte EQUALIZER_STATUS = 0x01; + static final byte REPEAT_STATUS = 0x02; + static final byte SHUFFLE_STATUS = 0x03; + static final byte SCAN_STATUS = 0x04; private static final byte JNI_EQUALIZER_STATUS_OFF = 0x01; private static final byte JNI_EQUALIZER_STATUS_ON = 0x02; @@ -55,18 +54,17 @@ class PlayerApplicationSettings { private static final byte JNI_STATUS_INVALID = -1; - /* * Hash map of current settings. */ - private Map<Integer, Integer> mSettings = new HashMap<Integer, Integer>(); + private SparseArray<Integer> mSettings = new SparseArray<>(); /* * Hash map of supported values, a setting should be supported by the remote in order to enable * in mSettings. */ - private Map<Integer, ArrayList<Integer>> mSupportedValues = - new HashMap<Integer, ArrayList<Integer>>(); + private SparseArray<ArrayList<Integer>> mSupportedValues = + new SparseArray<ArrayList<Integer>>(); /* Convert from JNI array to Java classes. */ static PlayerApplicationSettings makeSupportedSettings(byte[] btAvrcpAttributeList) { @@ -82,8 +80,7 @@ class PlayerApplicationSettings { supportedValues.add( mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++])); } - newObj.mSupportedValues.put(mapBTAttribIdToAvrcpPlayerSettings(attrId), - supportedValues); + newObj.mSupportedValues.put(attrId, supportedValues); } } catch (ArrayIndexOutOfBoundsException exception) { Log.e(TAG, "makeSupportedSettings attributeList index error."); @@ -91,25 +88,13 @@ class PlayerApplicationSettings { return newObj; } - public BluetoothAvrcpPlayerSettings getAvrcpSettings() { - int supportedSettings = 0; - for (Integer setting : mSettings.keySet()) { - supportedSettings |= setting; - } - BluetoothAvrcpPlayerSettings result = new BluetoothAvrcpPlayerSettings(supportedSettings); - for (Integer setting : mSettings.keySet()) { - result.addSettingValue(setting, mSettings.get(setting)); - } - return result; - } - static PlayerApplicationSettings makeSettings(byte[] btAvrcpAttributeList) { PlayerApplicationSettings newObj = new PlayerApplicationSettings(); try { for (int i = 0; i < btAvrcpAttributeList.length; ) { byte attrId = btAvrcpAttributeList[i++]; - newObj.mSettings.put(mapBTAttribIdToAvrcpPlayerSettings(attrId), + newObj.mSettings.put(attrId, mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++])); } } catch (ArrayIndexOutOfBoundsException exception) { @@ -123,177 +108,69 @@ class PlayerApplicationSettings { mSupportedValues = updates.mSupportedValues; } - public void setValues(BluetoothAvrcpPlayerSettings updates) { - int supportedSettings = updates.getSettings(); - for (int i = 1; i <= BluetoothAvrcpPlayerSettings.SETTING_SCAN; i++) { - if ((i & supportedSettings) > 0) { - mSettings.put(i, updates.getSettingValue(i)); - } - } + public boolean supportsSetting(int settingType, int settingValue) { + if (null == mSupportedValues.get(settingType)) return false; + return mSupportedValues.valueAt(settingType).contains(settingValue); } - /* - * Check through all settings to ensure that they are all available to be set and then check - * that the desired value is in fact supported by our remote player. - */ - public boolean supportsSettings(BluetoothAvrcpPlayerSettings settingsToCheck) { - int settingSubset = settingsToCheck.getSettings(); - int supportedSettings = 0; - for (Integer setting : mSupportedValues.keySet()) { - supportedSettings |= setting; - } - try { - if ((supportedSettings & settingSubset) == settingSubset) { - for (Integer settingId : mSettings.keySet()) { - // The setting is in both settings to check and supported settings but the - // value is not supported. - if ((settingId & settingSubset) == settingId && (!mSupportedValues.get( - settingId).contains(settingsToCheck.getSettingValue(settingId)))) { - return false; - } - } - return true; - } - } catch (NullPointerException e) { - Log.e(TAG, - "supportsSettings received a supported setting that has no supported values."); - } - return false; + public boolean supportsSetting(int settingType) { + return (null != mSupportedValues.get(settingType)); } - // Convert currently desired settings into an attribute array to pass to the native layer to - // enable them. - public ArrayList<Byte> getNativeSettings() { - int i = 0; - ArrayList<Byte> attribArray = new ArrayList<Byte>(); - for (Integer settingId : mSettings.keySet()) { - switch (settingId) { - case BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER: - attribArray.add(JNI_ATTRIB_EQUALIZER_STATUS); - attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId, - mSettings.get(settingId))); - break; - case BluetoothAvrcpPlayerSettings.SETTING_REPEAT: - attribArray.add(JNI_ATTRIB_REPEAT_STATUS); - attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId, - mSettings.get(settingId))); - break; - case BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE: - attribArray.add(JNI_ATTRIB_SHUFFLE_STATUS); - attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId, - mSettings.get(settingId))); - break; - case BluetoothAvrcpPlayerSettings.SETTING_SCAN: - attribArray.add(JNI_ATTRIB_SCAN_STATUS); - attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId, - mSettings.get(settingId))); - break; - default: - Log.w(TAG, "Unknown setting found in getNativeSettings: " + settingId); - } - } - return attribArray; + public int getSetting(int settingType) { + if (null == mSettings.get(settingType)) return -1; + return mSettings.get(settingType); } // Convert a native Attribute Id/Value pair into the AVRCP equivalent value. private static int mapAttribIdValtoAvrcpPlayerSetting(byte attribId, byte attribVal) { - if (attribId == JNI_ATTRIB_EQUALIZER_STATUS) { - switch (attribVal) { - case JNI_EQUALIZER_STATUS_OFF: - return BluetoothAvrcpPlayerSettings.STATE_OFF; - case JNI_EQUALIZER_STATUS_ON: - return BluetoothAvrcpPlayerSettings.STATE_ON; - } - } else if (attribId == JNI_ATTRIB_REPEAT_STATUS) { + if (attribId == REPEAT_STATUS) { switch (attribVal) { case JNI_REPEAT_STATUS_ALL_TRACK_REPEAT: - return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; + return PlaybackStateCompat.REPEAT_MODE_ALL; case JNI_REPEAT_STATUS_GROUP_REPEAT: - return BluetoothAvrcpPlayerSettings.STATE_GROUP; + return PlaybackStateCompat.REPEAT_MODE_GROUP; case JNI_REPEAT_STATUS_OFF: - return BluetoothAvrcpPlayerSettings.STATE_OFF; + return PlaybackStateCompat.REPEAT_MODE_NONE; case JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT: - return BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK; - } - } else if (attribId == JNI_ATTRIB_SCAN_STATUS) { - switch (attribVal) { - case JNI_SCAN_STATUS_ALL_TRACK_SCAN: - return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; - case JNI_SCAN_STATUS_GROUP_SCAN: - return BluetoothAvrcpPlayerSettings.STATE_GROUP; - case JNI_SCAN_STATUS_OFF: - return BluetoothAvrcpPlayerSettings.STATE_OFF; + return PlaybackStateCompat.REPEAT_MODE_ONE; } - } else if (attribId == JNI_ATTRIB_SHUFFLE_STATUS) { + } else if (attribId == SHUFFLE_STATUS) { switch (attribVal) { case JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE: - return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK; + return PlaybackStateCompat.SHUFFLE_MODE_ALL; case JNI_SHUFFLE_STATUS_GROUP_SHUFFLE: - return BluetoothAvrcpPlayerSettings.STATE_GROUP; + return PlaybackStateCompat.SHUFFLE_MODE_GROUP; case JNI_SHUFFLE_STATUS_OFF: - return BluetoothAvrcpPlayerSettings.STATE_OFF; + return PlaybackStateCompat.SHUFFLE_MODE_NONE; } } - return BluetoothAvrcpPlayerSettings.STATE_INVALID; + return JNI_STATUS_INVALID; } // Convert an AVRCP Setting/Value pair into the native equivalent value; - private static byte mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal) { - if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER) { - switch (mSettingVal) { - case BluetoothAvrcpPlayerSettings.STATE_OFF: - return JNI_EQUALIZER_STATUS_OFF; - case BluetoothAvrcpPlayerSettings.STATE_ON: - return JNI_EQUALIZER_STATUS_ON; - } - } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_REPEAT) { + static byte mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal) { + if (mSetting == REPEAT_STATUS) { switch (mSettingVal) { - case BluetoothAvrcpPlayerSettings.STATE_OFF: + case PlaybackStateCompat.REPEAT_MODE_NONE: return JNI_REPEAT_STATUS_OFF; - case BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK: + case PlaybackStateCompat.REPEAT_MODE_ONE: return JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT; - case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: + case PlaybackStateCompat.REPEAT_MODE_ALL: return JNI_REPEAT_STATUS_ALL_TRACK_REPEAT; - case BluetoothAvrcpPlayerSettings.STATE_GROUP: + case PlaybackStateCompat.REPEAT_MODE_GROUP: return JNI_REPEAT_STATUS_GROUP_REPEAT; } - } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) { + } else if (mSetting == SHUFFLE_STATUS) { switch (mSettingVal) { - case BluetoothAvrcpPlayerSettings.STATE_OFF: + case PlaybackStateCompat.SHUFFLE_MODE_NONE: return JNI_SHUFFLE_STATUS_OFF; - case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: + case PlaybackStateCompat.SHUFFLE_MODE_ALL: return JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE; - case BluetoothAvrcpPlayerSettings.STATE_GROUP: + case PlaybackStateCompat.SHUFFLE_MODE_GROUP: return JNI_SHUFFLE_STATUS_GROUP_SHUFFLE; } - } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SCAN) { - switch (mSettingVal) { - case BluetoothAvrcpPlayerSettings.STATE_OFF: - return JNI_SCAN_STATUS_OFF; - case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK: - return JNI_SCAN_STATUS_ALL_TRACK_SCAN; - case BluetoothAvrcpPlayerSettings.STATE_GROUP: - return JNI_SCAN_STATUS_GROUP_SCAN; - } } return JNI_STATUS_INVALID; } - - // convert a native Attribute Id into the AVRCP Setting equivalent value; - private static int mapBTAttribIdToAvrcpPlayerSettings(byte attribId) { - switch (attribId) { - case JNI_ATTRIB_EQUALIZER_STATUS: - return BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER; - case JNI_ATTRIB_REPEAT_STATUS: - return BluetoothAvrcpPlayerSettings.SETTING_REPEAT; - case JNI_ATTRIB_SHUFFLE_STATUS: - return BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE; - case JNI_ATTRIB_SCAN_STATUS: - return BluetoothAvrcpPlayerSettings.SETTING_SCAN; - default: - return BluetoothAvrcpPlayerSettings.STATE_INVALID; - } - } - } - |