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

Commit 974753ca authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4383937 from 76aab6db to oc-mr1-release

Change-Id: Ib869ad8809c62dd985a589aac41d3f61070910ae
parents 105440e9 76aab6db
Loading
Loading
Loading
Loading
+58 −21
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.browse.MediaBrowser;
@@ -78,6 +79,8 @@ public final class Avrcp {
    private Context mContext;
    private final AudioManager mAudioManager;
    private AvrcpMessageHandler mHandler;
    private Handler mAudioManagerPlaybackHandler;
    private AudioManagerPlaybackListener mAudioManagerPlaybackCb;
    private MediaSessionManager mMediaSessionManager;
    private @Nullable MediaController mMediaController;
    private MediaControllerListener mMediaControllerCb;
@@ -87,6 +90,7 @@ public final class Avrcp {
    private int mTransportControlFlags;
    private @NonNull PlaybackState mCurrentPlayState;
    private int mA2dpState;
    private boolean mAudioManagerIsPlaying;
    private int mPlayStatusChangedNT;
    private byte mReportedPlayStatus;
    private int mTrackChangedNT;
@@ -240,6 +244,7 @@ public final class Avrcp {
        mCurrentPlayState = new PlaybackState.Builder().setState(PlaybackState.STATE_NONE, -1L, 0.0f).build();
        mReportedPlayStatus = PLAYSTATUS_ERROR;
        mA2dpState = BluetoothA2dp.STATE_NOT_PLAYING;
        mAudioManagerIsPlaying = false;
        mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
        mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
        mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
@@ -307,6 +312,8 @@ public final class Avrcp {
        thread.start();
        Looper looper = thread.getLooper();
        mHandler = new AvrcpMessageHandler(looper);
        mAudioManagerPlaybackHandler = new Handler(looper);
        mAudioManagerPlaybackCb = new AudioManagerPlaybackListener();
        mMediaControllerCb = new MediaControllerListener();
        mAvrcpMediaRsp = new AvrcpMediaRsp();
        mMediaPlayerInfoList = new TreeMap<Integer, MediaPlayerInfo>();
@@ -336,6 +343,9 @@ public final class Avrcp {
            // initialize browsable player list and build media player list
            buildBrowsablePlayerList();
        }

        mAudioManager.registerAudioPlaybackCallback(
                mAudioManagerPlaybackCb, mAudioManagerPlaybackHandler);
    }

    public static Avrcp make(Context context) {
@@ -347,18 +357,23 @@ public final class Avrcp {

    public synchronized void doQuit() {
        if (DEBUG) Log.d(TAG, "doQuit");
        if (mAudioManager != null) {
            mAudioManager.unregisterAudioPlaybackCallback(mAudioManagerPlaybackCb);
        }
        if (mMediaController != null) mMediaController.unregisterCallback(mMediaControllerCb);
        if (mMediaSessionManager != null) {
            mMediaSessionManager.setCallback(null, null);
            mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveSessionListener);
        }

        mAudioManagerPlaybackHandler.removeCallbacksAndMessages(null);
        mHandler.removeCallbacksAndMessages(null);
        Looper looper = mHandler.getLooper();
        if (looper != null) {
            looper.quit();
        }

        mAudioManagerPlaybackHandler = null;
        mHandler = null;
        mContext.unregisterReceiver(mAvrcpReceiver);
        mContext.unregisterReceiver(mBootReceiver);
@@ -374,6 +389,30 @@ public final class Avrcp {
            mVolumeMapping.clear();
    }

    private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback {
        @Override
        public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
            super.onPlaybackConfigChanged(configs);
            boolean isPlaying = false;
            for (AudioPlaybackConfiguration config : configs) {
                if (DEBUG) {
                    Log.d(TAG,
                            "AudioManager Player: "
                                    + AudioPlaybackConfiguration.toLogFriendlyString(config));
                }
                if (config.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    isPlaying = true;
                    break;
                }
            }
            if (DEBUG) Log.d(TAG, "AudioManager isPlaying: " + isPlaying);
            if (mAudioManagerIsPlaying != isPlaying) {
                mAudioManagerIsPlaying = isPlaying;
                updateCurrentMediaState();
            }
        }
    }

    private class MediaControllerListener extends MediaController.Callback {
        @Override
        public void onMetadataChanged(MediaMetadata metadata) {
@@ -807,10 +846,22 @@ public final class Avrcp {

            if (controllerState != null) {
                newState = controllerState;
            } else if (mAudioManager != null && mAudioManager.isMusicActive()) {
                // Use A2DP state if we don't have a state from MediaControlller
            }
            // Use the AudioManager to update the playback state.
            // NOTE: We cannot use the
            //    (mA2dpState == BluetoothA2dp.STATE_PLAYING)
            // check, because after Pause, the A2DP state remains in
            // STATE_PLAYING for 3 more seconds.
            // As a result of that, if we pause the music, on carkits the
            // Play status indicator will continue to display "Playing"
            // for 3 more seconds which can be confusing.
            if (mAudioManagerIsPlaying
                    || (controllerState == null && mAudioManager != null
                               && mAudioManager.isMusicActive())) {
                // Use AudioManager playback state if we don't have the state
                // from MediaControlller
                PlaybackState.Builder builder = new PlaybackState.Builder();
                if (mA2dpState == BluetoothA2dp.STATE_PLAYING) {
                if (mAudioManagerIsPlaying) {
                    builder.setState(PlaybackState.STATE_PLAYING,
                            PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f);
                } else {
@@ -1026,22 +1077,6 @@ public final class Avrcp {
                mAddressedMediaPlayer.updateNowPlayingList(mMediaController);
            }

            if ((newQueueId == -1 || newQueueId != mLastQueueId)
                    && currentAttributes.equals(mMediaAttributes)
                    && newPlayStatus == PLAYSTATUS_PLAYING
                    && mReportedPlayStatus == PLAYSTATUS_STOPPED) {
                // Most carkits like seeing the track changed before the
                // playback state changed, but some controllers are slow
                // to update their metadata. Hold of on sending the playback state
                // update until after we know the current metadata is up to date
                // and track changed has been sent. This was seen on BMW carkits
                Log.i(TAG,
                        "Waiting for metadata update to send track changed: " + newQueueId + " : "
                                + currentAttributes + " : " + mMediaAttributes);

                return;
            }

            // Notify track changed if:
            //  - The CT is registered for the notification
            //  - Queue ID is UNKNOWN and MediaMetadata is different
@@ -1060,9 +1095,11 @@ public final class Avrcp {
        }

        // still send the updated play state if the playback state is none or buffering
        Log.e(TAG, "play status change " + mReportedPlayStatus + "➡" + newPlayStatus);
        Log.e(TAG,
                "play status change " + mReportedPlayStatus + "➡" + newPlayStatus
                        + " mPlayStatusChangedNT: " + mPlayStatusChangedNT);
        if (mPlayStatusChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM
                && (mReportedPlayStatus != newPlayStatus)) {
                || (mReportedPlayStatus != newPlayStatus)) {
            sendPlaybackStatus(AvrcpConstants.NOTIFICATION_TYPE_CHANGED, newPlayStatus);
        }

+35 −11
Original line number Diff line number Diff line
@@ -437,12 +437,16 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
            mWakeLock = null;
        }

        // Step 1: clean up active server session
        if (mServerSession != null) {
            mServerSession.close();
            mServerSession = null;
        }

        // Step 2: clean up existing connection socket
        closeConnectionSocket();
        // Step 3: clean up SDP record
        cleanUpSdpRecord();
        // Step 4: clean up existing server socket(s)
        closeServerSocket();
        if (mServerSockets != null) {
            mServerSockets.shutdown(false);
@@ -452,6 +456,24 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
        if (VERBOSE) Log.v(TAG, "Pbap Service closeService out");
    }

    private void cleanUpSdpRecord() {
        if (mSdpHandle < 0) {
            if (VERBOSE) Log.v(TAG, "cleanUpSdpRecord, SDP record never created");
            return;
        }
        int sdpHandle = mSdpHandle;
        mSdpHandle = -1;
        SdpManager sdpManager = SdpManager.getDefaultManager();
        if (sdpManager == null) {
            Log.e(TAG, "cleanUpSdpRecord failed, sdpManager is null, sdpHandle=" + sdpHandle);
            return;
        }
        Log.i(TAG, "cleanUpSdpRecord, mSdpHandle=" + sdpHandle);
        if (!sdpManager.removeSdpRecord(sdpHandle)) {
            Log.e(TAG, "cleanUpSdpRecord, removeSdpRecord failed, sdpHandle=" + sdpHandle);
        }
    }

    private final void startObexServerSession() throws IOException {
        if (VERBOSE) Log.v(TAG, "Pbap Service startObexServerSession");

@@ -939,6 +961,10 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
        }
    }

    /**
     * Start server side socket listeners. Caller should make sure that adapter is in a ready state
     * and SDP record is cleaned up. Otherwise, this method will fail.
     */
    synchronized private void startSocketListeners() {
        if (DEBUG) Log.d(TAG, "startsocketListener");
        if (mServerSession != null) {
@@ -956,17 +982,10 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
                Log.e(TAG, "Failed to start the listeners");
                return;
            }
            SdpManager sdpManager = SdpManager.getDefaultManager();
            if (sdpManager == null) {
                Log.e(TAG, "Failed to start the listeners sdp null ");
            if (mSdpHandle >= 0) {
                Log.e(TAG, "SDP handle was not cleaned up, mSdpHandle=" + mSdpHandle);
                return;
            }
            if (mAdapter != null && mSdpHandle >= 0) {
                Log.d(TAG, "Removing SDP record for PBAP with SDP handle:" + mSdpHandle);
                boolean status = sdpManager.removeSdpRecord(mSdpHandle);
                Log.d(TAG, "RemoveSDPrecord returns " + status);
                mSdpHandle = -1;
            }
            mSdpHandle = SdpManager.getDefaultManager().createPbapPseRecord(
                    "OBEX Phonebook Access Server", mServerSockets.getRfcommChannel(),
                    mServerSockets.getL2capPsm(), SDP_PBAP_SERVER_VERSION,
@@ -1057,8 +1076,13 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
     */
    @Override
    public synchronized void onAcceptFailed() {
        // Clean up SDP record first
        cleanUpSdpRecord();
        // Force socket listener to restart
        if (mServerSockets != null) {
            mServerSockets.shutdown(false);
            mServerSockets = null;
        }
        if (!mInterrupted && mAdapter != null && mAdapter.isEnabled()) {
            startSocketListeners();
        }