CarAudioManager.java revision d72b53500006e84b0c69e650878267c693c164a3
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 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        try {
132            return mService.getAudioAttributesForCarUsage(carUsage);
133        } catch (RemoteException e) {
134            return createAudioAttributes(AudioAttributes.CONTENT_TYPE_UNKNOWN,
135                    AudioAttributes.USAGE_UNKNOWN);
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 IllegalArgumentException {
152        try {
153            return mService.getAudioAttributesForRadio(radioType);
154        } catch (RemoteException e) {
155            return createAudioAttributes(AudioAttributes.CONTENT_TYPE_UNKNOWN,
156                    AudioAttributes.USAGE_UNKNOWN);
157        }
158    }
159
160    /**
161     * Get AudioAttributes for external audio source.
162     *
163     * @param externalSourceType String specifying the desired source type. Should use only what is
164     *        listed in {@link #getSupportedExternalSourceTypes()}.
165     * @return
166     * @throws IllegalArgumentException If not supported type is passed.
167     *
168     * @hide
169     */
170    public AudioAttributes getAudioAttributesForExternalSource(String externalSourceType)
171            throws IllegalArgumentException {
172        try {
173            return mService.getAudioAttributesForExternalSource(externalSourceType);
174        } catch (RemoteException e) {
175            return createAudioAttributes(AudioAttributes.CONTENT_TYPE_UNKNOWN,
176                    AudioAttributes.USAGE_UNKNOWN);
177        }
178    }
179
180    /**
181     * List all supported external audio sources.
182     *
183     * @return
184     *
185     * @hide
186     */
187    public String[] getSupportedExternalSourceTypes() {
188        try {
189            return mService.getSupportedExternalSourceTypes();
190        } catch (RemoteException e) {
191            return null;
192        }
193    }
194
195    /**
196     * List all supported radio sources.
197     *
198     * @return
199     *
200     * @hide
201     */
202    public String[] getSupportedRadioTypes() {
203        try {
204            return mService.getSupportedRadioTypes();
205        } catch (RemoteException e) {
206            return null;
207        }
208    }
209
210    /**
211     * Request audio focus.
212     * Send a request to obtain the audio focus.
213     * @param l
214     * @param requestAttributes
215     * @param durationHint
216     * @param flags
217     */
218    public int requestAudioFocus(OnAudioFocusChangeListener l,
219                                 AudioAttributes requestAttributes,
220                                 int durationHint,
221                                 int flags) throws IllegalArgumentException {
222        return mAudioManager.requestAudioFocus(l, requestAttributes, durationHint, flags);
223    }
224
225    /**
226     * Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
227     * @param l
228     * @param aa
229     * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
230     */
231    public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
232        return mAudioManager.abandonAudioFocus(l, aa);
233    }
234
235    /**
236     * Sets the volume index for a particular stream.
237     *
238     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
239     *
240     * @param streamType The stream whose volume index should be set.
241     * @param index The volume index to set. See
242     *            {@link #getStreamMaxVolume(int)} for the largest valid value.
243     * @param flags One or more flags (e.g., {@link android.media.AudioManager#FLAG_SHOW_UI},
244     *              {@link android.media.AudioManager#FLAG_PLAY_SOUND})
245     */
246    @SystemApi
247    public void setStreamVolume(int streamType, int index, int flags)
248            throws CarNotConnectedException {
249        try {
250            mService.setStreamVolume(streamType, index, flags);
251        } catch (RemoteException e) {
252            Log.e(CarLibLog.TAG_CAR, "setStreamVolume failed", e);
253            throw new CarNotConnectedException(e);
254        }
255    }
256
257    /**
258     * Registers a global volume controller interface.
259     *
260     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
261     *
262     * @hide
263     */
264    @SystemApi
265    public void setVolumeController(IVolumeController controller)
266            throws CarNotConnectedException {
267        try {
268            mService.setVolumeController(controller);
269        } catch (RemoteException e) {
270            Log.e(CarLibLog.TAG_CAR, "setVolumeController failed", e);
271            throw new CarNotConnectedException(e);
272        }
273    }
274
275    /**
276     * Returns the maximum volume index for a particular stream.
277     *
278     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
279     *
280     * @param stream The stream type whose maximum volume index is returned.
281     * @return The maximum valid volume index for the stream.
282     */
283    @SystemApi
284    public int getStreamMaxVolume(int stream) throws CarNotConnectedException {
285        try {
286            return mService.getStreamMaxVolume(stream);
287        } catch (RemoteException e) {
288            Log.e(CarLibLog.TAG_CAR, "getStreamMaxVolume failed", e);
289            throw new CarNotConnectedException(e);
290        }
291    }
292
293    /**
294     * Returns the minimum volume index for a particular stream.
295     *
296     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
297     *
298     * @param stream The stream type whose maximum volume index is returned.
299     * @return The maximum valid volume index for the stream.
300     */
301    @SystemApi
302    public int getStreamMinVolume(int stream) throws CarNotConnectedException {
303        try {
304            return mService.getStreamMinVolume(stream);
305        } catch (RemoteException e) {
306            Log.e(CarLibLog.TAG_CAR, "getStreamMaxVolume failed", e);
307            throw new CarNotConnectedException(e);
308        }
309    }
310
311    /**
312     * Returns the current volume index for a particular stream.
313     *
314     * Requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
315     *
316     * @param stream The stream type whose volume index is returned.
317     * @return The current volume index for the stream.
318     *
319     * @see #getStreamMaxVolume(int)
320     * @see #setStreamVolume(int, int, int)
321     */
322    @SystemApi
323    public int getStreamVolume(int stream) throws CarNotConnectedException {
324        try {
325            return mService.getStreamVolume(stream);
326        } catch (RemoteException e) {
327            Log.e(CarLibLog.TAG_CAR, "getStreamVolume failed", e);
328            throw new CarNotConnectedException(e);
329        }
330    }
331
332    /**
333     * Check if media audio is muted or not. This will include music and radio. Any application
334     * taking audio focus for media stream will get it out of mute state.
335     *
336     * @return true if media is muted.
337     * @throws CarNotConnectedException if the connection to the car service has been lost.
338     * @hide
339     */
340    @SystemApi
341    public boolean isMediaMuted() throws CarNotConnectedException {
342        try {
343            return mService.isMediaMuted();
344        } catch (RemoteException e) {
345            Log.e(CarLibLog.TAG_CAR, "isMediaMuted failed", e);
346            throw new CarNotConnectedException(e);
347        }
348    }
349
350    /**
351     * Mute or unmute media stream including radio. This can involve audio focus change to stop
352     * whatever app holding audio focus now. If requester is currently holding audio focus,
353     * it will get LOSS_TRANSIENT focus loss.
354     * This API requires {@link android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME} permission.
355     *
356     * @param mute
357     * @return Mute state of system after the request. Note that mute request can fail if there
358     *         is higher priority audio already being played like phone call.
359     * @throws CarNotConnectedException if the connection to the car service has been lost.
360     * @hide
361     */
362    @SystemApi
363    public boolean setMediaMute(boolean mute) throws CarNotConnectedException {
364        try {
365            return mService.setMediaMute(mute);
366        } catch (RemoteException e) {
367            Log.e(CarLibLog.TAG_CAR, "setMediaMute failed", e);
368            throw new CarNotConnectedException(e);
369        }
370    }
371
372    @Override
373    public void onCarDisconnected() {
374    }
375
376    /** @hide */
377    public CarAudioManager(IBinder service, Context context) {
378        mService = ICarAudio.Stub.asInterface(service);
379        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
380    }
381
382    private AudioAttributes createAudioAttributes(int contentType, int usage) {
383        AudioAttributes.Builder builder = new AudioAttributes.Builder();
384        return builder.setContentType(contentType).setUsage(usage).build();
385    }
386}
387