1/*
2 * Copyright (C) 2014 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
17package android.support.v4.media.session;
18
19import android.app.PendingIntent;
20import android.content.Context;
21import android.media.AudioAttributes;
22import android.media.AudioManager;
23import android.media.MediaMetadata;
24import android.media.Rating;
25import android.media.session.MediaController;
26import android.media.session.MediaSession;
27import android.media.session.PlaybackState;
28import android.os.Bundle;
29import android.os.Handler;
30import android.os.Parcel;
31import android.os.ResultReceiver;
32import android.view.KeyEvent;
33
34import java.util.ArrayList;
35import java.util.List;
36
37class MediaControllerCompatApi21 {
38    public static Object fromToken(Context context, Object sessionToken) {
39        return new MediaController(context, (MediaSession.Token) sessionToken);
40    }
41
42    public static Object createCallback(Callback callback) {
43        return new CallbackProxy<Callback>(callback);
44    }
45
46    public static void registerCallback(Object controllerObj, Object callbackObj, Handler handler) {
47        ((MediaController) controllerObj).registerCallback(
48                (MediaController.Callback)callbackObj, handler);
49    }
50
51    public static void unregisterCallback(Object controllerObj, Object callbackObj) {
52        ((MediaController) controllerObj)
53                .unregisterCallback((MediaController.Callback) callbackObj);
54    }
55
56    public static Object getTransportControls(Object controllerObj) {
57        return ((MediaController)controllerObj).getTransportControls();
58    }
59
60    public static Object getPlaybackState(Object controllerObj) {
61        return ((MediaController)controllerObj).getPlaybackState();
62    }
63
64    public static Object getMetadata(Object controllerObj) {
65        return ((MediaController)controllerObj).getMetadata();
66    }
67
68    public static List<Object> getQueue(Object controllerObj) {
69        List<MediaSession.QueueItem> queue = ((MediaController) controllerObj).getQueue();
70        if (queue == null) {
71            return null;
72        }
73        List<Object> queueObjs = new ArrayList<Object>(queue);
74        return queueObjs;
75    }
76
77    public static CharSequence getQueueTitle(Object controllerObj) {
78        return ((MediaController) controllerObj).getQueueTitle();
79    }
80
81    public static Bundle getExtras(Object controllerObj) {
82        return ((MediaController) controllerObj).getExtras();
83    }
84
85    public static int getRatingType(Object controllerObj) {
86        return ((MediaController) controllerObj).getRatingType();
87    }
88
89    public static long getFlags(Object controllerObj) {
90        return ((MediaController) controllerObj).getFlags();
91    }
92
93    public static Object getPlaybackInfo(Object controllerObj) {
94        return ((MediaController) controllerObj).getPlaybackInfo();
95    }
96
97    public static PendingIntent getSessionActivity(Object controllerObj) {
98        return ((MediaController) controllerObj).getSessionActivity();
99    }
100
101    public static boolean dispatchMediaButtonEvent(Object controllerObj, KeyEvent event) {
102        return ((MediaController) controllerObj).dispatchMediaButtonEvent(event);
103    }
104
105    public static void setVolumeTo(Object controllerObj, int value, int flags) {
106        ((MediaController) controllerObj).setVolumeTo(value, flags);
107    }
108
109    public static void adjustVolume(Object controllerObj, int direction, int flags) {
110        ((MediaController) controllerObj).adjustVolume(direction, flags);
111    }
112
113    public static void sendCommand(Object controllerObj,
114            String command, Bundle params, ResultReceiver cb) {
115        ((MediaController) controllerObj).sendCommand(command, params, cb);
116    }
117
118    public static String getPackageName(Object controllerObj) {
119        return ((MediaController) controllerObj).getPackageName();
120    }
121
122    public static class TransportControls {
123        public static void play(Object controlsObj) {
124            ((MediaController.TransportControls)controlsObj).play();
125        }
126
127        public static void pause(Object controlsObj) {
128            ((MediaController.TransportControls)controlsObj).pause();
129        }
130
131        public static void stop(Object controlsObj) {
132            ((MediaController.TransportControls)controlsObj).stop();
133        }
134
135        public static void seekTo(Object controlsObj, long pos) {
136            ((MediaController.TransportControls)controlsObj).seekTo(pos);
137        }
138
139        public static void fastForward(Object controlsObj) {
140            ((MediaController.TransportControls)controlsObj).fastForward();
141        }
142
143        public static void rewind(Object controlsObj) {
144            ((MediaController.TransportControls)controlsObj).rewind();
145        }
146
147        public static void skipToNext(Object controlsObj) {
148            ((MediaController.TransportControls)controlsObj).skipToNext();
149        }
150
151        public static void skipToPrevious(Object controlsObj) {
152            ((MediaController.TransportControls)controlsObj).skipToPrevious();
153        }
154
155        public static void setRating(Object controlsObj, Object ratingObj) {
156            ((MediaController.TransportControls)controlsObj).setRating((Rating)ratingObj);
157        }
158
159        public static void playFromMediaId(Object controlsObj, String mediaId, Bundle extras) {
160            ((MediaController.TransportControls) controlsObj).playFromMediaId(mediaId, extras);
161        }
162
163        public static void playFromSearch(Object controlsObj, String query, Bundle extras) {
164            ((MediaController.TransportControls) controlsObj).playFromSearch(query, extras);
165        }
166
167        public static void skipToQueueItem(Object controlsObj, long id) {
168            ((MediaController.TransportControls) controlsObj).skipToQueueItem(id);
169        }
170
171        public static void sendCustomAction(Object controlsObj, String action, Bundle args) {
172            ((MediaController.TransportControls) controlsObj).sendCustomAction(action, args);
173        }
174    }
175
176    public static class PlaybackInfo {
177        public static int getPlaybackType(Object volumeInfoObj) {
178            return ((MediaController.PlaybackInfo)volumeInfoObj).getPlaybackType();
179        }
180
181        public static AudioAttributes getAudioAttributes(Object volumeInfoObj) {
182            return ((MediaController.PlaybackInfo) volumeInfoObj).getAudioAttributes();
183        }
184
185        public static int getLegacyAudioStream(Object volumeInfoObj) {
186            AudioAttributes attrs = getAudioAttributes(volumeInfoObj);
187            return toLegacyStreamType(attrs);
188        }
189
190        public static int getVolumeControl(Object volumeInfoObj) {
191            return ((MediaController.PlaybackInfo)volumeInfoObj).getVolumeControl();
192        }
193
194        public static int getMaxVolume(Object volumeInfoObj) {
195            return ((MediaController.PlaybackInfo)volumeInfoObj).getMaxVolume();
196        }
197
198        public static int getCurrentVolume(Object volumeInfoObj) {
199            return ((MediaController.PlaybackInfo)volumeInfoObj).getCurrentVolume();
200        }
201
202        // This is copied from AudioAttributes.toLegacyStreamType. TODO This
203        // either needs to be kept in sync with that one or toLegacyStreamType
204        // needs to be made public so it can be used by the support lib.
205        private static final int FLAG_SCO = 0x1 << 2;
206        private static final int STREAM_BLUETOOTH_SCO = 6;
207        private static final int STREAM_SYSTEM_ENFORCED = 7;
208        private static int toLegacyStreamType(AudioAttributes aa) {
209            // flags to stream type mapping
210            if ((aa.getFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
211                    == AudioAttributes.FLAG_AUDIBILITY_ENFORCED) {
212                return STREAM_SYSTEM_ENFORCED;
213            }
214            if ((aa.getFlags() & FLAG_SCO) == FLAG_SCO) {
215                return STREAM_BLUETOOTH_SCO;
216            }
217
218            // usage to stream type mapping
219            switch (aa.getUsage()) {
220                case AudioAttributes.USAGE_MEDIA:
221                case AudioAttributes.USAGE_GAME:
222                case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
223                case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
224                    return AudioManager.STREAM_MUSIC;
225                case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
226                    return AudioManager.STREAM_SYSTEM;
227                case AudioAttributes.USAGE_VOICE_COMMUNICATION:
228                    return AudioManager.STREAM_VOICE_CALL;
229                case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
230                    return AudioManager.STREAM_DTMF;
231                case AudioAttributes.USAGE_ALARM:
232                    return AudioManager.STREAM_ALARM;
233                case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
234                    return AudioManager.STREAM_RING;
235                case AudioAttributes.USAGE_NOTIFICATION:
236                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
237                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
238                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
239                case AudioAttributes.USAGE_NOTIFICATION_EVENT:
240                    return AudioManager.STREAM_NOTIFICATION;
241                case AudioAttributes.USAGE_UNKNOWN:
242                default:
243                    return AudioManager.STREAM_MUSIC;
244            }
245        }
246    }
247
248    public static interface Callback {
249        public void onSessionDestroyed();
250        public void onSessionEvent(String event, Bundle extras);
251        public void onPlaybackStateChanged(Object stateObj);
252        public void onMetadataChanged(Object metadataObj);
253        public void onQueueChanged(List<?> queue);
254        public void onQueueTitleChanged(CharSequence title);
255        public void onExtrasChanged(Bundle extras);
256        public void onAudioInfoChanged(int type, int stream, int control, int max, int current);
257    }
258
259    static class CallbackProxy<T extends Callback> extends MediaController.Callback {
260        protected final T mCallback;
261
262        public CallbackProxy(T callback) {
263            mCallback = callback;
264        }
265
266        @Override
267        public void onSessionDestroyed() {
268            mCallback.onSessionDestroyed();
269        }
270
271        @Override
272        public void onSessionEvent(String event, Bundle extras) {
273            mCallback.onSessionEvent(event, extras);
274        }
275
276        @Override
277        public void onPlaybackStateChanged(PlaybackState state) {
278            mCallback.onPlaybackStateChanged(state);
279        }
280
281        @Override
282        public void onMetadataChanged(MediaMetadata metadata) {
283            mCallback.onMetadataChanged(metadata);
284        }
285
286        @Override
287        public void onQueueChanged(List<MediaSession.QueueItem> queue) {
288            mCallback.onQueueChanged(queue);
289        }
290
291        @Override
292        public void onQueueTitleChanged(CharSequence title) {
293            mCallback.onQueueTitleChanged(title);
294        }
295
296        @Override
297        public void onExtrasChanged(Bundle extras) {
298            mCallback.onExtrasChanged(extras);
299        }
300
301        @Override
302        public void onAudioInfoChanged(MediaController.PlaybackInfo info){
303            mCallback.onAudioInfoChanged(info.getPlaybackType(),
304                    PlaybackInfo.getLegacyAudioStream(info), info.getVolumeControl(),
305                    info.getMaxVolume(), info.getCurrentVolume());
306        }
307    }
308}
309