blob: 29b5a3bdcc0f04b912c7868d652304bf4574b2c2 [file] [log] [blame]
keunyoungd32f4e62015-09-21 11:33:06 -07001/*
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 com.android.car.hal;
17
keunyoung5c7cb262015-10-19 10:47:45 -070018import android.util.Log;
19
20import com.android.car.AudioRoutingPolicy;
21import com.android.car.CarLog;
22import com.android.car.vehiclenetwork.VehicleNetwork;
keunyoungd32f4e62015-09-21 11:33:06 -070023import com.android.car.vehiclenetwork.VehicleNetworkConsts;
Keun-young Park0727f952015-12-21 14:30:07 -080024import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioContextFlag;
keunyounga74b9ca2015-10-21 13:33:58 -070025import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioExtFocusFlag;
26import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusIndex;
keunyoung1ab8e182015-09-24 09:25:22 -070027import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequest;
28import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusState;
keunyounga74b9ca2015-10-21 13:33:58 -070029import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioHwVariantConfigFlag;
keunyoung5c7cb262015-10-19 10:47:45 -070030import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioRoutingPolicyIndex;
keunyoungd32f4e62015-09-21 11:33:06 -070031import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioStreamState;
keunyounga74b9ca2015-10-21 13:33:58 -070032import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioStreamStateIndex;
33import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioVolumeIndex;
keunyoungd32f4e62015-09-21 11:33:06 -070034import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
keunyoung5c7cb262015-10-19 10:47:45 -070035import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
keunyoungd32f4e62015-09-21 11:33:06 -070036import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
37
38import java.io.PrintWriter;
keunyounga74b9ca2015-10-21 13:33:58 -070039import java.util.HashMap;
keunyoungd32f4e62015-09-21 11:33:06 -070040import java.util.LinkedList;
41import java.util.List;
42
43public class AudioHalService extends HalServiceBase {
44
keunyounga74b9ca2015-10-21 13:33:58 -070045 public static final int VEHICLE_AUDIO_FOCUS_REQUEST_INVALID = -1;
keunyoungd32f4e62015-09-21 11:33:06 -070046 public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN =
keunyoung1ab8e182015-09-24 09:25:22 -070047 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN;
keunyoungd32f4e62015-09-21 11:33:06 -070048 public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT =
keunyoung1ab8e182015-09-24 09:25:22 -070049 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT;
keunyoungd32f4e62015-09-21 11:33:06 -070050 public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK =
keunyoung1ab8e182015-09-24 09:25:22 -070051 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK;
keunyoungd32f4e62015-09-21 11:33:06 -070052 public static final int VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE =
keunyoung1ab8e182015-09-24 09:25:22 -070053 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE;
keunyoungd32f4e62015-09-21 11:33:06 -070054
55 public static String audioFocusRequestToString(int request) {
keunyoung1ab8e182015-09-24 09:25:22 -070056 return VehicleAudioFocusRequest.enumToString(request);
keunyoungd32f4e62015-09-21 11:33:06 -070057 }
58
keunyounga74b9ca2015-10-21 13:33:58 -070059 public static final int VEHICLE_AUDIO_FOCUS_STATE_INVALID = -1;
keunyoungd32f4e62015-09-21 11:33:06 -070060 public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN =
keunyoung1ab8e182015-09-24 09:25:22 -070061 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN;
keunyoungd32f4e62015-09-21 11:33:06 -070062 public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT =
keunyoung1ab8e182015-09-24 09:25:22 -070063 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT;
keunyoungd32f4e62015-09-21 11:33:06 -070064 public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK =
keunyoung1ab8e182015-09-24 09:25:22 -070065 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK;
keunyoungd32f4e62015-09-21 11:33:06 -070066 public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT =
keunyoung1ab8e182015-09-24 09:25:22 -070067 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT;
keunyoungd32f4e62015-09-21 11:33:06 -070068 public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS =
keunyoung1ab8e182015-09-24 09:25:22 -070069 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
keunyoungd32f4e62015-09-21 11:33:06 -070070 public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE =
keunyoung1ab8e182015-09-24 09:25:22 -070071 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE;
keunyoungd32f4e62015-09-21 11:33:06 -070072
73 public static String audioFocusStateToString(int state) {
keunyoung1ab8e182015-09-24 09:25:22 -070074 return VehicleAudioFocusState.enumToString(state);
keunyoungd32f4e62015-09-21 11:33:06 -070075 }
76
77 public static final int VEHICLE_AUDIO_STREAM_STATE_STOPPED =
78 VehicleAudioStreamState.VEHICLE_AUDIO_STREAM_STATE_STOPPED;
79 public static final int VEHICLE_AUDIO_STREAM_STATE_STARTED =
80 VehicleAudioStreamState.VEHICLE_AUDIO_STREAM_STATE_STARTED;
81
82 public static String audioStreamStateToString(int state) {
83 return VehicleAudioStreamState.enumToString(state);
84 }
85
keunyounga74b9ca2015-10-21 13:33:58 -070086 public static final int VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG =
87 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG;
88 public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG =
89 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG;
90 public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT_FLAG =
91 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT_FLAG;
92 public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG =
93 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG;
94
keunyoungd32f4e62015-09-21 11:33:06 -070095 public static final int STREAM_NUM_DEFAULT = 0;
96
97 public interface AudioHalListener {
keunyounga74b9ca2015-10-21 13:33:58 -070098 /**
99 * Audio focus change from car.
100 * @param focusState
101 * @param streams
102 * @param externalFocus Flags of active external audio focus.
103 * 0 means no external audio focus.
104 */
105 void onFocusChange(int focusState, int streams, int externalFocus);
106 /**
107 * Audio volume change from car.
108 * @param streamNumber
109 * @param volume
110 * @param volumeState
111 */
keunyoung5c7cb262015-10-19 10:47:45 -0700112 void onVolumeChange(int streamNumber, int volume, int volumeState);
keunyounga74b9ca2015-10-21 13:33:58 -0700113 /**
114 * Volume limit change from car.
115 * @param streamNumber
116 * @param volume
117 */
118 void onVolumeLimitChange(int streamNumber, int volume);
119 /**
120 * Stream state change (start / stop) from android
121 * @param streamNumber
122 * @param state
123 */
keunyoung5c7cb262015-10-19 10:47:45 -0700124 void onStreamStatusChange(int streamNumber, int state);
keunyoungd32f4e62015-09-21 11:33:06 -0700125 }
126
127 private final VehicleHal mVehicleHal;
128 private AudioHalListener mListener;
keunyoung5c7cb262015-10-19 10:47:45 -0700129 private int mVariant;
130
131 private List<VehiclePropValue> mQueuedEvents;
keunyoungd32f4e62015-09-21 11:33:06 -0700132
keunyounga74b9ca2015-10-21 13:33:58 -0700133 private final HashMap<Integer, VehiclePropConfig> mProperties = new HashMap<>();
134
keunyoungd32f4e62015-09-21 11:33:06 -0700135 public AudioHalService(VehicleHal vehicleHal) {
136 mVehicleHal = vehicleHal;
137 }
138
keunyoung5c7cb262015-10-19 10:47:45 -0700139 public void setListener(AudioHalListener listener) {
140 List<VehiclePropValue> eventsToDispatch = null;
141 synchronized (this) {
142 mListener = listener;
143 if (mQueuedEvents != null) {
144 eventsToDispatch = mQueuedEvents;
145 mQueuedEvents = null;
146 }
147 }
148 if (eventsToDispatch != null) {
149 dispatchEventToListener(listener, eventsToDispatch);
150 }
151 }
152
153 public void setAudioRoutingPolicy(AudioRoutingPolicy policy) {
154 VehicleNetwork vn = mVehicleHal.getVehicleNetwork();
155 VehiclePropConfigs configs = vn.listProperties(
156 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY);
157 if (configs == null) {
158 Log.w(CarLog.TAG_AUDIO,
159 "Vehicle HAL did not implement VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY");
160 return;
161 }
162 int[] policyToSet = new int[2];
163 for (int i = 0; i < policy.getPhysicalStreamsCount(); i++) {
164 policyToSet[VehicleAudioRoutingPolicyIndex.VEHICLE_AUDIO_ROUTING_POLICY_INDEX_STREAM] =
165 i;
166 int streams = 0;
167 for (int logicalStream : policy.getLogicalStreamsForPhysicalStream(i)) {
168 streams |= logicalStreamToHalStreamType(logicalStream);
169 }
170 policyToSet[VehicleAudioRoutingPolicyIndex.VEHICLE_AUDIO_ROUTING_POLICY_INDEX_CONTEXTS]
171 = streams;
172 vn.setIntVectorProperty(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY,
173 policyToSet);
174 }
175 }
176
177 private static int logicalStreamToHalStreamType(int logicalStream) {
178 switch (logicalStream) {
179 case AudioRoutingPolicy.STREAM_TYPE_CALL:
Keun-young Park0727f952015-12-21 14:30:07 -0800180 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_CALL_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700181 case AudioRoutingPolicy.STREAM_TYPE_MEDIA:
Keun-young Park0727f952015-12-21 14:30:07 -0800182 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700183 case AudioRoutingPolicy.STREAM_TYPE_NAV_GUIDANCE:
Keun-young Park0727f952015-12-21 14:30:07 -0800184 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700185 case AudioRoutingPolicy.STREAM_TYPE_VOICE_COMMAND:
Keun-young Park0727f952015-12-21 14:30:07 -0800186 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_VOICE_COMMAND_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700187 case AudioRoutingPolicy.STREAM_TYPE_ALARM:
Keun-young Park0727f952015-12-21 14:30:07 -0800188 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_ALARM_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700189 case AudioRoutingPolicy.STREAM_TYPE_NOTIFICATION:
Keun-young Park0727f952015-12-21 14:30:07 -0800190 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NOTIFICATION_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700191 case AudioRoutingPolicy.STREAM_TYPE_UNKNOWN:
Keun-young Park0727f952015-12-21 14:30:07 -0800192 return VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_UNKNOWN_FLAG;
keunyoung5c7cb262015-10-19 10:47:45 -0700193 default:
194 Log.w(CarLog.TAG_AUDIO, "Unknown logical stream:" + logicalStream);
195 return 0;
196 }
keunyoungd32f4e62015-09-21 11:33:06 -0700197 }
198
199 public synchronized void requestAudioFocusChange(int request, int streams) {
keunyounga74b9ca2015-10-21 13:33:58 -0700200 requestAudioFocusChange(request, streams, VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG);
201 }
202
203 public synchronized void requestAudioFocusChange(int request, int streams, int extFocus) {
204 int[] payload = { request, streams, extFocus };
keunyoungd32f4e62015-09-21 11:33:06 -0700205 mVehicleHal.getVehicleNetwork().setIntVectorProperty(
206 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, payload);
207 }
208
keunyoung5c7cb262015-10-19 10:47:45 -0700209 public synchronized int getHwVariant() {
210 return mVariant;
211 }
212
keunyounga74b9ca2015-10-21 13:33:58 -0700213 public synchronized boolean isRadioExternal() {
214 VehiclePropConfig config = mProperties.get(
215 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT);
216 if (config == null) {
217 return true;
218 }
Keun-young Park0727f952015-12-21 14:30:07 -0800219 return (config.getConfigArray(0) &
keunyounga74b9ca2015-10-21 13:33:58 -0700220 VehicleAudioHwVariantConfigFlag.VEHICLE_AUDIO_HW_VARIANT_FLAG_PASS_RADIO_AUDIO_FOCUS_FLAG)
221 == 0;
222 }
223
224 public synchronized boolean isFocusSupported() {
225 return isPropertySupportedLocked(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS);
226 }
227
228 private boolean isPropertySupportedLocked(int property) {
229 VehiclePropConfig config = mProperties.get(property);
230 return config != null;
231 }
232
keunyoungd32f4e62015-09-21 11:33:06 -0700233 @Override
234 public synchronized void init() {
keunyounga74b9ca2015-10-21 13:33:58 -0700235 for (VehiclePropConfig config : mProperties.values()) {
236 if (VehicleHal.isPropertySubscribable(config)) {
237 mVehicleHal.subscribeProperty(this, config.getProp(), 0);
keunyoung5c7cb262015-10-19 10:47:45 -0700238 }
239 }
240 try {
241 mVariant = mVehicleHal.getVehicleNetwork().getIntProperty(
242 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT);
243 } catch (IllegalArgumentException e) {
244 // no variant. Set to default, 0.
245 mVariant = 0;
keunyoungd32f4e62015-09-21 11:33:06 -0700246 }
247 }
248
249 @Override
250 public synchronized void release() {
keunyounga74b9ca2015-10-21 13:33:58 -0700251 for (VehiclePropConfig config : mProperties.values()) {
252 if (VehicleHal.isPropertySubscribable(config)) {
253 mVehicleHal.unsubscribeProperty(this, config.getProp());
keunyoung5c7cb262015-10-19 10:47:45 -0700254 }
keunyoungd32f4e62015-09-21 11:33:06 -0700255 }
keunyounga74b9ca2015-10-21 13:33:58 -0700256 mProperties.clear();
keunyoungd32f4e62015-09-21 11:33:06 -0700257 }
258
259 @Override
260 public synchronized List<VehiclePropConfig> takeSupportedProperties(
261 List<VehiclePropConfig> allProperties) {
keunyoungd32f4e62015-09-21 11:33:06 -0700262 for (VehiclePropConfig p : allProperties) {
263 switch (p.getProp()) {
264 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS:
keunyoungd32f4e62015-09-21 11:33:06 -0700265 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME:
keunyoung5c7cb262015-10-19 10:47:45 -0700266 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT:
keunyoung5c7cb262015-10-19 10:47:45 -0700267 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT:
keunyoungd32f4e62015-09-21 11:33:06 -0700268 case VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE:
keunyounga74b9ca2015-10-21 13:33:58 -0700269 mProperties.put(p.getProp(), p);
keunyoungd32f4e62015-09-21 11:33:06 -0700270 break;
271 }
272 }
keunyounga74b9ca2015-10-21 13:33:58 -0700273 return new LinkedList<VehiclePropConfig>(mProperties.values());
keunyoungd32f4e62015-09-21 11:33:06 -0700274 }
275
276 @Override
277 public void handleHalEvents(List<VehiclePropValue> values) {
278 AudioHalListener listener = null;
279 synchronized (this) {
280 listener = mListener;
keunyoung5c7cb262015-10-19 10:47:45 -0700281 if (listener == null) {
282 if (mQueuedEvents == null) {
283 mQueuedEvents = new LinkedList<VehiclePropValue>();
284 }
285 mQueuedEvents.addAll(values);
286 }
keunyoungd32f4e62015-09-21 11:33:06 -0700287 }
keunyoung5c7cb262015-10-19 10:47:45 -0700288 if (listener != null) {
289 dispatchEventToListener(listener, values);
keunyoungd32f4e62015-09-21 11:33:06 -0700290 }
keunyoung5c7cb262015-10-19 10:47:45 -0700291 }
292
293 private void dispatchEventToListener(AudioHalListener listener, List<VehiclePropValue> values) {
keunyoungd32f4e62015-09-21 11:33:06 -0700294 for (VehiclePropValue v : values) {
295 switch (v.getProp()) {
296 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS: {
keunyounga74b9ca2015-10-21 13:33:58 -0700297 int focusState = v.getInt32Values(
298 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_FOCUS);
299 int streams = v.getInt32Values(
300 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_STREAMS);
301 int externalFocus = v.getInt32Values(
302 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE);
303 listener.onFocusChange(focusState, streams, externalFocus);
keunyoungd32f4e62015-09-21 11:33:06 -0700304 } break;
305 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME: {
keunyounga74b9ca2015-10-21 13:33:58 -0700306 int volume = v.getInt32Values(
307 VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_VOLUME);
308 int streamNum = v.getInt32Values(
309 VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STREAM);
310 int volumeState = v.getInt32Values(
311 VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STATE);
keunyoung5c7cb262015-10-19 10:47:45 -0700312 listener.onVolumeChange(streamNum, volume, volumeState);
313 } break;
314 case VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT: {
315 //TODO
keunyoungd32f4e62015-09-21 11:33:06 -0700316 } break;
317 case VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE: {
keunyounga74b9ca2015-10-21 13:33:58 -0700318 int state = v.getInt32Values(
319 VehicleAudioStreamStateIndex.VEHICLE_AUDIO_STREAM_STATE_INDEX_STATE);
320 int streamNum = v.getInt32Values(
321 VehicleAudioStreamStateIndex.VEHICLE_AUDIO_STREAM_STATE_INDEX_STREAM);
keunyoung5c7cb262015-10-19 10:47:45 -0700322 listener.onStreamStatusChange(streamNum, state);
keunyoungd32f4e62015-09-21 11:33:06 -0700323 } break;
324 }
325 }
326 }
327
328 @Override
329 public void dump(PrintWriter writer) {
keunyoung5c7cb262015-10-19 10:47:45 -0700330 writer.println("*Audio HAL*");
331 writer.println(" audio H/W variant:" + mVariant);
keunyounga74b9ca2015-10-21 13:33:58 -0700332 writer.println(" Supported properties");
333 VehicleHal.dumpProperties(writer, mProperties.values());
keunyoungd32f4e62015-09-21 11:33:06 -0700334 }
335
336}