1 /*
2  * Copyright (C) 2022 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 android.media.bettertogether.cts;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.annotation.NonNull;
22 import android.media.MediaDescription;
23 import android.media.browse.MediaBrowser.MediaItem;
24 import android.media.session.MediaSession;
25 import android.media.session.MediaSessionManager;
26 import android.os.Bundle;
27 import android.service.media.MediaBrowserService;
28 
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 
35 /**
36  * Stub implementation of (@link android.service.media.MediaBrowserService}.
37  */
38 public class StubMediaBrowserService extends MediaBrowserService {
39     static final String EXTRAS_KEY = "test_extras_key";
40     static final String EXTRAS_VALUE = "test_extras_value";
41 
42     static final String MEDIA_ID_INVALID = "test_media_id_invalid";
43     static final String MEDIA_ID_ROOT = "test_media_id_root";
44     static final String MEDIA_ID_CHILDREN_DELAYED = "test_media_id_children_delayed";
45 
46     static final String[] MEDIA_ID_CHILDREN = new String[] {
47         "test_media_id_children_0", "test_media_id_children_1",
48         "test_media_id_children_2", "test_media_id_children_3",
49         MEDIA_ID_CHILDREN_DELAYED
50     };
51 
52     static StubMediaBrowserService sInstance;
53 
54     static MediaSession sSession;
55     static MediaSessionManager.RemoteUserInfo sBrowserInfo;
56 
57     private Bundle mExtras;
58     private Result<List<MediaItem>> mPendingLoadChildrenResult;
59     private Result<MediaItem> mPendingLoadItemResult;
60     private Bundle mPendingRootHints;
61     private final Map<String, List<MediaItem>> mChildrenMap = new HashMap<>();
62 
clearBrowserInfo()63     public static void clearBrowserInfo() {
64         sBrowserInfo = null;
65     }
66 
67     @Override
onCreate()68     public void onCreate() {
69         super.onCreate();
70         sInstance = this;
71         sSession = new MediaSession(this, "StubMediaBrowserService");
72         setSessionToken(sSession.getSessionToken());
73     }
74 
75     @Override
onDestroy()76     public void onDestroy() {
77         super.onDestroy();
78         sSession.release();
79         sInstance = null;
80         sSession = null;
81     }
82 
83     @Override
onGetRoot(String clientPackageName, int clientUid, Bundle rootHints)84     public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
85         sBrowserInfo = getCurrentBrowserInfo();
86         mExtras = new Bundle();
87         mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
88         return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
89     }
90 
91     @Override
onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result)92     public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
93         List<MediaItem> mediaItems = new ArrayList<>();
94         if (MEDIA_ID_ROOT.equals(parentMediaId)) {
95             Bundle rootHints = getBrowserRootHints();
96             for (String id : MEDIA_ID_CHILDREN) {
97                 mediaItems.add(new MediaItem(new MediaDescription.Builder()
98                         .setMediaId(id).setExtras(rootHints).build(), MediaItem.FLAG_BROWSABLE));
99             }
100             sBrowserInfo = getCurrentBrowserInfo();
101             result.sendResult(mediaItems);
102         } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
103             assertThat(mPendingLoadChildrenResult).isNull();
104             mPendingLoadChildrenResult = result;
105             mPendingRootHints = getBrowserRootHints();
106             result.detach();
107         } else if (MEDIA_ID_INVALID.equals(parentMediaId)) {
108             result.sendResult(null);
109         } else if (mChildrenMap.containsKey(parentMediaId)) {
110             result.sendResult(mChildrenMap.get(parentMediaId));
111         }
112     }
113 
114     @Override
onLoadItem(String itemId, Result<MediaItem> result)115     public void onLoadItem(String itemId, Result<MediaItem> result) {
116         if (MEDIA_ID_CHILDREN_DELAYED.equals(itemId)) {
117             mPendingLoadItemResult = result;
118             mPendingRootHints = getBrowserRootHints();
119             result.detach();
120             return;
121         }
122 
123         for (String id : MEDIA_ID_CHILDREN) {
124             if (id.equals(itemId)) {
125                 result.sendResult(new MediaItem(new MediaDescription.Builder()
126                         .setMediaId(id).setExtras(getBrowserRootHints()).build(),
127                                 MediaItem.FLAG_BROWSABLE));
128                 sBrowserInfo = getCurrentBrowserInfo();
129                 return;
130             }
131         }
132 
133         super.onLoadItem(itemId, result);
134     }
135 
putChildrenToMap(@onNull String parentMediaId, @NonNull List<MediaItem> children)136     public void putChildrenToMap(@NonNull String parentMediaId, @NonNull List<MediaItem> children) {
137         mChildrenMap.put(parentMediaId, children);
138     }
139 
removeChildrenFromMap(@onNull String parentMediaId)140     public void removeChildrenFromMap(@NonNull String parentMediaId) {
141         mChildrenMap.remove(parentMediaId);
142     }
143 
sendDelayedNotifyChildrenChanged()144     public void sendDelayedNotifyChildrenChanged() {
145         if (mPendingLoadChildrenResult != null) {
146             mPendingLoadChildrenResult.sendResult(Collections.<MediaItem>emptyList());
147             mPendingRootHints = null;
148             mPendingLoadChildrenResult = null;
149         }
150     }
151 
sendDelayedItemLoaded()152     public void sendDelayedItemLoaded() {
153         if (mPendingLoadItemResult != null) {
154             mPendingLoadItemResult.sendResult(new MediaItem(new MediaDescription.Builder()
155                     .setMediaId(MEDIA_ID_CHILDREN_DELAYED).setExtras(mPendingRootHints).build(),
156                             MediaItem.FLAG_BROWSABLE));
157             mPendingRootHints = null;
158             mPendingLoadItemResult = null;
159         }
160     }
161 }
162