• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.audio_util;
18 
19 import android.support.v4.media.session.MediaControllerCompat;
20 import android.support.v4.media.session.MediaSessionCompat;
21 import android.support.v4.media.session.PlaybackStateCompat;
22 
23 import com.android.bluetooth.avrcp.AvrcpTargetService;
24 
25 /**
26  * Manager class for player apps.
27  */
28 public class PlayerSettingsManager {
29     private static final String TAG = "PlayerSettingsManager";
30 
31     private final MediaPlayerList mMediaPlayerList;
32     private final AvrcpTargetService mService;
33 
34     private MediaControllerCompat mActivePlayerController;
35     private final MediaControllerCallback mControllerCallback;
36 
37     /**
38      * Instantiates a new PlayerSettingsManager.
39      *
40      * @param mediaPlayerList is used to retrieve the current active player.
41      */
PlayerSettingsManager(MediaPlayerList mediaPlayerList, AvrcpTargetService service)42     public PlayerSettingsManager(MediaPlayerList mediaPlayerList, AvrcpTargetService service) {
43         mService = service;
44         mMediaPlayerList = mediaPlayerList;
45         mMediaPlayerList.setPlayerSettingsCallback(
46                 (mediaPlayerWrapper) -> activePlayerChanged(mediaPlayerWrapper));
47         mControllerCallback = new MediaControllerCallback();
48 
49         MediaPlayerWrapper wrapper = mMediaPlayerList.getActivePlayer();
50         if (wrapper != null) {
51             mActivePlayerController = new MediaControllerCompat(mService,
52                     MediaSessionCompat.Token.fromToken(wrapper.getSessionToken()));
53             mActivePlayerController.registerCallback(mControllerCallback);
54         } else {
55             mActivePlayerController = null;
56         }
57     }
58 
59     /**
60      * Unregister callbacks
61      */
cleanup()62     public void cleanup() {
63         updateRemoteDevice();
64         if (mActivePlayerController != null) {
65             mActivePlayerController.unregisterCallback(mControllerCallback);
66         }
67     }
68 
69     /**
70      * Updates the active player controller.
71      */
activePlayerChanged(MediaPlayerWrapper mediaPlayerWrapper)72     private void activePlayerChanged(MediaPlayerWrapper mediaPlayerWrapper) {
73         if (mActivePlayerController != null) {
74             mActivePlayerController.unregisterCallback(mControllerCallback);
75         }
76         if (mediaPlayerWrapper != null) {
77             mActivePlayerController = new MediaControllerCompat(mService,
78                     MediaSessionCompat.Token.fromToken(mediaPlayerWrapper.getSessionToken()));
79             mActivePlayerController.registerCallback(mControllerCallback);
80         } else {
81             mActivePlayerController = null;
82             updateRemoteDevice();
83         }
84     }
85 
86     /**
87      * Sends the MediaController values of the active player to the remote device.
88      *
89      * This is called when:
90      * - The class is created and the session is ready
91      * - The class is destroyed
92      * - The active player changed and the session is ready
93      * - The last active player has been removed
94      * - The repeat / shuffle player state changed
95      */
updateRemoteDevice()96     private void updateRemoteDevice() {
97         mService.sendPlayerSettings(getPlayerRepeatMode(), getPlayerShuffleMode());
98     }
99 
100     /**
101      * Called from remote device to set the active player repeat mode.
102      */
setPlayerRepeatMode(int repeatMode)103     public boolean setPlayerRepeatMode(int repeatMode) {
104         if (mActivePlayerController == null) {
105             return false;
106         }
107         MediaControllerCompat.TransportControls controls =
108                 mActivePlayerController.getTransportControls();
109         switch (repeatMode) {
110             case PlayerSettingsValues.STATE_REPEAT_OFF:
111                 controls.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_NONE);
112                 return true;
113             case PlayerSettingsValues.STATE_REPEAT_SINGLE_TRACK:
114                 controls.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_ONE);
115                 return true;
116             case PlayerSettingsValues.STATE_REPEAT_GROUP:
117                 controls.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_GROUP);
118                 return true;
119             case PlayerSettingsValues.STATE_REPEAT_ALL_TRACK:
120                 controls.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_ALL);
121                 return true;
122             default:
123                 controls.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_NONE);
124                 return false;
125         }
126     }
127 
128     /**
129      * Called from remote device to set the active player shuffle mode.
130      */
setPlayerShuffleMode(int shuffleMode)131     public boolean setPlayerShuffleMode(int shuffleMode) {
132         if (mActivePlayerController == null) {
133             return false;
134         }
135         MediaControllerCompat.TransportControls controls =
136                 mActivePlayerController.getTransportControls();
137         switch (shuffleMode) {
138             case PlayerSettingsValues.STATE_SHUFFLE_OFF:
139                 controls.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_NONE);
140                 return true;
141             case PlayerSettingsValues.STATE_SHUFFLE_GROUP:
142                 controls.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_GROUP);
143                 return true;
144             case PlayerSettingsValues.STATE_SHUFFLE_ALL_TRACK:
145                 controls.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_ALL);
146                 return true;
147             default:
148                 controls.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_NONE);
149                 return false;
150         }
151     }
152 
153     /**
154      * Retrieves & converts the repeat value of the active player MediaController to AVRCP values
155      */
getPlayerRepeatMode()156     public int getPlayerRepeatMode() {
157         if (mActivePlayerController == null) {
158             return PlayerSettingsValues.STATE_REPEAT_OFF;
159         }
160         int mediaFwkMode = mActivePlayerController.getRepeatMode();
161         switch (mediaFwkMode) {
162             case PlaybackStateCompat.REPEAT_MODE_NONE:
163                 return PlayerSettingsValues.STATE_REPEAT_OFF;
164             case PlaybackStateCompat.REPEAT_MODE_ONE:
165                 return PlayerSettingsValues.STATE_REPEAT_SINGLE_TRACK;
166             case PlaybackStateCompat.REPEAT_MODE_GROUP:
167                 return PlayerSettingsValues.STATE_REPEAT_GROUP;
168             case PlaybackStateCompat.REPEAT_MODE_ALL:
169                 return PlayerSettingsValues.STATE_REPEAT_ALL_TRACK;
170             case PlaybackStateCompat.REPEAT_MODE_INVALID:
171                 return PlayerSettingsValues.STATE_REPEAT_OFF;
172             default:
173                 return PlayerSettingsValues.STATE_REPEAT_OFF;
174         }
175     }
176 
177     /**
178      * Retrieves & converts the shuffle value of the active player MediaController to AVRCP values
179      */
getPlayerShuffleMode()180     public int getPlayerShuffleMode() {
181         if (mActivePlayerController == null) {
182             return PlayerSettingsValues.STATE_SHUFFLE_OFF;
183         }
184         int mediaFwkMode = mActivePlayerController.getShuffleMode();
185         switch (mediaFwkMode) {
186             case PlaybackStateCompat.SHUFFLE_MODE_NONE:
187                 return PlayerSettingsValues.STATE_SHUFFLE_OFF;
188             case PlaybackStateCompat.SHUFFLE_MODE_GROUP:
189                 return PlayerSettingsValues.STATE_SHUFFLE_GROUP;
190             case PlaybackStateCompat.SHUFFLE_MODE_ALL:
191                 return PlayerSettingsValues.STATE_SHUFFLE_ALL_TRACK;
192             case PlaybackStateCompat.SHUFFLE_MODE_INVALID:
193                 return PlayerSettingsValues.STATE_SHUFFLE_OFF;
194             default:
195                 return PlayerSettingsValues.STATE_SHUFFLE_OFF;
196         }
197     }
198 
199     // Receives callbacks from the MediaControllerCompat.
200     private class MediaControllerCallback extends MediaControllerCompat.Callback {
201         @Override
onRepeatModeChanged(final int repeatMode)202         public void onRepeatModeChanged(final int repeatMode) {
203             updateRemoteDevice();
204         }
205 
206         @Override
onSessionReady()207         public void onSessionReady() {
208             updateRemoteDevice();
209         }
210 
211         @Override
onShuffleModeChanged(final int shuffleMode)212         public void onShuffleModeChanged(final int shuffleMode) {
213             updateRemoteDevice();
214         }
215     }
216 
217     /**
218      * Class containing all the Shuffle/Repeat values as defined in the BT spec.
219      */
220     public static final class PlayerSettingsValues {
221         /**
222          * Repeat setting, as defined by Bluetooth specification.
223          */
224         public static final int SETTING_REPEAT = 2;
225 
226         /**
227          * Shuffle setting, as defined by Bluetooth specification.
228          */
229         public static final int SETTING_SHUFFLE = 3;
230 
231         /**
232          * Repeat OFF state, as defined by Bluetooth specification.
233          */
234         public static final int STATE_REPEAT_OFF = 1;
235 
236         /**
237          * Single track repeat, as defined by Bluetooth specification.
238          */
239         public static final int STATE_REPEAT_SINGLE_TRACK = 2;
240 
241         /**
242          * All track repeat, as defined by Bluetooth specification.
243          */
244         public static final int STATE_REPEAT_ALL_TRACK = 3;
245 
246         /**
247          * Group repeat, as defined by Bluetooth specification.
248          */
249         public static final int STATE_REPEAT_GROUP = 4;
250 
251         /**
252          * Shuffle OFF state, as defined by Bluetooth specification.
253          */
254         public static final int STATE_SHUFFLE_OFF = 1;
255 
256         /**
257          * All track shuffle, as defined by Bluetooth specification.
258          */
259         public static final int STATE_SHUFFLE_ALL_TRACK = 2;
260 
261         /**
262          * Group shuffle, as defined by Bluetooth specification.
263          */
264         public static final int STATE_SHUFFLE_GROUP = 3;
265 
266         /**
267          * Default state off.
268          */
269         public static final int STATE_DEFAULT_OFF = 1;
270     }
271 }
272