• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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.media;
18 
19 import android.app.PendingIntent;
20 import android.content.Context;
21 import android.media.MediaController2;
22 import android.media.MediaItem2;
23 import android.media.MediaMetadata2;
24 import android.media.SessionCommand2;
25 import android.media.MediaSession2.CommandButton;
26 import android.media.SessionCommandGroup2;
27 import android.os.Bundle;
28 import android.os.ResultReceiver;
29 import android.text.TextUtils;
30 import android.util.Log;
31 
32 import com.android.media.MediaController2Impl.PlaybackInfoImpl;
33 import com.android.media.MediaSession2Impl.CommandButtonImpl;
34 
35 import java.lang.ref.WeakReference;
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 public class MediaController2Stub extends IMediaController2.Stub {
40     private static final String TAG = "MediaController2Stub";
41     private static final boolean DEBUG = true; // TODO(jaewan): Change
42 
43     private final WeakReference<MediaController2Impl> mController;
44 
MediaController2Stub(MediaController2Impl controller)45     MediaController2Stub(MediaController2Impl controller) {
46         mController = new WeakReference<>(controller);
47     }
48 
getController()49     private MediaController2Impl getController() throws IllegalStateException {
50         final MediaController2Impl controller = mController.get();
51         if (controller == null) {
52             throw new IllegalStateException("Controller is released");
53         }
54         return controller;
55     }
56 
getBrowser()57     private MediaBrowser2Impl getBrowser() throws IllegalStateException {
58         final MediaController2Impl controller = getController();
59         if (controller instanceof MediaBrowser2Impl) {
60             return (MediaBrowser2Impl) controller;
61         }
62         return null;
63     }
64 
destroy()65     public void destroy() {
66         mController.clear();
67     }
68 
69     @Override
onPlayerStateChanged(int state)70     public void onPlayerStateChanged(int state) {
71         final MediaController2Impl controller;
72         try {
73             controller = getController();
74         } catch (IllegalStateException e) {
75             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
76             return;
77         }
78         controller.pushPlayerStateChanges(state);
79     }
80 
81     @Override
onPositionChanged(long eventTimeMs, long positionMs)82     public void onPositionChanged(long eventTimeMs, long positionMs) {
83         final MediaController2Impl controller;
84         try {
85             controller = getController();
86         } catch (IllegalStateException e) {
87             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
88             return;
89         }
90         if (eventTimeMs < 0) {
91             Log.w(TAG, "onPositionChanged(): Ignoring negative eventTimeMs");
92             return;
93         }
94         if (positionMs < 0) {
95             Log.w(TAG, "onPositionChanged(): Ignoring negative positionMs");
96             return;
97         }
98         controller.pushPositionChanges(eventTimeMs, positionMs);
99     }
100 
101     @Override
onPlaybackSpeedChanged(float speed)102     public void onPlaybackSpeedChanged(float speed) {
103         final MediaController2Impl controller;
104         try {
105             controller = getController();
106         } catch (IllegalStateException e) {
107             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
108             return;
109         }
110         controller.pushPlaybackSpeedChanges(speed);
111     }
112 
113     @Override
onBufferedPositionChanged(long bufferedPositionMs)114     public void onBufferedPositionChanged(long bufferedPositionMs) {
115         final MediaController2Impl controller;
116         try {
117             controller = getController();
118         } catch (IllegalStateException e) {
119             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
120             return;
121         }
122         if (bufferedPositionMs < 0) {
123             Log.w(TAG, "onBufferedPositionChanged(): Ignoring negative bufferedPositionMs");
124             return;
125         }
126         controller.pushBufferedPositionChanges(bufferedPositionMs);
127     }
128 
129     @Override
onPlaylistChanged(List<Bundle> playlistBundle, Bundle metadataBundle)130     public void onPlaylistChanged(List<Bundle> playlistBundle, Bundle metadataBundle) {
131         final MediaController2Impl controller;
132         try {
133             controller = getController();
134         } catch (IllegalStateException e) {
135             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
136             return;
137         }
138         if (playlistBundle == null) {
139             Log.w(TAG, "onPlaylistChanged(): Ignoring null playlist from " + controller);
140             return;
141         }
142         List<MediaItem2> playlist = new ArrayList<>();
143         for (Bundle bundle : playlistBundle) {
144             MediaItem2 item = MediaItem2.fromBundle(bundle);
145             if (item == null) {
146                 Log.w(TAG, "onPlaylistChanged(): Ignoring null item in playlist");
147             } else {
148                 playlist.add(item);
149             }
150         }
151         MediaMetadata2 metadata = MediaMetadata2.fromBundle(metadataBundle);
152         controller.pushPlaylistChanges(playlist, metadata);
153     }
154 
155     @Override
onPlaylistMetadataChanged(Bundle metadataBundle)156     public void onPlaylistMetadataChanged(Bundle metadataBundle) throws RuntimeException {
157         final MediaController2Impl controller;
158         try {
159             controller = getController();
160         } catch (IllegalStateException e) {
161             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
162             return;
163         }
164         MediaMetadata2 metadata = MediaMetadata2.fromBundle(metadataBundle);
165         controller.pushPlaylistMetadataChanges(metadata);
166     }
167 
168     @Override
onRepeatModeChanged(int repeatMode)169     public void onRepeatModeChanged(int repeatMode) {
170         final MediaController2Impl controller;
171         try {
172             controller = getController();
173         } catch (IllegalStateException e) {
174             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
175             return;
176         }
177         controller.pushRepeatModeChanges(repeatMode);
178     }
179 
180     @Override
onPlaybackInfoChanged(Bundle playbackInfo)181     public void onPlaybackInfoChanged(Bundle playbackInfo) throws RuntimeException {
182         if (DEBUG) {
183             Log.d(TAG, "onPlaybackInfoChanged");
184         }
185         final MediaController2Impl controller;
186         try {
187             controller = getController();
188         } catch (IllegalStateException e) {
189             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
190             return;
191         }
192         MediaController2.PlaybackInfo info = PlaybackInfoImpl.fromBundle(playbackInfo);
193         if (info == null) {
194             Log.w(TAG, "onPlaybackInfoChanged(): Ignoring null playbackInfo");
195             return;
196         }
197         controller.pushPlaybackInfoChanges(info);
198     }
199 
200     @Override
onShuffleModeChanged(int shuffleMode)201     public void onShuffleModeChanged(int shuffleMode) {
202         final MediaController2Impl controller;
203         try {
204             controller = getController();
205         } catch (IllegalStateException e) {
206             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
207             return;
208         }
209         controller.pushShuffleModeChanges(shuffleMode);
210     }
211 
212     @Override
onError(int errorCode, Bundle extras)213     public void onError(int errorCode, Bundle extras) {
214         final MediaController2Impl controller;
215         try {
216             controller = getController();
217         } catch (IllegalStateException e) {
218             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
219             return;
220         }
221         controller.pushError(errorCode, extras);
222     }
223 
224     @Override
onConnected(IMediaSession2 sessionBinder, Bundle commandGroup, int playerState, long positionEventTimeMs, long positionMs, float playbackSpeed, long bufferedPositionMs, Bundle playbackInfo, int shuffleMode, int repeatMode, List<Bundle> itemBundleList, PendingIntent sessionActivity)225     public void onConnected(IMediaSession2 sessionBinder, Bundle commandGroup,
226             int playerState, long positionEventTimeMs, long positionMs, float playbackSpeed,
227             long bufferedPositionMs, Bundle playbackInfo, int shuffleMode, int repeatMode,
228             List<Bundle> itemBundleList, PendingIntent sessionActivity) {
229         final MediaController2Impl controller = mController.get();
230         if (controller == null) {
231             if (DEBUG) {
232                 Log.d(TAG, "onConnected after MediaController2.close()");
233             }
234             return;
235         }
236         final Context context = controller.getContext();
237         List<MediaItem2> itemList = null;
238         if (itemBundleList != null) {
239             itemList = new ArrayList<>();
240             for (int i = 0; i < itemBundleList.size(); i++) {
241                 MediaItem2 item = MediaItem2.fromBundle(itemBundleList.get(i));
242                 if (item != null) {
243                     itemList.add(item);
244                 }
245             }
246         }
247         controller.onConnectedNotLocked(sessionBinder,
248                 SessionCommandGroup2.fromBundle(commandGroup),
249                 playerState, positionEventTimeMs, positionMs, playbackSpeed, bufferedPositionMs,
250                 PlaybackInfoImpl.fromBundle(playbackInfo), repeatMode, shuffleMode,
251                 itemList, sessionActivity);
252     }
253 
254     @Override
onDisconnected()255     public void onDisconnected() {
256         final MediaController2Impl controller = mController.get();
257         if (controller == null) {
258             if (DEBUG) {
259                 Log.d(TAG, "onDisconnected after MediaController2.close()");
260             }
261             return;
262         }
263         controller.getInstance().close();
264     }
265 
266     @Override
onCustomLayoutChanged(List<Bundle> commandButtonlist)267     public void onCustomLayoutChanged(List<Bundle> commandButtonlist) {
268         if (commandButtonlist == null) {
269             Log.w(TAG, "onCustomLayoutChanged(): Ignoring null commandButtonlist");
270             return;
271         }
272         final MediaController2Impl controller;
273         try {
274             controller = getController();
275         } catch (IllegalStateException e) {
276             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
277             return;
278         }
279         if (controller == null) {
280             // TODO(jaewan): Revisit here. Could be a bug
281             return;
282         }
283         List<CommandButton> layout = new ArrayList<>();
284         for (int i = 0; i < commandButtonlist.size(); i++) {
285             CommandButton button = CommandButtonImpl.fromBundle(commandButtonlist.get(i));
286             if (button != null) {
287                 layout.add(button);
288             }
289         }
290         controller.onCustomLayoutChanged(layout);
291     }
292 
293     @Override
onAllowedCommandsChanged(Bundle commandsBundle)294     public void onAllowedCommandsChanged(Bundle commandsBundle) {
295         final MediaController2Impl controller;
296         try {
297             controller = getController();
298         } catch (IllegalStateException e) {
299             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
300             return;
301         }
302         if (controller == null) {
303             // TODO(jaewan): Revisit here. Could be a bug
304             return;
305         }
306         SessionCommandGroup2 commands = SessionCommandGroup2.fromBundle(commandsBundle);
307         if (commands == null) {
308             Log.w(TAG, "onAllowedCommandsChanged(): Ignoring null commands");
309             return;
310         }
311         controller.onAllowedCommandsChanged(commands);
312     }
313 
314     @Override
onCustomCommand(Bundle commandBundle, Bundle args, ResultReceiver receiver)315     public void onCustomCommand(Bundle commandBundle, Bundle args, ResultReceiver receiver) {
316         final MediaController2Impl controller;
317         try {
318             controller = getController();
319         } catch (IllegalStateException e) {
320             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
321             return;
322         }
323         SessionCommand2 command = SessionCommand2.fromBundle(commandBundle);
324         if (command == null) {
325             Log.w(TAG, "onCustomCommand(): Ignoring null command");
326             return;
327         }
328         controller.onCustomCommand(command, args, receiver);
329     }
330 
331     ////////////////////////////////////////////////////////////////////////////////////////////
332     // MediaBrowser specific
333     ////////////////////////////////////////////////////////////////////////////////////////////
334     @Override
onGetLibraryRootDone(Bundle rootHints, String rootMediaId, Bundle rootExtra)335     public void onGetLibraryRootDone(Bundle rootHints, String rootMediaId, Bundle rootExtra)
336             throws RuntimeException {
337         final MediaBrowser2Impl browser;
338         try {
339             browser = getBrowser();
340         } catch (IllegalStateException e) {
341             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
342             return;
343         }
344         if (browser == null) {
345             // TODO(jaewan): Revisit here. Could be a bug
346             return;
347         }
348         browser.onGetLibraryRootDone(rootHints, rootMediaId, rootExtra);
349     }
350 
351 
352     @Override
onGetItemDone(String mediaId, Bundle itemBundle)353     public void onGetItemDone(String mediaId, Bundle itemBundle) throws RuntimeException {
354         if (mediaId == null) {
355             Log.w(TAG, "onGetItemDone(): Ignoring null mediaId");
356             return;
357         }
358         final MediaBrowser2Impl browser;
359         try {
360             browser = getBrowser();
361         } catch (IllegalStateException e) {
362             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
363             return;
364         }
365         if (browser == null) {
366             // TODO(jaewan): Revisit here. Could be a bug
367             return;
368         }
369         browser.onGetItemDone(mediaId, MediaItem2.fromBundle(itemBundle));
370     }
371 
372     @Override
onGetChildrenDone(String parentId, int page, int pageSize, List<Bundle> itemBundleList, Bundle extras)373     public void onGetChildrenDone(String parentId, int page, int pageSize,
374             List<Bundle> itemBundleList, Bundle extras) throws RuntimeException {
375         if (parentId == null) {
376             Log.w(TAG, "onGetChildrenDone(): Ignoring null parentId");
377             return;
378         }
379         final MediaBrowser2Impl browser;
380         try {
381             browser = getBrowser();
382         } catch (IllegalStateException e) {
383             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
384             return;
385         }
386         if (browser == null) {
387             // TODO(jaewan): Revisit here. Could be a bug
388             return;
389         }
390 
391         List<MediaItem2> result = null;
392         if (itemBundleList != null) {
393             result = new ArrayList<>();
394             for (Bundle bundle : itemBundleList) {
395                 result.add(MediaItem2.fromBundle(bundle));
396             }
397         }
398         browser.onGetChildrenDone(parentId, page, pageSize, result, extras);
399     }
400 
401     @Override
onSearchResultChanged(String query, int itemCount, Bundle extras)402     public void onSearchResultChanged(String query, int itemCount, Bundle extras)
403             throws RuntimeException {
404         if (TextUtils.isEmpty(query)) {
405             Log.w(TAG, "onSearchResultChanged(): Ignoring empty query");
406             return;
407         }
408         final MediaBrowser2Impl browser;
409         try {
410             browser = getBrowser();
411         } catch (IllegalStateException e) {
412             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
413             return;
414         }
415         if (browser == null) {
416             // TODO(jaewan): Revisit here. Could be a bug
417             return;
418         }
419         browser.onSearchResultChanged(query, itemCount, extras);
420     }
421 
422     @Override
onGetSearchResultDone(String query, int page, int pageSize, List<Bundle> itemBundleList, Bundle extras)423     public void onGetSearchResultDone(String query, int page, int pageSize,
424             List<Bundle> itemBundleList, Bundle extras) throws RuntimeException {
425         if (TextUtils.isEmpty(query)) {
426             Log.w(TAG, "onGetSearchResultDone(): Ignoring empty query");
427             return;
428         }
429         final MediaBrowser2Impl browser;
430         try {
431             browser = getBrowser();
432         } catch (IllegalStateException e) {
433             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
434             return;
435         }
436         if (browser == null) {
437             // TODO(jaewan): Revisit here. Could be a bug
438             return;
439         }
440 
441         List<MediaItem2> result = null;
442         if (itemBundleList != null) {
443             result = new ArrayList<>();
444             for (Bundle bundle : itemBundleList) {
445                 result.add(MediaItem2.fromBundle(bundle));
446             }
447         }
448         browser.onGetSearchResultDone(query, page, pageSize, result, extras);
449     }
450 
451     @Override
onChildrenChanged(String parentId, int itemCount, Bundle extras)452     public void onChildrenChanged(String parentId, int itemCount, Bundle extras) {
453         if (parentId == null) {
454             Log.w(TAG, "onChildrenChanged(): Ignoring null parentId");
455             return;
456         }
457         final MediaBrowser2Impl browser;
458         try {
459             browser = getBrowser();
460         } catch (IllegalStateException e) {
461             Log.w(TAG, "Don't fail silently here. Highly likely a bug");
462             return;
463         }
464         if (browser == null) {
465             // TODO(jaewan): Revisit here. Could be a bug
466             return;
467         }
468         browser.onChildrenChanged(parentId, itemCount, extras);
469     }
470 }
471