• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package android.car.media;
17 
18 import android.annotation.IntDef;
19 import android.annotation.NonNull;
20 import android.annotation.RequiresPermission;
21 import android.annotation.SystemApi;
22 import android.car.Car;
23 import android.car.CarManagerBase;
24 import android.content.ComponentName;
25 import android.os.IBinder;
26 import android.os.RemoteException;
27 
28 import com.android.internal.annotations.GuardedBy;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 
36 /**
37  * API for updating and receiving updates to the primary media source in the car.
38  * @hide
39  */
40 @SystemApi
41 public final class CarMediaManager extends CarManagerBase {
42 
43     public static final int MEDIA_SOURCE_MODE_PLAYBACK = 0;
44     public static final int MEDIA_SOURCE_MODE_BROWSE = 1;
45 
46     /** @hide */
47     @IntDef(prefix = { "MEDIA_SOURCE_MODE_" }, value = {
48             MEDIA_SOURCE_MODE_PLAYBACK,
49             MEDIA_SOURCE_MODE_BROWSE
50     })
51     @Retention(RetentionPolicy.SOURCE)
52     public @interface MediaSourceMode {}
53 
54     private final Object mLock = new Object();
55 
56     private final ICarMedia mService;
57     @GuardedBy("mLock")
58     private Map<MediaSourceChangedListener, ICarMediaSourceListener> mCallbackMap = new HashMap();
59 
60     /**
61      * Get an instance of the CarMediaManager.
62      *
63      * Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead.
64      * @hide
65      */
CarMediaManager(Car car, IBinder service)66     public CarMediaManager(Car car, IBinder service) {
67         super(car);
68         mService = ICarMedia.Stub.asInterface(service);
69     }
70 
71     /**
72      * Listener for updates to the primary media source
73      */
74     public interface MediaSourceChangedListener {
75 
76         /**
77          * Called when the primary media source is changed
78          */
onMediaSourceChanged(@onNull ComponentName componentName)79         void onMediaSourceChanged(@NonNull ComponentName componentName);
80     }
81 
82     /**
83      * Gets the currently active media source for the provided mode
84      *
85      * @param mode the mode (playback or browse) for which the media source is active in.
86      * @return the active media source in the provided mode, will be non-{@code null}.
87      */
88     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
getMediaSource(@ediaSourceMode int mode)89     public @NonNull ComponentName getMediaSource(@MediaSourceMode int mode) {
90         try {
91             return mService.getMediaSource(mode);
92         } catch (RemoteException e) {
93             return handleRemoteExceptionFromCarService(e, null);
94         }
95     }
96 
97     /**
98      * Sets the currently active media source for the provided mode
99      *
100      * @param mode the mode (playback or browse) for which the media source is active in.
101      */
102     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
setMediaSource(@onNull ComponentName componentName, @MediaSourceMode int mode)103     public void setMediaSource(@NonNull ComponentName componentName, @MediaSourceMode int mode) {
104         try {
105             mService.setMediaSource(componentName, mode);
106         } catch (RemoteException e) {
107             handleRemoteExceptionFromCarService(e);
108         }
109     }
110 
111     /**
112      * Register a callback that receives updates to the active media source.
113      *
114      * @param callback the callback to receive active media source updates.
115      * @param mode the mode to receive updates for.
116      */
117     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
addMediaSourceListener(@onNull MediaSourceChangedListener callback, @MediaSourceMode int mode)118     public void addMediaSourceListener(@NonNull MediaSourceChangedListener callback,
119             @MediaSourceMode int mode) {
120         try {
121             ICarMediaSourceListener binderCallback = new ICarMediaSourceListener.Stub() {
122                 @Override
123                 public void onMediaSourceChanged(ComponentName componentName) {
124                     callback.onMediaSourceChanged(componentName);
125                 }
126             };
127             synchronized (mLock) {
128                 mCallbackMap.put(callback, binderCallback);
129             }
130             mService.registerMediaSourceListener(binderCallback, mode);
131         } catch (RemoteException e) {
132             handleRemoteExceptionFromCarService(e);
133         }
134     }
135 
136     /**
137      * Unregister a callback that receives updates to the active media source.
138      *
139      * @param callback the callback to be unregistered.
140      * @param mode the mode that the callback was registered to receive updates for.
141      */
142     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
removeMediaSourceListener(@onNull MediaSourceChangedListener callback, @MediaSourceMode int mode)143     public void removeMediaSourceListener(@NonNull MediaSourceChangedListener callback,
144             @MediaSourceMode int mode) {
145         try {
146             synchronized (mLock) {
147                 ICarMediaSourceListener binderCallback = mCallbackMap.remove(callback);
148                 mService.unregisterMediaSourceListener(binderCallback, mode);
149             }
150         } catch (RemoteException e) {
151             handleRemoteExceptionFromCarService(e);
152         }
153     }
154 
155     /**
156      * Retrieve a list of media sources, ordered by most recently used.
157      *
158      * @param mode the mode (playback or browse) for which to retrieve media sources from.
159      * @return non-{@code null} list of media sources, ordered by most recently used
160      */
161     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
getLastMediaSources(@ediaSourceMode int mode)162     public @NonNull List<ComponentName> getLastMediaSources(@MediaSourceMode int mode) {
163         try {
164             return mService.getLastMediaSources(mode);
165         } catch (RemoteException e) {
166             return handleRemoteExceptionFromCarService(e, null);
167         }
168     }
169 
170     /** @hide */
171     @Override
onCarDisconnected()172     public void onCarDisconnected() {
173         synchronized (mLock) {
174             mCallbackMap.clear();
175         }
176     }
177 
178     /**
179      * Returns whether the browse and playback sources can be changed independently.
180      * @return true if the browse and playback sources can be changed independently, false if it
181      * isn't or if the value could not be determined.
182      * @hide
183      */
184     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
isIndependentPlaybackConfig()185     public boolean isIndependentPlaybackConfig() {
186         try {
187             return mService.isIndependentPlaybackConfig();
188         } catch (RemoteException e) {
189             return handleRemoteExceptionFromCarService(e, null);
190         }
191     }
192 
193     /**
194      * Sets whether the browse and playback sources can be changed independently.
195      * @param independent whether the browse and playback sources can be changed independently.
196      * @hide
197      */
198     @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
setIndependentPlaybackConfig(boolean independent)199     public void setIndependentPlaybackConfig(boolean independent) {
200         try {
201             mService.setIndependentPlaybackConfig(independent);
202         } catch (RemoteException e) {
203             handleRemoteExceptionFromCarService(e);
204         }
205     }
206 }
207