Loading android/app/src/com/android/bluetooth/avrcp/AddressedMediaPlayer.java +23 −12 Original line number Diff line number Diff line Loading @@ -45,15 +45,19 @@ public class AddressedMediaPlayer { private AvrcpMediaRspInterface mMediaInterface; private List<MediaSession.QueueItem> mNowPlayingList; private long mLastTrackIdSent; public AddressedMediaPlayer(AvrcpMediaRspInterface mediaInterface) { mNowPlayingList = null; mMediaInterface = mediaInterface; mLastTrackIdSent = MediaSession.QueueItem.UNKNOWN_ID; } void cleanup() { if (DEBUG) Log.v(TAG, "cleanup"); mNowPlayingList = null; mMediaInterface = null; mLastTrackIdSent = MediaSession.QueueItem.UNKNOWN_ID; } /* get now playing list from addressed player */ Loading Loading @@ -242,22 +246,27 @@ public class AddressedMediaPlayer { mMediaInterface.getTotalNumOfItemsRsp(bdaddr, AvrcpConstants.RSP_NO_ERROR, 0, items.size()); } void sendTrackChangeWithId(int trackChangedNT, MediaController mediaController) { boolean sendTrackChangeWithId(boolean requesting, MediaController mediaController) { if (DEBUG) Log.d(TAG, "sendTrackChangeWithId"); byte[] track; if (mediaController == null) { mMediaInterface.trackChangedRsp(trackChangedNT, AvrcpConstants.NO_TRACK_SELECTED); return; } long qid = MediaSession.QueueItem.UNKNOWN_ID; if (mediaController != null) { PlaybackState state = mediaController.getPlaybackState(); if (state != null) { qid = state.getActiveQueueItemId(); } /* for any item associated with NowPlaying, uid is queueId */ if (state != null) qid = state.getActiveQueueItemId(); } if (!requesting && qid == mLastTrackIdSent) { if (DEBUG) Log.d(TAG, "not sending duplicate track changed id " + qid); return false; } track = ByteBuffer.allocate(AvrcpConstants.UID_SIZE).putLong(qid).array(); if (DEBUG) Log.d(TAG, "trackChangedRsp: 0x" + Utils.byteArrayToString(track)); int trackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; if (requesting) trackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; mMediaInterface.trackChangedRsp(trackChangedNT, track); mLastTrackIdSent = qid; return (trackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_CHANGED); } /* Loading Loading @@ -418,11 +427,13 @@ public class AddressedMediaPlayer { break; case AvrcpConstants.ATTRID_TRACK_NUM: attrValue = extras.getString(MediaMetadata.METADATA_KEY_TRACK_NUMBER); attrValue = Long.toString(extras.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); break; case AvrcpConstants.ATTRID_NUM_TRACKS: attrValue = extras.getString(MediaMetadata.METADATA_KEY_NUM_TRACKS); attrValue = Long.toString(extras.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); break; case AvrcpConstants.ATTRID_GENRE: Loading @@ -430,7 +441,7 @@ public class AddressedMediaPlayer { break; case AvrcpConstants.ATTRID_PLAY_TIME: attrValue = extras.getString(MediaMetadata.METADATA_KEY_DURATION); attrValue = Long.toString(extras.getLong(MediaMetadata.METADATA_KEY_DURATION)); break; case AvrcpConstants.ATTRID_COVER_ART: Loading android/app/src/com/android/bluetooth/avrcp/Avrcp.java +76 −85 Original line number Diff line number Diff line Loading @@ -81,12 +81,11 @@ public final class Avrcp { private PackageManager mPackageManager; private int mTransportControlFlags; private PlaybackState mCurrentPlayState; private long mLastStateUpdate; private int mA2dpState; private int mPlayStatusChangedNT; private int mTrackChangedNT; private int mPlayPosChangedNT; private long mTracksPlayed; private long mSongLengthMs; private long mPlaybackIntervalMs; private long mLastReportedPosition; private long mNextPosMs; Loading Loading @@ -235,11 +234,10 @@ public final class Avrcp { private Avrcp(Context context) { mMediaAttributes = new MediaAttributes(null); mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING; mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; mTracksPlayed = 0; mLastStateUpdate = -1L; mSongLengthMs = 0L; mPlaybackIntervalMs = 0L; mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; mLastReportedPosition = -1; Loading Loading @@ -364,24 +362,13 @@ public final class Avrcp { @Override public void onMetadataChanged(MediaMetadata metadata) { Log.v(TAG, "MediaController metadata changed"); updateMetadata(metadata); updateCurrentMediaState(); } @Override public synchronized void onPlaybackStateChanged(PlaybackState state) { if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString()); updatePlaybackState(state); byte stateBytes = (byte) convertPlayStateToBytes(state.getState()); /* updating play status in global media player list */ MediaPlayerInfo player = getAddressedPlayerInfo(); if (player != null) { player.setPlayStatus(stateBytes); } else { Log.w(TAG, "onPlaybackStateChanged: no addressed player id=" + mCurrAddrPlayerID); } updateCurrentMediaState(); } @Override Loading Loading @@ -434,7 +421,7 @@ public final class Avrcp { byte[] address = (byte[]) msg.obj; if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_PLAY_STATUS"); getPlayStatusRspNative(address, convertPlayStateToPlayStatus(mCurrentPlayState), (int) mSongLengthMs, (int) getPlayPosition()); (int) mMediaAttributes.getLength(), (int) getPlayPosition()); break; } Loading Loading @@ -699,7 +686,8 @@ public final class Avrcp { case MSG_SET_A2DP_AUDIO_STATE: if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1); updateA2dpAudioState(msg.arg1); mA2dpState = msg.arg1; updateCurrentMediaState(); break; case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: { Loading Loading @@ -792,30 +780,22 @@ public final class Avrcp { } } private void updateA2dpAudioState(int state) { boolean isPlaying = (state == BluetoothA2dp.STATE_PLAYING); if (isPlaying != isPlayingState(mCurrentPlayState)) { /* if a2dp is streaming, check to make sure music is active */ if (isPlaying && !mAudioManager.isMusicActive()) return; PlaybackState.Builder builder = new PlaybackState.Builder(); if (isPlaying) { builder.setState(PlaybackState.STATE_PLAYING, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); } else { builder.setState(PlaybackState.STATE_PAUSED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); } updatePlaybackState(builder.build()); } } private void updatePlaybackState(PlaybackState state) { if (state == null) { state = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f).build(); } byte stateBytes = (byte) convertPlayStateToBytes(state.getState()); /* updating play status in global media player list */ MediaPlayerInfo player = getAddressedPlayerInfo(); if (player != null) { player.setPlayStatus(stateBytes); } else { Log.w(TAG, "onPlaybackStateChanged: no addressed player id=" + mCurrAddrPlayerID); } int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState); int newPlayStatus = convertPlayStateToPlayStatus(state); Loading @@ -826,7 +806,6 @@ public final class Avrcp { } mCurrentPlayState = state; mLastStateUpdate = SystemClock.elapsedRealtime(); sendPlayPosNotificationRsp(false); Loading @@ -849,7 +828,7 @@ public final class Avrcp { private String mediaNumber; private String mediaTotalNumber; private String genre; private String playingTimeMs; private long playingTimeMs; private static final int ATTR_TITLE = 1; private static final int ATTR_ARTIST_NAME = 2; Loading @@ -870,7 +849,7 @@ public final class Avrcp { mediaNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); mediaTotalNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); playingTimeMs = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_DURATION)); playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); // Try harder for the title. title = data.getString(MediaMetadata.METADATA_KEY_TITLE); Loading @@ -888,6 +867,11 @@ public final class Avrcp { title = new String(); } public long getLength() { if (!exists) return 0L; return playingTimeMs; } public boolean equals(MediaAttributes other) { if (other == null) return false; Loading @@ -898,13 +882,11 @@ public final class Avrcp { if (exists == false) return true; return (title.equals(other.title)) && (artistName.equals(other.artistName)) && (albumName.equals(other.albumName)) && (mediaNumber.equals(other.mediaNumber)) && (mediaTotalNumber.equals(other.mediaTotalNumber)) && (genre.equals(other.genre)) && (playingTimeMs.equals(other.playingTimeMs)); return (title.equals(other.title)) && (artistName.equals(other.artistName)) && (albumName.equals(other.albumName)) && (mediaNumber.equals(other.mediaNumber)) && (mediaTotalNumber.equals(other.mediaTotalNumber)) && (genre.equals(other.genre)) && (playingTimeMs == other.playingTimeMs); } public String getString(int attrId) { Loading @@ -925,7 +907,7 @@ public final class Avrcp { case ATTR_GENRE: return genre; case ATTR_PLAYING_TIME_MS: return playingTimeMs; return Long.toString(playingTimeMs); default: return new String(); } Loading @@ -944,40 +926,47 @@ public final class Avrcp { return "[MediaAttributes: none]"; } return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" + mediaNumber + "/" + mediaTotalNumber + ") " + genre + "]"; return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre + "]"; } } private void updateMetadata(MediaMetadata data) { MediaAttributes oldAttributes = mMediaAttributes; mMediaAttributes = new MediaAttributes(data); if (data == null) { mSongLengthMs = 0L; private void updateCurrentMediaState() { if (mMediaController == null) { // Use A2DP state if we don't have a MediaControlller boolean isPlaying = (mA2dpState == BluetoothA2dp.STATE_PLAYING); if (isPlaying != isPlayingState(mCurrentPlayState)) { /* if a2dp is streaming, check to make sure music is active */ if (isPlaying && !mAudioManager.isMusicActive()) return; PlaybackState.Builder builder = new PlaybackState.Builder(); if (isPlaying) { builder.setState(PlaybackState.STATE_PLAYING, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); } else { mSongLengthMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); builder.setState(PlaybackState.STATE_PAUSED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); } updatePlaybackState(builder.build()); } // Can't get metadata from A2dp so we're done. return; } if (!oldAttributes.equals(mMediaAttributes)) { MediaAttributes currentAttributes = mMediaAttributes; PlaybackState newState = mMediaController.getPlaybackState(); // Metadata mMediaAttributes = new MediaAttributes(mMediaController.getMetadata()); if (currentAttributes.equals(mMediaAttributes)) { Log.v(TAG, "MediaAttributes Changed to " + mMediaAttributes.toString()); mTracksPlayed++; if (mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; sendTrackChangedRsp(); } } else { Log.v(TAG, "Updated " + mMediaAttributes.toString() + " but no change!"); sendTrackChangedRsp(false); } // Update the play state, which sends play state and play position // notifications if needed. if (mMediaController != null) { updatePlaybackState(mMediaController.getPlaybackState()); } else { updatePlaybackState(null); } } private void getRcFeaturesRequestFromNative(byte[] address, int features) { Loading Loading @@ -1021,7 +1010,7 @@ public final class Avrcp { case EVT_TRACK_CHANGED: Log.v(TAG, "Track changed notification enabled"); mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; sendTrackChangedRsp(); sendTrackChangedRsp(true); break; case EVT_PLAY_POS_CHANGED: Loading Loading @@ -1068,22 +1057,25 @@ public final class Avrcp { mHandler.sendMessage(msg); } private void sendTrackChangedRsp() { private void sendTrackChangedRsp(boolean requested) { MediaPlayerInfo info = getAddressedPlayerInfo(); if (info != null && !info.isBrowseSupported()) { // for players which does not support Browse or when no track is currently selected trackChangeRspForBrowseUnsupported(); trackChangeRspForBrowseUnsupported(requested); } else { boolean changed = mAddressedMediaPlayer.sendTrackChangeWithId(requested, mMediaController); // for players which support browsing mAddressedMediaPlayer.sendTrackChangeWithId(mTrackChangedNT, mMediaController); if (changed) mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; } } private void trackChangeRspForBrowseUnsupported() { private void trackChangeRspForBrowseUnsupported(boolean requested) { byte[] track = AvrcpConstants.TRACK_IS_SELECTED; if (mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && !mMediaAttributes.exists) { if (requested && !mMediaAttributes.exists) { track = AvrcpConstants.NO_TRACK_SELECTED; } else if (!requested) { mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; } registerNotificationRspTrackChangeNative(mTrackChangedNT, track); } Loading @@ -1098,7 +1090,9 @@ public final class Avrcp { } if (isPlayingState(mCurrentPlayState)) { return SystemClock.elapsedRealtime() - mLastStateUpdate + mCurrentPlayState.getPosition(); long sinceUpdate = (SystemClock.elapsedRealtime() - mCurrentPlayState.getLastPositionUpdateTime()); return sinceUpdate + mCurrentPlayState.getPosition(); } return mCurrentPlayState.getPosition(); Loading Loading @@ -2105,13 +2099,12 @@ public final class Avrcp { if (newController != null) { mMediaController = newController; mMediaController.registerCallback(mMediaControllerCb, mHandler); updateMetadata(mMediaController.getMetadata()); mAddressedMediaPlayer.updateNowPlayingList(mMediaController.getQueue()); } else { updateMetadata(null); mAddressedMediaPlayer.updateNowPlayingList(null); registerRsp = false; } updateCurrentMediaState(); } return registerRsp; } Loading Loading @@ -2264,10 +2257,8 @@ public final class Avrcp { ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); ProfileService.println(sb, "mTracksPlayed: " + mTracksPlayed); ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); ProfileService.println(sb, "mLastStateUpdate: " + mLastStateUpdate); ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); ProfileService.println(sb, "mSongLengthMs: " + mSongLengthMs); ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); Loading Loading
android/app/src/com/android/bluetooth/avrcp/AddressedMediaPlayer.java +23 −12 Original line number Diff line number Diff line Loading @@ -45,15 +45,19 @@ public class AddressedMediaPlayer { private AvrcpMediaRspInterface mMediaInterface; private List<MediaSession.QueueItem> mNowPlayingList; private long mLastTrackIdSent; public AddressedMediaPlayer(AvrcpMediaRspInterface mediaInterface) { mNowPlayingList = null; mMediaInterface = mediaInterface; mLastTrackIdSent = MediaSession.QueueItem.UNKNOWN_ID; } void cleanup() { if (DEBUG) Log.v(TAG, "cleanup"); mNowPlayingList = null; mMediaInterface = null; mLastTrackIdSent = MediaSession.QueueItem.UNKNOWN_ID; } /* get now playing list from addressed player */ Loading Loading @@ -242,22 +246,27 @@ public class AddressedMediaPlayer { mMediaInterface.getTotalNumOfItemsRsp(bdaddr, AvrcpConstants.RSP_NO_ERROR, 0, items.size()); } void sendTrackChangeWithId(int trackChangedNT, MediaController mediaController) { boolean sendTrackChangeWithId(boolean requesting, MediaController mediaController) { if (DEBUG) Log.d(TAG, "sendTrackChangeWithId"); byte[] track; if (mediaController == null) { mMediaInterface.trackChangedRsp(trackChangedNT, AvrcpConstants.NO_TRACK_SELECTED); return; } long qid = MediaSession.QueueItem.UNKNOWN_ID; if (mediaController != null) { PlaybackState state = mediaController.getPlaybackState(); if (state != null) { qid = state.getActiveQueueItemId(); } /* for any item associated with NowPlaying, uid is queueId */ if (state != null) qid = state.getActiveQueueItemId(); } if (!requesting && qid == mLastTrackIdSent) { if (DEBUG) Log.d(TAG, "not sending duplicate track changed id " + qid); return false; } track = ByteBuffer.allocate(AvrcpConstants.UID_SIZE).putLong(qid).array(); if (DEBUG) Log.d(TAG, "trackChangedRsp: 0x" + Utils.byteArrayToString(track)); int trackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; if (requesting) trackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; mMediaInterface.trackChangedRsp(trackChangedNT, track); mLastTrackIdSent = qid; return (trackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_CHANGED); } /* Loading Loading @@ -418,11 +427,13 @@ public class AddressedMediaPlayer { break; case AvrcpConstants.ATTRID_TRACK_NUM: attrValue = extras.getString(MediaMetadata.METADATA_KEY_TRACK_NUMBER); attrValue = Long.toString(extras.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); break; case AvrcpConstants.ATTRID_NUM_TRACKS: attrValue = extras.getString(MediaMetadata.METADATA_KEY_NUM_TRACKS); attrValue = Long.toString(extras.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); break; case AvrcpConstants.ATTRID_GENRE: Loading @@ -430,7 +441,7 @@ public class AddressedMediaPlayer { break; case AvrcpConstants.ATTRID_PLAY_TIME: attrValue = extras.getString(MediaMetadata.METADATA_KEY_DURATION); attrValue = Long.toString(extras.getLong(MediaMetadata.METADATA_KEY_DURATION)); break; case AvrcpConstants.ATTRID_COVER_ART: Loading
android/app/src/com/android/bluetooth/avrcp/Avrcp.java +76 −85 Original line number Diff line number Diff line Loading @@ -81,12 +81,11 @@ public final class Avrcp { private PackageManager mPackageManager; private int mTransportControlFlags; private PlaybackState mCurrentPlayState; private long mLastStateUpdate; private int mA2dpState; private int mPlayStatusChangedNT; private int mTrackChangedNT; private int mPlayPosChangedNT; private long mTracksPlayed; private long mSongLengthMs; private long mPlaybackIntervalMs; private long mLastReportedPosition; private long mNextPosMs; Loading Loading @@ -235,11 +234,10 @@ public final class Avrcp { private Avrcp(Context context) { mMediaAttributes = new MediaAttributes(null); mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build(); mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING; mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; mTracksPlayed = 0; mLastStateUpdate = -1L; mSongLengthMs = 0L; mPlaybackIntervalMs = 0L; mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; mLastReportedPosition = -1; Loading Loading @@ -364,24 +362,13 @@ public final class Avrcp { @Override public void onMetadataChanged(MediaMetadata metadata) { Log.v(TAG, "MediaController metadata changed"); updateMetadata(metadata); updateCurrentMediaState(); } @Override public synchronized void onPlaybackStateChanged(PlaybackState state) { if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString()); updatePlaybackState(state); byte stateBytes = (byte) convertPlayStateToBytes(state.getState()); /* updating play status in global media player list */ MediaPlayerInfo player = getAddressedPlayerInfo(); if (player != null) { player.setPlayStatus(stateBytes); } else { Log.w(TAG, "onPlaybackStateChanged: no addressed player id=" + mCurrAddrPlayerID); } updateCurrentMediaState(); } @Override Loading Loading @@ -434,7 +421,7 @@ public final class Avrcp { byte[] address = (byte[]) msg.obj; if (DEBUG) Log.v(TAG, "MSG_NATIVE_REQ_GET_PLAY_STATUS"); getPlayStatusRspNative(address, convertPlayStateToPlayStatus(mCurrentPlayState), (int) mSongLengthMs, (int) getPlayPosition()); (int) mMediaAttributes.getLength(), (int) getPlayPosition()); break; } Loading Loading @@ -699,7 +686,8 @@ public final class Avrcp { case MSG_SET_A2DP_AUDIO_STATE: if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1); updateA2dpAudioState(msg.arg1); mA2dpState = msg.arg1; updateCurrentMediaState(); break; case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: { Loading Loading @@ -792,30 +780,22 @@ public final class Avrcp { } } private void updateA2dpAudioState(int state) { boolean isPlaying = (state == BluetoothA2dp.STATE_PLAYING); if (isPlaying != isPlayingState(mCurrentPlayState)) { /* if a2dp is streaming, check to make sure music is active */ if (isPlaying && !mAudioManager.isMusicActive()) return; PlaybackState.Builder builder = new PlaybackState.Builder(); if (isPlaying) { builder.setState(PlaybackState.STATE_PLAYING, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); } else { builder.setState(PlaybackState.STATE_PAUSED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); } updatePlaybackState(builder.build()); } } private void updatePlaybackState(PlaybackState state) { if (state == null) { state = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f).build(); } byte stateBytes = (byte) convertPlayStateToBytes(state.getState()); /* updating play status in global media player list */ MediaPlayerInfo player = getAddressedPlayerInfo(); if (player != null) { player.setPlayStatus(stateBytes); } else { Log.w(TAG, "onPlaybackStateChanged: no addressed player id=" + mCurrAddrPlayerID); } int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState); int newPlayStatus = convertPlayStateToPlayStatus(state); Loading @@ -826,7 +806,6 @@ public final class Avrcp { } mCurrentPlayState = state; mLastStateUpdate = SystemClock.elapsedRealtime(); sendPlayPosNotificationRsp(false); Loading @@ -849,7 +828,7 @@ public final class Avrcp { private String mediaNumber; private String mediaTotalNumber; private String genre; private String playingTimeMs; private long playingTimeMs; private static final int ATTR_TITLE = 1; private static final int ATTR_ARTIST_NAME = 2; Loading @@ -870,7 +849,7 @@ public final class Avrcp { mediaNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER)); mediaTotalNumber = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS)); genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); playingTimeMs = longStringOrBlank(data.getLong(MediaMetadata.METADATA_KEY_DURATION)); playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); // Try harder for the title. title = data.getString(MediaMetadata.METADATA_KEY_TITLE); Loading @@ -888,6 +867,11 @@ public final class Avrcp { title = new String(); } public long getLength() { if (!exists) return 0L; return playingTimeMs; } public boolean equals(MediaAttributes other) { if (other == null) return false; Loading @@ -898,13 +882,11 @@ public final class Avrcp { if (exists == false) return true; return (title.equals(other.title)) && (artistName.equals(other.artistName)) && (albumName.equals(other.albumName)) && (mediaNumber.equals(other.mediaNumber)) && (mediaTotalNumber.equals(other.mediaTotalNumber)) && (genre.equals(other.genre)) && (playingTimeMs.equals(other.playingTimeMs)); return (title.equals(other.title)) && (artistName.equals(other.artistName)) && (albumName.equals(other.albumName)) && (mediaNumber.equals(other.mediaNumber)) && (mediaTotalNumber.equals(other.mediaTotalNumber)) && (genre.equals(other.genre)) && (playingTimeMs == other.playingTimeMs); } public String getString(int attrId) { Loading @@ -925,7 +907,7 @@ public final class Avrcp { case ATTR_GENRE: return genre; case ATTR_PLAYING_TIME_MS: return playingTimeMs; return Long.toString(playingTimeMs); default: return new String(); } Loading @@ -944,40 +926,47 @@ public final class Avrcp { return "[MediaAttributes: none]"; } return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" + mediaNumber + "/" + mediaTotalNumber + ") " + genre + "]"; return "[MediaAttributes: " + title + " - " + albumName + " by " + artistName + " (" + playingTimeMs + " " + mediaNumber + "/" + mediaTotalNumber + ") " + genre + "]"; } } private void updateMetadata(MediaMetadata data) { MediaAttributes oldAttributes = mMediaAttributes; mMediaAttributes = new MediaAttributes(data); if (data == null) { mSongLengthMs = 0L; private void updateCurrentMediaState() { if (mMediaController == null) { // Use A2DP state if we don't have a MediaControlller boolean isPlaying = (mA2dpState == BluetoothA2dp.STATE_PLAYING); if (isPlaying != isPlayingState(mCurrentPlayState)) { /* if a2dp is streaming, check to make sure music is active */ if (isPlaying && !mAudioManager.isMusicActive()) return; PlaybackState.Builder builder = new PlaybackState.Builder(); if (isPlaying) { builder.setState(PlaybackState.STATE_PLAYING, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f); } else { mSongLengthMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); builder.setState(PlaybackState.STATE_PAUSED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f); } updatePlaybackState(builder.build()); } // Can't get metadata from A2dp so we're done. return; } if (!oldAttributes.equals(mMediaAttributes)) { MediaAttributes currentAttributes = mMediaAttributes; PlaybackState newState = mMediaController.getPlaybackState(); // Metadata mMediaAttributes = new MediaAttributes(mMediaController.getMetadata()); if (currentAttributes.equals(mMediaAttributes)) { Log.v(TAG, "MediaAttributes Changed to " + mMediaAttributes.toString()); mTracksPlayed++; if (mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM) { mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; sendTrackChangedRsp(); } } else { Log.v(TAG, "Updated " + mMediaAttributes.toString() + " but no change!"); sendTrackChangedRsp(false); } // Update the play state, which sends play state and play position // notifications if needed. if (mMediaController != null) { updatePlaybackState(mMediaController.getPlaybackState()); } else { updatePlaybackState(null); } } private void getRcFeaturesRequestFromNative(byte[] address, int features) { Loading Loading @@ -1021,7 +1010,7 @@ public final class Avrcp { case EVT_TRACK_CHANGED: Log.v(TAG, "Track changed notification enabled"); mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM; sendTrackChangedRsp(); sendTrackChangedRsp(true); break; case EVT_PLAY_POS_CHANGED: Loading Loading @@ -1068,22 +1057,25 @@ public final class Avrcp { mHandler.sendMessage(msg); } private void sendTrackChangedRsp() { private void sendTrackChangedRsp(boolean requested) { MediaPlayerInfo info = getAddressedPlayerInfo(); if (info != null && !info.isBrowseSupported()) { // for players which does not support Browse or when no track is currently selected trackChangeRspForBrowseUnsupported(); trackChangeRspForBrowseUnsupported(requested); } else { boolean changed = mAddressedMediaPlayer.sendTrackChangeWithId(requested, mMediaController); // for players which support browsing mAddressedMediaPlayer.sendTrackChangeWithId(mTrackChangedNT, mMediaController); if (changed) mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; } } private void trackChangeRspForBrowseUnsupported() { private void trackChangeRspForBrowseUnsupported(boolean requested) { byte[] track = AvrcpConstants.TRACK_IS_SELECTED; if (mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM && !mMediaAttributes.exists) { if (requested && !mMediaAttributes.exists) { track = AvrcpConstants.NO_TRACK_SELECTED; } else if (!requested) { mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED; } registerNotificationRspTrackChangeNative(mTrackChangedNT, track); } Loading @@ -1098,7 +1090,9 @@ public final class Avrcp { } if (isPlayingState(mCurrentPlayState)) { return SystemClock.elapsedRealtime() - mLastStateUpdate + mCurrentPlayState.getPosition(); long sinceUpdate = (SystemClock.elapsedRealtime() - mCurrentPlayState.getLastPositionUpdateTime()); return sinceUpdate + mCurrentPlayState.getPosition(); } return mCurrentPlayState.getPosition(); Loading Loading @@ -2105,13 +2099,12 @@ public final class Avrcp { if (newController != null) { mMediaController = newController; mMediaController.registerCallback(mMediaControllerCb, mHandler); updateMetadata(mMediaController.getMetadata()); mAddressedMediaPlayer.updateNowPlayingList(mMediaController.getQueue()); } else { updateMetadata(null); mAddressedMediaPlayer.updateNowPlayingList(null); registerRsp = false; } updateCurrentMediaState(); } return registerRsp; } Loading Loading @@ -2264,10 +2257,8 @@ public final class Avrcp { ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags); ProfileService.println(sb, "mTracksPlayed: " + mTracksPlayed); ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState); ProfileService.println(sb, "mLastStateUpdate: " + mLastStateUpdate); ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT); ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT); ProfileService.println(sb, "mSongLengthMs: " + mSongLengthMs); ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs); ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT); ProfileService.println(sb, "mNextPosMs: " + mNextPosMs); Loading