CarEmulator.java revision 57787b006b4b4967bc1e390c672e34150a603e7a
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 */ 16 17package com.google.android.car.kitchensink; 18 19import android.car.Car; 20import android.car.test.VehicleHalEmulator.VehicleHalPropertyHandler; 21import android.car.test.VehicleHalEmulator; 22import android.os.SystemClock; 23import android.util.SparseIntArray; 24import android.view.KeyEvent; 25 26import com.android.car.vehiclenetwork.VehicleNetworkConsts; 27import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusIndex; 28import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequest; 29import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusState; 30import com.android.car.vehiclenetwork.VehiclePropConfigUtil; 31import com.android.car.vehiclenetwork.VehiclePropValueUtil; 32import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePermissionModel; 33import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess; 34import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode; 35import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType; 36import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 37 38import java.util.ArrayList; 39import java.util.List; 40 41public class CarEmulator { 42 43 private final Car mCar; 44 private final VehicleHalEmulator mHalEmulator; 45 46 private final AudioFocusPropertyHandler mAudioFocusPropertyHandler = 47 new AudioFocusPropertyHandler(); 48 private final AudioStreamStatePropertyHandler mAudioStreamStatePropertyHandler = 49 new AudioStreamStatePropertyHandler(); 50 private final AudioVolumeLimitPropertyHandler mAudioVolumeLimitPropertyHandler = 51 new AudioVolumeLimitPropertyHandler(); 52 private final SingleChannelVolumeHandler mVolumeHandler; 53 private static final int STREAM_COUNT = 2; 54 private static final int[] STREAM_MAX_VOLUME = {30, 30}; 55 private static final int[] STREAM_MIN_VOLUME = {0, 0}; 56 57 public CarEmulator(Car car) { 58 mCar = car; 59 mHalEmulator = new VehicleHalEmulator(car); 60 List<Integer> maxVols = new ArrayList<>(); 61 List<Integer> minVols = new ArrayList<>(); 62 for(int i = 0; i < STREAM_COUNT; i++) { 63 maxVols.add(STREAM_MAX_VOLUME[i]); 64 minVols.add(STREAM_MIN_VOLUME[i]); 65 } 66 mVolumeHandler = new SingleChannelVolumeHandler(minVols, maxVols); 67 int zones = (1<<maxVols.size()) - 1; 68 69 mHalEmulator.addProperty( 70 VehiclePropConfigUtil.getBuilder( 71 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, 72 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE, 73 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 74 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4, 75 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 76 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 77 mAudioFocusPropertyHandler); 78 mHalEmulator.addProperty( 79 VehiclePropConfigUtil.getBuilder( 80 VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE, 81 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE, 82 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 83 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2, 84 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 85 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 86 mAudioStreamStatePropertyHandler); 87 mHalEmulator.addProperty( 88 VehiclePropConfigUtil.getBuilder(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME, 89 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE, 90 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 91 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3, 92 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 93 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/, 94 maxVols, minVols).setZones(zones).build(), 95 mVolumeHandler); 96 mHalEmulator.addProperty( 97 VehiclePropConfigUtil.getBuilder( 98 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT, 99 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE, 100 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 101 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2, 102 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 103 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 104 mAudioVolumeLimitPropertyHandler); 105 106 mHalEmulator.addProperty( 107 VehiclePropConfigUtil.getBuilder( 108 VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, 109 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ, 110 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 111 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4, 112 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 113 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 114 mHWKeyHandler); 115 } 116 117 public void start() { 118 mHalEmulator.start(); 119 } 120 121 public void stop() { 122 mHalEmulator.stop(); 123 } 124 125 public void setAudioFocusControl(boolean reject) { 126 mAudioFocusPropertyHandler.setAudioFocusControl(reject); 127 } 128 129 public void injectVolumeKey(boolean volUp) { 130 int[] values = { 131 VehicleNetworkConsts.VehicleHwKeyInputAction.VEHICLE_HW_KEY_INPUT_ACTION_DOWN, 132 volUp ? KeyEvent.KEYCODE_VOLUME_UP : KeyEvent.KEYCODE_VOLUME_DOWN, 0, 0 }; 133 134 VehiclePropValue injectValue = VehiclePropValueUtil.createIntVectorValue( 135 VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, values, 136 SystemClock.elapsedRealtimeNanos()); 137 138 mHalEmulator.injectEvent(injectValue); 139 140 int[] upValues = { 141 VehicleNetworkConsts.VehicleHwKeyInputAction.VEHICLE_HW_KEY_INPUT_ACTION_UP, 142 volUp ? KeyEvent.KEYCODE_VOLUME_UP : KeyEvent.KEYCODE_VOLUME_DOWN, 0, 0 }; 143 144 injectValue = VehiclePropValueUtil.createIntVectorValue( 145 VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, upValues, 146 SystemClock.elapsedRealtimeNanos()); 147 148 mHalEmulator.injectEvent(injectValue); 149 } 150 151 private final VehicleHalEmulator.VehicleHalPropertyHandler mHWKeyHandler = 152 new VehicleHalEmulator.VehicleHalPropertyHandler() { 153 @Override 154 public void onPropertySet(VehiclePropValue value) { 155 } 156 157 @Override 158 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 159 int[] values = {0, 0, 0, 0 }; 160 return VehiclePropValueUtil.createIntVectorValue( 161 VehicleNetworkConsts.VEHICLE_PROPERTY_HW_KEY_INPUT, values, 162 SystemClock.elapsedRealtimeNanos()); 163 } 164 165 @Override 166 public void onPropertySubscribe(int property, float sampleRate, int zones) { 167 } 168 169 @Override 170 public void onPropertyUnsubscribe(int property) { 171 } 172 }; 173 174 private class AudioFocusPropertyHandler implements VehicleHalPropertyHandler { 175 private boolean mRejectFocus; 176 private int mCurrentFocusState = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 177 private int mCurrentFocusStreams = 0; 178 private int mCurrentFocusExtState = 0; 179 180 public void setAudioFocusControl(boolean reject) { 181 VehiclePropValue injectValue = null; 182 synchronized (this) { 183 if (reject) { 184 if (!mRejectFocus) { 185 mCurrentFocusState = VehicleAudioFocusState 186 .VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE; 187 mCurrentFocusStreams = 0; 188 mCurrentFocusExtState = 0; 189 mRejectFocus = true; 190 int[] values = { mCurrentFocusState, mCurrentFocusStreams, 191 mCurrentFocusExtState, 0}; 192 injectValue = VehiclePropValueUtil.createIntVectorValue( 193 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 194 SystemClock.elapsedRealtimeNanos()); 195 } 196 } else { 197 if (mRejectFocus) { 198 mCurrentFocusState = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 199 mCurrentFocusStreams = 0; 200 mCurrentFocusExtState = 0; 201 int[] values = { mCurrentFocusState, mCurrentFocusStreams, 202 mCurrentFocusExtState, 0}; 203 injectValue = VehiclePropValueUtil.createIntVectorValue( 204 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 205 SystemClock.elapsedRealtimeNanos()); 206 } 207 mRejectFocus = false; 208 } 209 } 210 if (injectValue != null) { 211 mHalEmulator.injectEvent(injectValue); 212 } 213 } 214 215 @Override 216 public void onPropertySet(VehiclePropValue value) { 217 VehiclePropValue injectValue = null; 218 synchronized (this) { 219 if (mRejectFocus) { 220 int[] values = { mCurrentFocusState, mCurrentFocusStreams, 221 mCurrentFocusExtState, 0}; 222 injectValue = VehiclePropValueUtil.createIntVectorValue( 223 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 224 SystemClock.elapsedRealtimeNanos()); 225 } else { 226 int request = value.getInt32Values( 227 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_FOCUS); 228 int requestedStreams = value.getInt32Values( 229 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_STREAMS); 230 int requestedExtFocus = value.getInt32Values( 231 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE); 232 int response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 233 switch (request) { 234 case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN: 235 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN; 236 break; 237 case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT: 238 case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK: 239 response = 240 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT; 241 break; 242 case VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE: 243 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 244 break; 245 } 246 mCurrentFocusState = response; 247 mCurrentFocusStreams = requestedStreams; 248 mCurrentFocusExtState = requestedExtFocus; 249 int[] values = { mCurrentFocusState, mCurrentFocusStreams, 250 mCurrentFocusExtState, 0}; 251 injectValue = VehiclePropValueUtil.createIntVectorValue( 252 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 253 SystemClock.elapsedRealtimeNanos()); 254 } 255 } 256 if (injectValue != null) { 257 mHalEmulator.injectEvent(injectValue); 258 } 259 } 260 261 @Override 262 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 263 int[] values = { mCurrentFocusState, mCurrentFocusStreams, 264 mCurrentFocusExtState, 0}; 265 return VehiclePropValueUtil.createIntVectorValue( 266 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 267 SystemClock.elapsedRealtimeNanos()); 268 } 269 270 @Override 271 public void onPropertySubscribe(int property, float sampleRate, int zones) { 272 } 273 274 @Override 275 public void onPropertyUnsubscribe(int property) { 276 } 277 } 278 279 private class AudioStreamStatePropertyHandler implements VehicleHalPropertyHandler { 280 @Override 281 public void onPropertySet(VehiclePropValue value) { 282 } 283 284 @Override 285 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 286 //ignore 287 return null; 288 } 289 290 @Override 291 public void onPropertySubscribe(int property, float sampleRate, int zones) { 292 } 293 294 @Override 295 public void onPropertyUnsubscribe(int property) { 296 } 297 } 298 299 private static class AudioVolumeLimitPropertyHandler implements VehicleHalPropertyHandler { 300 @Override 301 public void onPropertySet(VehiclePropValue value) { 302 } 303 304 @Override 305 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 306 int stream = value.getInt32Values( 307 VehicleNetworkConsts.VehicleAudioVolumeLimitIndex 308 .VEHICLE_AUDIO_VOLUME_LIMIT_INDEX_STREAM); 309 310 int[] values = {stream, 20}; 311 VehiclePropValue propValue = VehiclePropValueUtil.createIntVectorValue( 312 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME_LIMIT, values, 313 SystemClock.elapsedRealtimeNanos()); 314 return propValue; 315 } 316 317 @Override 318 public void onPropertySubscribe(int property, float sampleRate, int zones) { 319 } 320 321 @Override 322 public void onPropertyUnsubscribe(int property) { 323 } 324 } 325 326 private class SingleChannelVolumeHandler implements 327 VehicleHalEmulator.VehicleHalPropertyHandler { 328 private final List<Integer> mMins; 329 private final List<Integer> mMaxs; 330 private final SparseIntArray mCurrent; 331 332 public SingleChannelVolumeHandler(List<Integer> mins, List<Integer> maxs) { 333 mMins = mins; 334 mMaxs = maxs; 335 mCurrent = new SparseIntArray(mMins.size()); 336 // initialize the vol to be the min volume. 337 for (int i = 0; i < mMins.size(); i++) { 338 mCurrent.put(i, mMins.get(i)); 339 } 340 } 341 342 @Override 343 public void onPropertySet(VehiclePropValue value) { 344 int stream = value.getInt32Values( 345 VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STREAM); 346 int volume = value.getInt32Values( 347 VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_VOLUME); 348 int state = value.getInt32Values( 349 VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STATE); 350 351 int[] values = {stream, volume, state}; 352 VehiclePropValue injectValue = VehiclePropValueUtil.createIntVectorValue( 353 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME, values, 354 SystemClock.elapsedRealtimeNanos()); 355 mCurrent.put(stream, volume); 356 mHalEmulator.injectEvent(injectValue); 357 } 358 359 @Override 360 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 361 int stream = value.getInt32Values( 362 VehicleNetworkConsts.VehicleAudioVolumeIndex.VEHICLE_AUDIO_VOLUME_INDEX_STREAM); 363 364 int volume = mCurrent.get(stream); 365 int[] values = {stream, volume, 0}; 366 VehiclePropValue propValue = VehiclePropValueUtil.createIntVectorValue( 367 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME, values, 368 SystemClock.elapsedRealtimeNanos()); 369 return propValue; 370 } 371 372 @Override 373 public void onPropertySubscribe(int property, float sampleRate, int zones) { 374 } 375 376 @Override 377 public void onPropertyUnsubscribe(int property) { 378 } 379 } 380} 381