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.MediaLibraryService2;
22 import android.media.MediaLibraryService2.LibraryRoot;
23 import android.media.MediaLibraryService2.MediaLibrarySession;
24 import android.media.MediaLibraryService2.MediaLibrarySession.Builder;
25 import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
26 import android.media.MediaPlayerBase;
27 import android.media.MediaPlaylistAgent;
28 import android.media.MediaSession2;
29 import android.media.MediaSession2.ControllerInfo;
30 import android.media.MediaSessionService2;
31 import android.media.SessionToken2;
32 import android.media.VolumeProvider2;
33 import android.media.update.MediaLibraryService2Provider;
34 import android.os.Bundle;
35 import android.text.TextUtils;
36 
37 import com.android.media.MediaSession2Impl.BuilderBaseImpl;
38 
39 import java.util.concurrent.Executor;
40 
41 public class MediaLibraryService2Impl extends MediaSessionService2Impl implements
42         MediaLibraryService2Provider {
43     private final MediaSessionService2 mInstance;
44     private MediaLibrarySession mLibrarySession;
45 
MediaLibraryService2Impl(MediaLibraryService2 instance)46     public MediaLibraryService2Impl(MediaLibraryService2 instance) {
47         super(instance);
48         mInstance = instance;
49     }
50 
51     @Override
onCreate_impl()52     public void onCreate_impl() {
53         super.onCreate_impl();
54 
55         // Effectively final
56         MediaSession2 session = getSession();
57         if (!(session instanceof MediaLibrarySession)) {
58             throw new RuntimeException("Expected MediaLibrarySession, but returned MediaSession2");
59         }
60         mLibrarySession = (MediaLibrarySession) getSession();
61     }
62 
63     @Override
getSessionType()64     int getSessionType() {
65         return SessionToken2.TYPE_LIBRARY_SERVICE;
66     }
67 
68     public static class MediaLibrarySessionImpl extends MediaSession2Impl
69             implements MediaLibrarySessionProvider {
MediaLibrarySessionImpl(Context context, MediaPlayerBase player, String id, MediaPlaylistAgent playlistAgent, VolumeProvider2 volumeProvider, PendingIntent sessionActivity, Executor callbackExecutor, MediaLibrarySessionCallback callback)70         public MediaLibrarySessionImpl(Context context,
71                 MediaPlayerBase player, String id, MediaPlaylistAgent playlistAgent,
72                 VolumeProvider2 volumeProvider,
73                 PendingIntent sessionActivity, Executor callbackExecutor,
74                 MediaLibrarySessionCallback callback) {
75             super(context, player, id, playlistAgent, volumeProvider, sessionActivity,
76                     callbackExecutor, callback);
77             // Don't put any extra initialization here. Here's the reason.
78             // System service will recognize this session inside of the super constructor and would
79             // connect to this session assuming that initialization is finished. However, if any
80             // initialization logic is here, calls from the server would fail.
81             // see: MediaSession2Stub#connect()
82         }
83 
84         @Override
createInstance()85         MediaLibrarySession createInstance() {
86             return new MediaLibrarySession(this);
87         }
88 
89         @Override
getInstance()90         MediaLibrarySession getInstance() {
91             return (MediaLibrarySession) super.getInstance();
92         }
93 
94         @Override
getCallback()95         MediaLibrarySessionCallback getCallback() {
96             return (MediaLibrarySessionCallback) super.getCallback();
97         }
98 
99         @Override
notifyChildrenChanged_impl(ControllerInfo controller, String parentId, int itemCount, Bundle extras)100         public void notifyChildrenChanged_impl(ControllerInfo controller, String parentId,
101                 int itemCount, Bundle extras) {
102             if (controller == null) {
103                 throw new IllegalArgumentException("controller shouldn't be null");
104             }
105             if (parentId == null) {
106                 throw new IllegalArgumentException("parentId shouldn't be null");
107             }
108             getSessionStub().notifyChildrenChangedNotLocked(controller, parentId, itemCount,
109                     extras);
110         }
111 
112         @Override
notifyChildrenChanged_impl(String parentId, int itemCount, Bundle extras)113         public void notifyChildrenChanged_impl(String parentId, int itemCount, Bundle extras) {
114             if (parentId == null) {
115                 throw new IllegalArgumentException("parentId shouldn't be null");
116             }
117             getSessionStub().notifyChildrenChangedNotLocked(parentId, itemCount, extras);
118         }
119 
120         @Override
notifySearchResultChanged_impl(ControllerInfo controller, String query, int itemCount, Bundle extras)121         public void notifySearchResultChanged_impl(ControllerInfo controller, String query,
122                 int itemCount, Bundle extras) {
123             ensureCallingThread();
124             if (controller == null) {
125                 throw new IllegalArgumentException("controller shouldn't be null");
126             }
127             if (TextUtils.isEmpty(query)) {
128                 throw new IllegalArgumentException("query shouldn't be empty");
129             }
130             getSessionStub().notifySearchResultChanged(controller, query, itemCount, extras);
131         }
132     }
133 
134     public static class BuilderImpl
135             extends BuilderBaseImpl<MediaLibrarySession, MediaLibrarySessionCallback> {
BuilderImpl(MediaLibraryService2 service, Builder instance, Executor callbackExecutor, MediaLibrarySessionCallback callback)136         public BuilderImpl(MediaLibraryService2 service, Builder instance,
137                 Executor callbackExecutor, MediaLibrarySessionCallback callback) {
138             super(service);
139             setSessionCallback_impl(callbackExecutor, callback);
140         }
141 
142         @Override
build_impl()143         public MediaLibrarySession build_impl() {
144             return new MediaLibrarySessionImpl(mContext, mPlayer, mId, mPlaylistAgent,
145                     mVolumeProvider, mSessionActivity, mCallbackExecutor, mCallback).getInstance();
146         }
147     }
148 
149     public static final class LibraryRootImpl implements LibraryRootProvider {
150         private final LibraryRoot mInstance;
151         private final String mRootId;
152         private final Bundle mExtras;
153 
LibraryRootImpl(LibraryRoot instance, String rootId, Bundle extras)154         public LibraryRootImpl(LibraryRoot instance, String rootId, Bundle extras) {
155             if (rootId == null) {
156                 throw new IllegalArgumentException("rootId shouldn't be null.");
157             }
158             mInstance = instance;
159             mRootId = rootId;
160             mExtras = extras;
161         }
162 
163         @Override
getRootId_impl()164         public String getRootId_impl() {
165             return mRootId;
166         }
167 
168         @Override
getExtras_impl()169         public Bundle getExtras_impl() {
170             return mExtras;
171         }
172     }
173 }
174