Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aec2f01b authored by Marie Janssen's avatar Marie Janssen Committed by android-build-merger
Browse files

Merge \\\\"Refactor playback position tracking\\\\" am: 0d83e296 am: 33bbc33e am: 629be9ed

am: 720cf930

Change-Id: I7794c863f5d0906fdcd141f702d2360f5f13af4a
parents 50e4257b 720cf930
Loading
Loading
Loading
Loading
+69 −81
Original line number Diff line number Diff line
@@ -62,14 +62,13 @@ public final class Avrcp {
    private MediaAttributes mMediaAttributes;
    private int mTransportControlFlags;
    private PlaybackState mCurrentPlayState;
    private long mLastStateUpdate;
    private int mPlayStatusChangedNT;
    private int mTrackChangedNT;
    private int mPlayPosChangedNT;
    private long mTrackNumber;
    private long mCurrentPosMs;
    private long mPlayStartTimeMs;
    private long mSongLengthMs;
    private long mPlaybackIntervalMs;
    private int mPlayPosChangedNT;
    private long mNextPosMs;
    private long mPrevPosMs;
    private long mSkipStartTime;
@@ -144,8 +143,7 @@ public final class Avrcp {
        mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED;
        mTrackChangedNT = NOTIFICATION_TYPE_CHANGED;
        mTrackNumber = -1L;
        mCurrentPosMs = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
        mPlayStartTimeMs = -1L;
        mLastStateUpdate = -1L;
        mSongLengthMs = 0L;
        mPlaybackIntervalMs = 0L;
        mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED;
@@ -220,7 +218,7 @@ public final class Avrcp {
        @Override
        public void onPlaybackStateChanged(PlaybackState state) {
            Log.v(TAG, "MediaController playback changed: " + state.toString());
            updatePlayPauseState(state);
            updatePlaybackState(state);
        }

        @Override
@@ -261,12 +259,12 @@ public final class Avrcp {
        mMediaController = controller;
        if (mMediaController == null) {
            updateMetadata(null);
            updatePlayPauseState(null);
            updatePlaybackState(null);
            return;
        }
        mMediaController.registerCallback(mMediaControllerCb, mHandler);
        updateMetadata(mMediaController.getMetadata());
        updatePlayPauseState(mMediaController.getPlaybackState());
        updatePlaybackState(mMediaController.getPlaybackState());
    }

    /** Handles Avrcp messages. */
@@ -325,8 +323,7 @@ public final class Avrcp {

            case MESSAGE_PLAY_INTERVAL_TIMEOUT:
                if (DEBUG) Log.v(TAG, "MESSAGE_PLAY_INTERVAL_TIMEOUT");
                mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED;
                registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)getPlayPosition());
                sendPlayPosNotificationRsp(false);
                break;

            case MESSAGE_VOLUME_CHANGED:
@@ -624,56 +621,25 @@ public final class Avrcp {
                builder.setState(PlaybackState.STATE_PAUSED,
                                 PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f);
            }
            updatePlayPauseState(builder.build());
            updatePlaybackState(builder.build());
        }
    }

    private void updatePlayPauseState(PlaybackState state) {
    private void updatePlaybackState(PlaybackState state) {
        if (DEBUG) Log.v(TAG,
                "updatePlayPauseState: old=" + mCurrentPlayState + ", state=" + state);
                "updatePlaybackState: old=" + mCurrentPlayState + ", new=" + state);
        if (state == null) {
          state = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE,
                         PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f).build();
        }
        boolean oldPosValid = (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN);

        int oldPlayStatus = convertPlayStateToPlayStatus(mCurrentPlayState);
        int newPlayStatus = convertPlayStateToPlayStatus(state);

        if ((mCurrentPlayState.getState() == PlaybackState.STATE_PLAYING) &&
                (mCurrentPlayState != state) && oldPosValid) {
            mCurrentPosMs = getPlayPosition();
        }

        if (state.getState() == PlaybackState.STATE_NONE ||
                state.getState() == PlaybackState.STATE_ERROR) {
            mCurrentPosMs = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
        } else {
            mCurrentPosMs = state.getPosition();
        }

        if ((state.getState() == PlaybackState.STATE_PLAYING) &&
                (mCurrentPlayState.getState() != PlaybackState.STATE_PLAYING)) {
            mPlayStartTimeMs = SystemClock.elapsedRealtime();
        }

        mCurrentPlayState = state;
        mLastStateUpdate = SystemClock.elapsedRealtime();

        boolean newPosValid = mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN;
        long playPosition = getPlayPosition();

        mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT);
        /* need send play position changed notification when play status is changed */
        if ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) &&
                ((oldPlayStatus != newPlayStatus) || (oldPosValid != newPosValid) ||
                 (newPosValid && ((playPosition >= mNextPosMs) || (playPosition <= mPrevPosMs))))) {
            mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED;
            registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)playPosition);
        }
        if ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) && newPosValid &&
                (state.getState() == PlaybackState.STATE_PLAYING)) {
            Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT);
            mHandler.sendMessageDelayed(msg, mNextPosMs - playPosition);
        }
        sendPlayPosNotificationRsp(false);

        if ((mPlayStatusChangedNT == NOTIFICATION_TYPE_INTERIM) && (oldPlayStatus != newPlayStatus)) {
            mPlayStatusChangedNT = NOTIFICATION_TYPE_CHANGED;
@@ -804,22 +770,14 @@ public final class Avrcp {
        if (!oldAttributes.equals(mMediaAttributes)) {
            Log.v(TAG, "MediaAttributes Changed to " + mMediaAttributes.toString());
            mTrackNumber++;

            // Update the play state, which sends a notification if needed.
            updatePlaybackState(mMediaController.getPlaybackState());

            if (mTrackChangedNT == NOTIFICATION_TYPE_INTERIM) {
                mTrackChangedNT = NOTIFICATION_TYPE_CHANGED;
                sendTrackChangedRsp();
            }

            if (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN &&
                isPlayingState(mCurrentPlayState)) {
                mPlayStartTimeMs = SystemClock.elapsedRealtime();
            }
            /* need send play position changed notification when track is changed */
            if (mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) {
                mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED;
                registerNotificationRspPlayPosNative(mPlayPosChangedNT,
                        (int)getPlayPosition());
                mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT);
            }
        } else {
            Log.v(TAG, "Updated " + mMediaAttributes.toString() + " but no change!");
        }
@@ -867,18 +825,9 @@ public final class Avrcp {
                break;

            case EVT_PLAY_POS_CHANGED:
                long songPosition = getPlayPosition();
                mPlayPosChangedNT = NOTIFICATION_TYPE_INTERIM;
                sendPlayPosNotificationRsp(true);
                mPlaybackIntervalMs = (long)param * 1000L;
                if (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) {
                    mNextPosMs = songPosition + mPlaybackIntervalMs;
                    mPrevPosMs = songPosition - mPlaybackIntervalMs;
                    if (isPlayingState(mCurrentPlayState)) {
                        Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT);
                        mHandler.sendMessageDelayed(msg, mPlaybackIntervalMs);
                    }
                }
                registerNotificationRspPlayPosNative(mPlayPosChangedNT, (int)songPosition);
                break;

        }
@@ -938,17 +887,17 @@ public final class Avrcp {
    }

    private long getPlayPosition() {
        long songPosition = -1L;
        if (mCurrentPosMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) {
            if (mCurrentPlayState.getState() == PlaybackState.STATE_PLAYING) {
                songPosition = SystemClock.elapsedRealtime() -
                        mPlayStartTimeMs + mCurrentPosMs;
            } else {
                songPosition = mCurrentPosMs;
            }
        if (mCurrentPlayState == null)
            return -1L;

        if (mCurrentPlayState.getPosition() == PlaybackState.PLAYBACK_POSITION_UNKNOWN)
            return -1L;

        if (isPlayingState(mCurrentPlayState)) {
            return SystemClock.elapsedRealtime() - mLastStateUpdate + mCurrentPlayState.getPosition();
        }
        if (DEBUG) Log.v(TAG, "position=" + songPosition);
        return songPosition;

        return -1L;
    }

    private int convertPlayStateToPlayStatus(PlaybackState state) {
@@ -992,6 +941,44 @@ public final class Avrcp {
               (state.getState() == PlaybackState.STATE_BUFFERING);
    }

    /**
     * Sends a play position notification, or schedules one to be
     * sent later at an appropriate time. If |requested| is true,
     * does both because this was called in reponse to a request from the
     * TG.
     */
    private void sendPlayPosNotificationRsp(boolean requested) {
        long playPositionMs = getPlayPosition();

        // mNextPosMs is set to -1 when the previous position was invalid
        // so this will be true if the new position is valid & old was invalid.
        // mPlayPositionMs is set to -1 when the new position is invalid,
        // and the old mPrevPosMs is >= 0 so this is true when the new is invalid
        // and the old was valid.
        if (requested || ((mPlayPosChangedNT == NOTIFICATION_TYPE_INTERIM) &&
             ((playPositionMs >= mNextPosMs) || (playPositionMs <= mPrevPosMs)))) {
            if (!requested) mPlayPosChangedNT = NOTIFICATION_TYPE_CHANGED;
            registerNotificationRspPlayPosNative(mPlayStatusChangedNT, (int)playPositionMs);
            if (playPositionMs != PlaybackState.PLAYBACK_POSITION_UNKNOWN) {
                mNextPosMs = playPositionMs + mPlaybackIntervalMs;
                mPrevPosMs = playPositionMs - mPlaybackIntervalMs;
            } else {
                mNextPosMs = -1;
                mPrevPosMs = -1;
            }
        }

        mHandler.removeMessages(MESSAGE_PLAY_INTERVAL_TIMEOUT);
        if (mPlayStatusChangedNT == NOTIFICATION_TYPE_INTERIM) {
            Message msg = mHandler.obtainMessage(MESSAGE_PLAY_INTERVAL_TIMEOUT);
            long delay = mPlaybackIntervalMs;
            if (mNextPosMs != -1) {
                delay = mNextPosMs - (playPositionMs > 0 ? playPositionMs : 0);
            }
            mHandler.sendMessageDelayed(msg, delay);
        }
    }

    /**
     * This is called from AudioService. It will return whether this device supports abs volume.
     * NOT USED AT THE MOMENT.
@@ -1090,11 +1077,10 @@ public final class Avrcp {
        ProfileService.println(sb, "mMediaAttributes: " + mMediaAttributes);
        ProfileService.println(sb, "mTransportControlFlags: " + mTransportControlFlags);
        ProfileService.println(sb, "mCurrentPlayState: " + mCurrentPlayState);
        ProfileService.println(sb, "mLastStateUpdate: " + mLastStateUpdate);
        ProfileService.println(sb, "mPlayStatusChangedNT: " + mPlayStatusChangedNT);
        ProfileService.println(sb, "mTrackChangedNT: " + mTrackChangedNT);
        ProfileService.println(sb, "mTrackNumber: " + mTrackNumber);
        ProfileService.println(sb, "mCurrentPosMs: " + mCurrentPosMs);
        ProfileService.println(sb, "mPlayStartTimeMs: " + mPlayStartTimeMs);
        ProfileService.println(sb, "mSongLengthMs: " + mSongLengthMs);
        ProfileService.println(sb, "mPlaybackIntervalMs: " + mPlaybackIntervalMs);
        ProfileService.println(sb, "mPlayPosChangedNT: " + mPlayPosChangedNT);
@@ -1112,6 +1098,8 @@ public final class Avrcp {
        ProfileService.println(sb, "mAbsVolRetryTimes: " + mAbsVolRetryTimes);
        ProfileService.println(sb, "mSkipAmount: " + mSkipAmount);
        ProfileService.println(sb, "mVolumeMapping: " + mVolumeMapping.toString());
        if (mMediaController != null)
            ProfileService.println(sb, "mMediaSession pkg: " + mMediaController.getPackageName());
    }

    // Do not modify without updating the HAL bt_rc.h files.