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.content.Intent;
22import android.media.AudioAttributes;
23import android.media.MediaDescription;
24import android.media.MediaMetadata;
25import android.media.Rating;
26import android.media.VolumeProvider;
27import android.media.session.MediaSession;
28import android.media.session.PlaybackState;
29import android.os.Bundle;
30import android.os.Handler;
31import android.os.Parcelable;
32import android.os.ResultReceiver;
33import android.support.annotation.RequiresApi;
34import android.util.Log;
35
36import java.lang.reflect.Field;
37import java.util.ArrayList;
38import java.util.List;
39
40@RequiresApi(21)
41class MediaSessionCompatApi21 {
42    static final String TAG = "MediaSessionCompatApi21";
43
44    public static Object createSession(Context context, String tag) {
45        return new MediaSession(context, tag);
46    }
47
48    public static Object verifySession(Object mediaSession) {
49        if (mediaSession instanceof MediaSession) {
50            return mediaSession;
51        }
52        throw new IllegalArgumentException("mediaSession is not a valid MediaSession object");
53    }
54
55    public static Object verifyToken(Object token) {
56        if (token instanceof MediaSession.Token) {
57            return token;
58        }
59        throw new IllegalArgumentException("token is not a valid MediaSession.Token object");
60    }
61
62    public static Object createCallback(Callback callback) {
63        return new CallbackProxy<Callback>(callback);
64    }
65
66    public static void setCallback(Object sessionObj, Object callbackObj, Handler handler) {
67        ((MediaSession) sessionObj).setCallback((MediaSession.Callback) callbackObj, handler);
68    }
69
70    public static void setFlags(Object sessionObj, int flags) {
71        ((MediaSession)sessionObj).setFlags(flags);
72    }
73
74    public static void setPlaybackToLocal(Object sessionObj, int stream) {
75        // TODO update APIs to use support version of AudioAttributes
76        AudioAttributes.Builder bob = new AudioAttributes.Builder();
77        bob.setLegacyStreamType(stream);
78        ((MediaSession) sessionObj).setPlaybackToLocal(bob.build());
79    }
80
81    public static void setPlaybackToRemote(Object sessionObj, Object volumeProviderObj) {
82        ((MediaSession)sessionObj).setPlaybackToRemote((VolumeProvider)volumeProviderObj);
83    }
84
85    public static void setActive(Object sessionObj, boolean active) {
86        ((MediaSession)sessionObj).setActive(active);
87    }
88
89    public static boolean isActive(Object sessionObj) {
90        return ((MediaSession)sessionObj).isActive();
91    }
92
93    public static void sendSessionEvent(Object sessionObj, String event, Bundle extras) {
94        ((MediaSession)sessionObj).sendSessionEvent(event, extras);
95    }
96
97    public static void release(Object sessionObj) {
98        ((MediaSession)sessionObj).release();
99    }
100
101    public static Parcelable getSessionToken(Object sessionObj) {
102        return ((MediaSession)sessionObj).getSessionToken();
103    }
104
105    public static void setPlaybackState(Object sessionObj, Object stateObj) {
106        ((MediaSession)sessionObj).setPlaybackState((PlaybackState)stateObj);
107    }
108
109    public static void setMetadata(Object sessionObj, Object metadataObj) {
110        ((MediaSession)sessionObj).setMetadata((MediaMetadata)metadataObj);
111    }
112
113    public static void setSessionActivity(Object sessionObj, PendingIntent pi) {
114        ((MediaSession) sessionObj).setSessionActivity(pi);
115    }
116
117    public static void setMediaButtonReceiver(Object sessionObj, PendingIntent pi) {
118        ((MediaSession) sessionObj).setMediaButtonReceiver(pi);
119    }
120
121    public static void setQueue(Object sessionObj, List<Object> queueObjs) {
122        if (queueObjs == null) {
123            ((MediaSession) sessionObj).setQueue(null);
124            return;
125        }
126        ArrayList<MediaSession.QueueItem> queue = new ArrayList<MediaSession.QueueItem>();
127        for (Object itemObj : queueObjs) {
128            queue.add((MediaSession.QueueItem) itemObj);
129        }
130        ((MediaSession) sessionObj).setQueue(queue);
131    }
132
133    public static void setQueueTitle(Object sessionObj, CharSequence title) {
134        ((MediaSession) sessionObj).setQueueTitle(title);
135    }
136
137    public static void setExtras(Object sessionObj, Bundle extras) {
138        ((MediaSession) sessionObj).setExtras(extras);
139    }
140
141    public static boolean hasCallback(Object sessionObj) {
142        Field callbackField = null;
143        try {
144            callbackField = sessionObj.getClass().getDeclaredField("mCallback");
145            if (callbackField != null) {
146                callbackField.setAccessible(true);
147                return callbackField.get(sessionObj) != null;
148            }
149        } catch (NoSuchFieldException | IllegalAccessException e) {
150            Log.w(TAG, "Failed to get mCallback object.");
151        }
152        return false;
153    }
154
155    interface Callback {
156        void onCommand(String command, Bundle extras, ResultReceiver cb);
157        boolean onMediaButtonEvent(Intent mediaButtonIntent);
158        void onPlay();
159        void onPlayFromMediaId(String mediaId, Bundle extras);
160        void onPlayFromSearch(String search, Bundle extras);
161        void onSkipToQueueItem(long id);
162        void onPause();
163        void onSkipToNext();
164        void onSkipToPrevious();
165        void onFastForward();
166        void onRewind();
167        void onStop();
168        void onSeekTo(long position);
169        void onSetRating(Object ratingObject);
170        void onSetRating(Object ratingObject, Bundle extras);
171        void onCustomAction(String action, Bundle extras);
172    }
173
174    static class CallbackProxy<T extends Callback> extends MediaSession.Callback {
175        protected final T mCallback;
176
177        public CallbackProxy(T callback) {
178            mCallback = callback;
179        }
180
181        @Override
182        public void onCommand(String command, Bundle args, ResultReceiver cb) {
183            mCallback.onCommand(command, args, cb);
184        }
185
186        @Override
187        public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
188            return mCallback.onMediaButtonEvent(mediaButtonIntent)
189                    || super.onMediaButtonEvent(mediaButtonIntent);
190        }
191
192        @Override
193        public void onPlay() {
194            mCallback.onPlay();
195        }
196
197        @Override
198        public void onPlayFromMediaId(String mediaId, Bundle extras) {
199            mCallback.onPlayFromMediaId(mediaId, extras);
200        }
201
202        @Override
203        public void onPlayFromSearch(String search, Bundle extras) {
204            mCallback.onPlayFromSearch(search, extras);
205        }
206
207        @Override
208        public void onSkipToQueueItem(long id) {
209            mCallback.onSkipToQueueItem(id);
210        }
211
212        @Override
213        public void onPause() {
214            mCallback.onPause();
215        }
216
217        @Override
218        public void onSkipToNext() {
219            mCallback.onSkipToNext();
220        }
221
222        @Override
223        public void onSkipToPrevious() {
224            mCallback.onSkipToPrevious();
225        }
226
227        @Override
228        public void onFastForward() {
229            mCallback.onFastForward();
230        }
231
232        @Override
233        public void onRewind() {
234            mCallback.onRewind();
235        }
236
237        @Override
238        public void onStop() {
239            mCallback.onStop();
240        }
241
242        @Override
243        public void onSeekTo(long pos) {
244            mCallback.onSeekTo(pos);
245        }
246
247        @Override
248        public void onSetRating(Rating rating) {
249            mCallback.onSetRating(rating);
250        }
251
252        @Override
253        public void onCustomAction(String action, Bundle extras) {
254            mCallback.onCustomAction(action, extras);
255        }
256    }
257
258    static class QueueItem {
259
260        public static Object createItem(Object mediaDescription, long id) {
261            return new MediaSession.QueueItem((MediaDescription) mediaDescription, id);
262        }
263
264        public static Object getDescription(Object queueItem) {
265            return ((MediaSession.QueueItem) queueItem).getDescription();
266        }
267
268        public static long getQueueId(Object queueItem) {
269            return ((MediaSession.QueueItem) queueItem).getQueueId();
270        }
271    }
272}
273