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 */
16package android.support.v4.media.session;
17
18import android.app.PendingIntent;
19import android.content.Context;
20import android.content.Intent;
21import android.graphics.Bitmap;
22import android.media.AudioManager;
23import android.media.MediaMetadataRetriever;
24import android.media.RemoteControlClient;
25import android.os.Bundle;
26import android.os.ResultReceiver;
27
28class MediaSessionCompatApi14 {
29    /***** RemoteControlClient States, we only need none as the others were public *******/
30    final static int RCC_PLAYSTATE_NONE = 0;
31
32    /***** MediaSession States *******/
33    final static int STATE_NONE = 0;
34    final static int STATE_STOPPED = 1;
35    final static int STATE_PAUSED = 2;
36    final static int STATE_PLAYING = 3;
37    final static int STATE_FAST_FORWARDING = 4;
38    final static int STATE_REWINDING = 5;
39    final static int STATE_BUFFERING = 6;
40    final static int STATE_ERROR = 7;
41    final static int STATE_CONNECTING = 8;
42    final static int STATE_SKIPPING_TO_PREVIOUS = 9;
43    final static int STATE_SKIPPING_TO_NEXT = 10;
44    final static int STATE_SKIPPING_TO_QUEUE_ITEM = 11;
45
46    /***** PlaybackState actions *****/
47    private static final long ACTION_STOP = 1 << 0;
48    private static final long ACTION_PAUSE = 1 << 1;
49    private static final long ACTION_PLAY = 1 << 2;
50    private static final long ACTION_REWIND = 1 << 3;
51    private static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4;
52    private static final long ACTION_SKIP_TO_NEXT = 1 << 5;
53    private static final long ACTION_FAST_FORWARD = 1 << 6;
54    private static final long ACTION_PLAY_PAUSE = 1 << 9;
55
56    /***** MediaMetadata keys ********/
57    private static final String METADATA_KEY_ART = "android.media.metadata.ART";
58    private static final String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
59    private static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
60    private static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
61    private static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
62    private static final String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
63    private static final String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
64    private static final String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
65    private static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
66    private static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
67    private static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
68    private static final String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
69    private static final String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
70    private static final String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
71    private static final String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
72
73    public static Object createRemoteControlClient(PendingIntent mbIntent) {
74        return new RemoteControlClient(mbIntent);
75    }
76
77    public static void setState(Object rccObj, int state) {
78        ((RemoteControlClient) rccObj).setPlaybackState(getRccStateFromState(state));
79    }
80
81    public static void setTransportControlFlags(Object rccObj, long actions) {
82        ((RemoteControlClient) rccObj).setTransportControlFlags(
83                getRccTransportControlFlagsFromActions(actions));
84    }
85
86    public static void setMetadata(Object rccObj, Bundle metadata) {
87        RemoteControlClient.MetadataEditor editor = ((RemoteControlClient) rccObj).editMetadata(
88                true);
89        buildOldMetadata(metadata, editor);
90        editor.apply();
91    }
92
93    public static void registerRemoteControlClient(Context context, Object rccObj) {
94        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
95        am.registerRemoteControlClient((RemoteControlClient) rccObj);
96    }
97
98    public static void unregisterRemoteControlClient(Context context, Object rccObj) {
99        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
100        am.unregisterRemoteControlClient((RemoteControlClient) rccObj);
101    }
102
103    static int getRccStateFromState(int state) {
104        switch (state) {
105            case STATE_CONNECTING:
106            case STATE_BUFFERING:
107                return RemoteControlClient.PLAYSTATE_BUFFERING;
108            case STATE_ERROR:
109                return RemoteControlClient.PLAYSTATE_ERROR;
110            case STATE_FAST_FORWARDING:
111                return RemoteControlClient.PLAYSTATE_FAST_FORWARDING;
112            case STATE_NONE:
113                return RCC_PLAYSTATE_NONE;
114            case STATE_PAUSED:
115                return RemoteControlClient.PLAYSTATE_PAUSED;
116            case STATE_PLAYING:
117                return RemoteControlClient.PLAYSTATE_PLAYING;
118            case STATE_REWINDING:
119                return RemoteControlClient.PLAYSTATE_REWINDING;
120            case STATE_SKIPPING_TO_PREVIOUS:
121                return RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS;
122            case STATE_SKIPPING_TO_NEXT:
123            case STATE_SKIPPING_TO_QUEUE_ITEM:
124                return RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS;
125            case STATE_STOPPED:
126                return RemoteControlClient.PLAYSTATE_STOPPED;
127            default:
128                return -1;
129        }
130    }
131
132    static int getRccTransportControlFlagsFromActions(long actions) {
133        int transportControlFlags = 0;
134        if ((actions & ACTION_STOP) != 0) {
135            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_STOP;
136        }
137        if ((actions & ACTION_PAUSE) != 0) {
138            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PAUSE;
139        }
140        if ((actions & ACTION_PLAY) != 0) {
141            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY;
142        }
143        if ((actions & ACTION_REWIND) != 0) {
144            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_REWIND;
145        }
146        if ((actions & ACTION_SKIP_TO_PREVIOUS) != 0) {
147            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS;
148        }
149        if ((actions & ACTION_SKIP_TO_NEXT) != 0) {
150            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_NEXT;
151        }
152        if ((actions & ACTION_FAST_FORWARD) != 0) {
153            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD;
154        }
155        if ((actions & ACTION_PLAY_PAUSE) != 0) {
156            transportControlFlags |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE;
157        }
158        return transportControlFlags;
159    }
160
161    static void buildOldMetadata(Bundle metadata, RemoteControlClient.MetadataEditor editor) {
162        if (metadata == null) {
163            return;
164        }
165        if (metadata.containsKey(METADATA_KEY_ART)) {
166            Bitmap art = metadata.getParcelable(METADATA_KEY_ART);
167            editor.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, art);
168        } else if (metadata.containsKey(METADATA_KEY_ALBUM_ART)) {
169            // Fall back to album art if the track art wasn't available
170            Bitmap art = metadata.getParcelable(METADATA_KEY_ALBUM_ART);
171            editor.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, art);
172        }
173        if (metadata.containsKey(METADATA_KEY_ALBUM)) {
174            editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM,
175                    metadata.getString(METADATA_KEY_ALBUM));
176        }
177        if (metadata.containsKey(METADATA_KEY_ALBUM_ARTIST)) {
178            editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
179                    metadata.getString(METADATA_KEY_ALBUM_ARTIST));
180        }
181        if (metadata.containsKey(METADATA_KEY_ARTIST)) {
182            editor.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST,
183                    metadata.getString(METADATA_KEY_ARTIST));
184        }
185        if (metadata.containsKey(METADATA_KEY_AUTHOR)) {
186            editor.putString(MediaMetadataRetriever.METADATA_KEY_AUTHOR,
187                    metadata.getString(METADATA_KEY_AUTHOR));
188        }
189        if (metadata.containsKey(METADATA_KEY_COMPILATION)) {
190            editor.putString(MediaMetadataRetriever.METADATA_KEY_COMPILATION,
191                    metadata.getString(METADATA_KEY_COMPILATION));
192        }
193        if (metadata.containsKey(METADATA_KEY_COMPOSER)) {
194            editor.putString(MediaMetadataRetriever.METADATA_KEY_COMPOSER,
195                    metadata.getString(METADATA_KEY_COMPOSER));
196        }
197        if (metadata.containsKey(METADATA_KEY_DATE)) {
198            editor.putString(MediaMetadataRetriever.METADATA_KEY_DATE,
199                    metadata.getString(METADATA_KEY_DATE));
200        }
201        if (metadata.containsKey(METADATA_KEY_DISC_NUMBER)) {
202            editor.putLong(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
203                    metadata.getLong(METADATA_KEY_DISC_NUMBER));
204        }
205        if (metadata.containsKey(METADATA_KEY_DURATION)) {
206            editor.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION,
207                    metadata.getLong(METADATA_KEY_DURATION));
208        }
209        if (metadata.containsKey(METADATA_KEY_GENRE)) {
210            editor.putString(MediaMetadataRetriever.METADATA_KEY_GENRE,
211                    metadata.getString(METADATA_KEY_GENRE));
212        }
213        if (metadata.containsKey(METADATA_KEY_TITLE)) {
214            editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE,
215                    metadata.getString(METADATA_KEY_TITLE));
216        }
217        if (metadata.containsKey(METADATA_KEY_TRACK_NUMBER)) {
218            editor.putLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER,
219                    metadata.getLong(METADATA_KEY_TRACK_NUMBER));
220        }
221        if (metadata.containsKey(METADATA_KEY_WRITER)) {
222            editor.putString(MediaMetadataRetriever.METADATA_KEY_WRITER,
223                    metadata.getString(METADATA_KEY_WRITER));
224        }
225    }
226}
227