CarAudioManager.java revision 150d8de43e71a624106e90bcc04067414c42ef18
1/*
2 * Copyright (C) 2015 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.car.media;
17
18import android.annotation.IntDef;
19import android.annotation.SystemApi;
20import android.car.CarLibLog;
21import android.car.CarNotConnectedException;
22import android.content.Context;
23import android.media.AudioAttributes;
24import android.media.AudioManager;
25import android.media.AudioManager.OnAudioFocusChangeListener;
26import android.media.IVolumeController;
27import android.os.IBinder;
28import android.os.RemoteException;
29import android.car.CarManagerBase;
30import android.util.Log;
31
32import java.lang.annotation.Retention;
33import java.lang.annotation.RetentionPolicy;
34
35/**
36 * APIs for handling car specific audio stuffs.
37 */
38public final class CarAudioManager implements CarManagerBase {
39
40    /**
41     * Audio usage for unspecified type.
42     */
43    public static final int CAR_AUDIO_USAGE_DEFAULT = 0;
44    /**
45     * Audio usage for playing music.
46     */
47    public static final int CAR_AUDIO_USAGE_MUSIC = 1;
48    /**
49     * Audio usage for H/W radio.
50     */
51    public static final int CAR_AUDIO_USAGE_RADIO = 2;
52    /**
53     * Audio usage for playing navigation guidance.
54     */
55    public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3;
56    /**
57     * Audio usage for voice call
58     */
59    public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4;
60    /**
61     * Audio usage for voice search or voice command.
62     */
63    public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5;
64    /**
65     * Audio usage for playing alarm.
66     */
67    public static final int CAR_AUDIO_USAGE_ALARM = 6;
68    /**
69     * Audio usage for notification sound.
70     */
71    public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7;
72    /**
73     * Audio usage for system sound like UI feedback.
74     */
75    public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8;
76    /**
77     * Audio usage for playing safety alert.
78     */
79    public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9;
80    /**
81     * Audio usage for external audio usage.
82     * @hide
83     */
84    public static final int CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE = 10;
85
86    /** @hide */
87    public static final int CAR_AUDIO_USAGE_MAX = CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
88
89    /** @hide */
90    @IntDef({CAR_AUDIO_USAGE_DEFAULT, CAR_AUDIO_USAGE_MUSIC, CAR_AUDIO_USAGE_RADIO,
91        CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE, CAR_AUDIO_USAGE_VOICE_CALL,
92        CAR_AUDIO_USAGE_VOICE_COMMAND, CAR_AUDIO_USAGE_ALARM, CAR_AUDIO_USAGE_NOTIFICATION,
93        CAR_AUDIO_USAGE_SYSTEM_SOUND, CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT,
94        CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE})
95    @Retention(RetentionPolicy.SOURCE)
96    public @interface CarAudioUsage {}
97
98    /** @hide */
99    public static final String CAR_RADIO_TYPE_AM_FM = "RADIO_AM_FM";
100    /** @hide */
101    public static final String CAR_RADIO_TYPE_AM_FM_HD = "RADIO_AM_FM_HD";
102    /** @hide */
103    public static final String CAR_RADIO_TYPE_DAB = "RADIO_DAB";
104    /** @hide */
105    public static final String CAR_RADIO_TYPE_SATELLITE = "RADIO_SATELLITE";
106
107    /** @hide */
108    public static final String CAR_EXTERNAL_SOURCE_TYPE_CD_DVD = "CD_DVD";
109    /** @hide */
110    public static final String CAR_EXTERNAL_SOURCE_TYPE_AUX_IN0 = "AUX_IN0";
111    /** @hide */
112    public static final String CAR_EXTERNAL_SOURCE_TYPE_AUX_IN1 = "AUX_IN1";
113    /** @hide */
114    public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE = "EXT_NAV_GUIDANCE";
115    /** @hide */
116    public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_VOICE_CALL = "EXT_VOICE_CALL";
117    /** @hide */
118    public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_VOICE_COMMAND = "EXT_VOICE_COMMAND";
119    /** @hide */
120    public static final String CAR_EXTERNAL_SOURCE_TYPE_EXT_SAFETY_ALERT = "EXT_SAFETY_ALERT";
121
122    private final ICarAudio mService;
123    private final AudioManager mAudioManager;
124
125    /**
126     * Get {@link AudioAttributes} relevant for the given usage in car.
127     * @param carUsage
128     * @return
129     */
130    public AudioAttributes getAudioAttributesForCarUsage(@CarAudioUsage int carUsage)
131            throws CarNotConnectedException {
132        try {
133            return mService.getAudioAttributesForCarUsage(carUsage);
134        } catch (RemoteException e) {
135            throw new CarNotConnectedException();
136        }
137    }
138
139    /**
140     * Get AudioAttributes for radio. This is necessary when there are multiple types of radio
141     * in system.
142     *
143     * @param radioType String specifying the desired radio type. Should use only what is listed in
144     *        {@link #getSupportedRadioTypes()}.
145     * @return
146     * @throws IllegalArgumentException If not supported type is passed.
147     *
148     * @hide
149     */
150    public AudioAttributes getAudioAttributesForRadio(String radioType)
151            throws CarNotConnectedException, IllegalArgumentException {
152        try {
153            return mService.getAudioAttributesForRadio(radioType);
154        } catch (RemoteException e) {
155            throw new CarNotConnectedException();
156        }
157    }
158
159    /**
160     * Get AudioAttributes for external audio source.
161     *
162     * @param externalSourceType String specifying the desired source type. Should use only what is
163     *        listed in {@link #getSupportedExternalSourceTypes()}.
164     * @return
165     * @throws IllegalArgumentException If not supported type is passed.
166     *
167     * @hide
168     */
169    public AudioAttributes getAudioAttributesForExternalSource(String externalSourceType)
170            throws CarNotConnectedException, IllegalArgumentException {
171        try {
172            return mService.getAudioAttributesForExternalSource(externalSourceType);
173        } catch (RemoteException e) {
174            throw new CarNotConnectedException();
175        }
176    }
177
178    /**
179     * List all supported external audio sources.
180     *
181     * @return
182     *
183     * @hide
184     */
185    public String[] getSupportedExternalSourceTypes() throws CarNotConnectedException {
186        try {
187            return mService.getSupportedExternalSourceTypes();
188        } catch (RemoteException e) {
189            throw new CarNotConnectedException();
190        }
191    }
192
193    /**
194     * List all supported radio sources.
195     *
196     * @return
197     *
198     * @hide
199     */
200    public String[] getSupportedRadioTypes() throws CarNotConnectedException {
201        try {
202            return mService.getSupportedRadioTypes();
203        } catch (RemoteException e) {
204            throw new CarNotConnectedException();
205        }
206    }
207
208    /**
209     * Request audio focus.
210     * Send a request to obtain the audio focus.
211     * @param l
212     * @param requestAttributes
213     * @param durationHint
214     * @param flags
215     */
216    public int requestAudioFocus(OnAudioFocusChangeListener l,
217                                 AudioAttributes requestAttributes,
218                                 int durationHint,
219                                 int flags)
220                                         throws CarNotConnectedException, IllegalArgumentException {
221        return mAudioManager.requestAudioFocus(l, requestAttributes, durationHint, flags);
222    }
223
224    /**
225     * Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
226     * @param l
227     * @param aa
228     */
229    public void abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
230        mAudioManager.abandonAudioFocus(l, aa);
231    }
232
233    /**
234     * Sets the volume index for a particular stream.
235     *
236     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
237     *
238     * @param streamType The stream whose volume index should be set.
239     * @param index The volume index to set. See
240     *            {@link #getStreamMaxVolume(int)} for the largest valid value.
241     * @param flags One or more flags (e.g., {@link android.media.AudioManager#FLAG_SHOW_UI},
242     *              {@link android.media.AudioManager#FLAG_PLAY_SOUND})
243     */
244    @SystemApi
245    public void setStreamVolume(int streamType, int index, int flags)
246            throws CarNotConnectedException {
247        try {
248            mService.setStreamVolume(streamType, index, flags);
249        } catch (RemoteException e) {
250            Log.e(CarLibLog.TAG_CAR, "setStreamVolume failed", e);
251            throw new CarNotConnectedException(e);
252        }
253    }
254
255    /**
256     * Registers a global volume controller interface.
257     *
258     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
259     *
260     * @hide
261     */
262    @SystemApi
263    public void setVolumeController(IVolumeController controller)
264            throws CarNotConnectedException {
265        try {
266            mService.setVolumeController(controller);
267        } catch (RemoteException e) {
268            Log.e(CarLibLog.TAG_CAR, "setVolumeController failed", e);
269            throw new CarNotConnectedException(e);
270        }
271    }
272
273    /**
274     * Returns the maximum volume index for a particular stream.
275     *
276     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
277     *
278     * @param stream The stream type whose maximum volume index is returned.
279     * @return The maximum valid volume index for the stream.
280     */
281    @SystemApi
282    public int getStreamMaxVolume(int stream) throws CarNotConnectedException {
283        try {
284            return mService.getStreamMaxVolume(stream);
285        } catch (RemoteException e) {
286            Log.e(CarLibLog.TAG_CAR, "getStreamMaxVolume failed", e);
287            throw new CarNotConnectedException(e);
288        }
289    }
290
291    /**
292     * Returns the minimum volume index for a particular stream.
293     *
294     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
295     *
296     * @param stream The stream type whose maximum volume index is returned.
297     * @return The maximum valid volume index for the stream.
298     */
299    @SystemApi
300    public int getStreamMinVolume(int stream) throws CarNotConnectedException {
301        try {
302            return mService.getStreamMinVolume(stream);
303        } catch (RemoteException e) {
304            Log.e(CarLibLog.TAG_CAR, "getStreamMaxVolume failed", e);
305            throw new CarNotConnectedException(e);
306        }
307    }
308
309    /**
310     * Returns the current volume index for a particular stream.
311     *
312     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
313     *
314     * @param stream The stream type whose volume index is returned.
315     * @return The current volume index for the stream.
316     *
317     * @see #getStreamMaxVolume(int)
318     * @see #setStreamVolume(int, int, int)
319     */
320    @SystemApi
321    public int getStreamVolume(int stream) throws CarNotConnectedException {
322        try {
323            return mService.getStreamVolume(stream);
324        } catch (RemoteException e) {
325            Log.e(CarLibLog.TAG_CAR, "getStreamVolume failed", e);
326            throw new CarNotConnectedException(e);
327        }
328    }
329
330    /**
331     * Check if media audio is muted or not. This will include music and radio. Any application
332     * taking audio focus for media stream will get it out of mute state.
333     *
334     * @return true if media is muted.
335     * @throws CarNotConnectedException if the connection to the car service has been lost.
336     * @hide
337     */
338    @SystemApi
339    public boolean isMediaMuted() throws CarNotConnectedException {
340        try {
341            return mService.isMediaMuted();
342        } catch (RemoteException e) {
343            Log.e(CarLibLog.TAG_CAR, "isMediaMuted failed", e);
344            throw new CarNotConnectedException(e);
345        }
346    }
347
348    /**
349     * Mute or unmute media stream including radio. This can involve audio focus change to stop
350     * whatever app holding audio focus now. If requester is currently holding audio focus,
351     * it will get LOSS_TRANSIENT focus loss.
352     * This API requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
353     *
354     * @param mute
355     * @return Mute state of system after the request. Note that mute request can fail if there
356     *         is higher priority audio already being played like phone call.
357     * @throws CarNotConnectedException if the connection to the car service has been lost.
358     * @hide
359     */
360    @SystemApi
361    public boolean setMediaMute(boolean mute) throws CarNotConnectedException {
362        try {
363            return mService.setMediaMute(mute);
364        } catch (RemoteException e) {
365            Log.e(CarLibLog.TAG_CAR, "setMediaMute failed", e);
366            throw new CarNotConnectedException(e);
367        }
368    }
369
370    /** @hide */
371    @Override
372    public void onCarDisconnected() {
373    }
374
375    /** @hide */
376    public CarAudioManager(IBinder service, Context context) {
377        mService = ICarAudio.Stub.asInterface(service);
378        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
379    }
380
381    private AudioAttributes createAudioAttributes(int contentType, int usage) {
382        AudioAttributes.Builder builder = new AudioAttributes.Builder();
383        return builder.setContentType(contentType).setUsage(usage).build();
384    }
385}
386