Add vehicle HAL mocking with carsystem and carsystemtest API
- System API and system test API for testing only added. Client
should link only one of them.
- vehicle HAL mocking allows mocking vehicle HAL completely.
- Once mocking is started, for now, all previous states are forgotton,
so stopping mocking does not return to original state. It is
better to simply restart framework after test.
- Added skeleton code for audio focus handling. Detailed implementaiton
will be added later.
bug: 24874617
Change-Id: I6e60daab3dc96769a94acc09a695f8f49dbb8536
(cherry picked from commit a32e24f50d5895a94d3a13d6ec2233af6e43dac5)
diff --git a/service/src/com/android/car/CarAudioService.java b/service/src/com/android/car/CarAudioService.java
index e730ee8..881b2c5 100644
--- a/service/src/com/android/car/CarAudioService.java
+++ b/service/src/com/android/car/CarAudioService.java
@@ -177,6 +177,7 @@
}
private void doHandleSystemAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
+ //TODO distinguish car service's own focus request from others
if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mFocusInfos[0] = afi;
sendCarAudioFocusRequestIfNecessary();
@@ -229,6 +230,16 @@
}
}
+ /**
+ * Focus listener to take focus away from android apps.
+ */
+ private class AndroidFocusListener implements AudioManager.OnAudioFocusChangeListener {
+ @Override
+ public void onAudioFocusChange(int focusChange) {
+ // nothing to do as system focus listener will get all necessary information.
+ }
+ }
+
private class CarAudioChangeHandler extends Handler {
private static final int MSG_FOCUS_CHANGE = 0;
private static final int MSG_STREAM_STATE_CHANGE = 1;
diff --git a/service/src/com/android/car/CarLog.java b/service/src/com/android/car/CarLog.java
index fe24354..e6ddc9e 100644
--- a/service/src/com/android/car/CarLog.java
+++ b/service/src/com/android/car/CarLog.java
@@ -23,4 +23,5 @@
public static final String TAG_HAL = "CAR.HAL";
public static final String TAG_INFO = "CAR.INFO";
public static final String TAG_AUDIO = "CAR.AUDIO";
+ public static final String TAG_TEST = "CAR.TEST";
}
diff --git a/service/src/com/android/car/CarSensorService.java b/service/src/com/android/car/CarSensorService.java
index e230f25..cffb37e 100644
--- a/service/src/com/android/car/CarSensorService.java
+++ b/service/src/com/android/car/CarSensorService.java
@@ -71,14 +71,6 @@
/** Sensor service is ready and all vehicle sensors are available. */
public abstract void onSensorServiceReady();
-
- /**
- * Provide default sensor value. This value should be always provided after {@link #init()}
- * call. Default value for safety related sensor should be giving safe state.
- * @param sensorType
- * @return
- */
- public abstract CarSensorEvent getDefaultValue(int sensorType);
}
/**
@@ -144,19 +136,20 @@
mSupportedSensors = refreshSupportedSensorsLocked();
if (mUseDefaultDrivingPolicy) {
mDrivingStatePolicy.init();
- addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
- mDrivingStatePolicy.getDefaultValue(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS));
mDrivingStatePolicy.registerSensorListener(this);
}
+ // always populate default value
+ addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
+ DrivingStatePolicy.getDefaultValue(
+ CarSensorManager.SENSOR_TYPE_DRIVING_STATUS));
if (mUseDefaultDayNightModePolicy) {
mDayNightModePolicy.init();
- addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_NIGHT,
- mDrivingStatePolicy.getDefaultValue(
- CarSensorManager.SENSOR_TYPE_NIGHT));
mDayNightModePolicy.registerSensorListener(this);
}
-
+ // always populate default value
+ addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_NIGHT,
+ DayNightModePolicy.getDefaultValue(
+ CarSensorManager.SENSOR_TYPE_NIGHT));
} finally {
mSensorLock.unlock();
}
@@ -171,7 +164,9 @@
@Override
public void release() {
- mHandlerThread.quit();
+ if (mHandlerThread != null) {
+ mHandlerThread.quit();
+ }
tryHoldSensorLock();
try {
if (mUseDefaultDrivingPolicy) {
diff --git a/service/src/com/android/car/CarTestService.java b/service/src/com/android/car/CarTestService.java
new file mode 100644
index 0000000..26a1b7d
--- /dev/null
+++ b/service/src/com/android/car/CarTestService.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.car.hal.VehicleHal;
+import com.android.car.vehiclenetwork.IVehicleNetworkHalMock;
+import com.android.car.vehiclenetwork.VehicleNetwork;
+import com.android.car.vehiclenetwork.VehiclePropValueParcelable;
+
+import java.io.PrintWriter;
+
+/**
+ * Service to allow testing / mocking vehicle HAL.
+ * This service uses Vehicle HAL APIs directly (one exception) as vehicle HAL mocking anyway
+ * requires accessing that level directly.
+ */
+public class CarTestService extends ICarTest.Stub implements CarServiceBase {
+ private static final int VERSION = 1;
+
+ private final Context mContext;
+ private final VehicleNetwork mVehicleNetwork;
+ private final ICarImpl mICarImpl;
+
+ public CarTestService(Context context, ICarImpl carImpl) {
+ mContext = context;
+ mICarImpl = carImpl;
+ mVehicleNetwork = VehicleHal.getInstance().getVehicleNetwork();
+ }
+
+ @Override
+ public void init() {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void release() {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void dump(PrintWriter writer) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
+ @Override
+ public void injectEvent(VehiclePropValueParcelable value) {
+ ICarImpl.assertVehicleHalMockPermission(mContext);
+ mVehicleNetwork.injectEvent(value.value);
+ }
+
+ @Override
+ public void startMocking(IVehicleNetworkHalMock mock) {
+ ICarImpl.assertVehicleHalMockPermission(mContext);
+ mVehicleNetwork.startMocking(mock);
+ VehicleHal.getInstance().startMocking();
+ mICarImpl.startMocking();
+ }
+
+ @Override
+ public void stopMocking(IVehicleNetworkHalMock mock) {
+ ICarImpl.assertVehicleHalMockPermission(mContext);
+ mVehicleNetwork.stopMocking(mock);
+ VehicleHal.getInstance().stopMocking();
+ mICarImpl.stopMocking();
+ }
+}
diff --git a/service/src/com/android/car/DayNightModePolicy.java b/service/src/com/android/car/DayNightModePolicy.java
index 23f36d9..892c077 100644
--- a/service/src/com/android/car/DayNightModePolicy.java
+++ b/service/src/com/android/car/DayNightModePolicy.java
@@ -17,6 +17,7 @@
package com.android.car;
import android.content.Context;
+import android.os.SystemClock;
import android.support.car.Car;
import android.support.car.CarSensorEvent;
import android.support.car.CarSensorManager;
@@ -47,10 +48,8 @@
// TODO Auto-generated method stub
}
- @Override
- public synchronized CarSensorEvent getDefaultValue(int sensorType) {
- // TODO Auto-generated method stub
- return null;
+ public static CarSensorEvent getDefaultValue(int sensorType) {
+ return createEvent(true /* isNight */);
}
@Override
@@ -89,6 +88,13 @@
// TODO Auto-generated method stub
}
+ private static CarSensorEvent createEvent(boolean isNight) {
+ CarSensorEvent event = new CarSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT,
+ SystemClock.elapsedRealtimeNanos(), 0, 1);
+ event.intValues[0] = isNight ? 1 : 0;
+ return event;
+ }
+
@Override
public synchronized void dump(PrintWriter writer) {
// TODO Auto-generated method stub
diff --git a/service/src/com/android/car/DrivingStatePolicy.java b/service/src/com/android/car/DrivingStatePolicy.java
index e1eed18..11fad66 100644
--- a/service/src/com/android/car/DrivingStatePolicy.java
+++ b/service/src/com/android/car/DrivingStatePolicy.java
@@ -91,14 +91,13 @@
// TODO Auto-generated method stub
}
- @Override
- public synchronized CarSensorEvent getDefaultValue(int sensorType) {
+ public static CarSensorEvent getDefaultValue(int sensorType) {
if (sensorType != CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) {
- Log.w(CarLog.TAG_SENSOR, "getCurrentValue to DrivingStatePolicy with sensorType:" +
+ Log.w(CarLog.TAG_SENSOR, "getDefaultValue to DrivingStatePolicy with sensorType:" +
sensorType);
return null;
}
- return createEvent(mDringState);
+ return createEvent(CarSensorEvent.DRIVE_STATUS_FULLY_RESTRICTED);
}
@Override
@@ -202,7 +201,7 @@
return gear == CarSensorEvent.GEAR_PARK;
}
- private CarSensorEvent createEvent(int drivingState) {
+ private static CarSensorEvent createEvent(int drivingState) {
CarSensorEvent event = new CarSensorEvent(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
SystemClock.elapsedRealtimeNanos(), 0, 1);
event.intValues[0] = drivingState;
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index b02bce6..779a48f 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.IBinder;
import android.support.car.Car;
import android.support.car.ICar;
@@ -41,6 +42,9 @@
private final CarSensorService mCarSensorService;
private final CarInfoService mCarInfoService;
private final CarAudioService mCarAudioService;
+ /** Test only service. Populate it only when necessary. */
+ @GuardedBy("this")
+ private CarTestService mCarTestService;
private final CarServiceBase[] mAllServices;
public synchronized static ICarImpl getInstance(Context serviceContext) {
@@ -86,6 +90,23 @@
VehicleHal.releaseInstance();
}
+ public void startMocking() {
+ reinitServices();
+ }
+
+ public void stopMocking() {
+ reinitServices();
+ }
+
+ private void reinitServices() {
+ for (int i = mAllServices.length - 1; i >= 0; i--) {
+ mAllServices[i].release();
+ }
+ for (CarServiceBase service: mAllServices) {
+ service.init();
+ }
+ }
+
@Override
public int getVersion() {
return VERSION;
@@ -98,6 +119,15 @@
return mCarSensorService;
case Car.INFO_SERVICE:
return mCarInfoService;
+ case CarSystemTest.TEST_SERVICE: {
+ assertVehicleHalMockPermission(mContext);
+ synchronized (this) {
+ if (mCarTestService == null) {
+ mCarTestService = new CarTestService(mContext, this);
+ }
+ return mCarTestService;
+ }
+ }
default:
Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
return null;
@@ -130,10 +160,21 @@
return false;
}
+ public static void assertVehicleHalMockPermission(Context context) {
+ if (context.checkCallingOrSelfPermission(CarSystemTest.PERMISSION_MOCK_VEHICLE_HAL)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission");
+ }
+ }
+
void dump(PrintWriter writer) {
writer.println("*Dump all services*");
for (CarServiceBase service: mAllServices) {
service.dump(writer);
}
+ CarTestService testService = mCarTestService;
+ if (testService != null) {
+ testService.dump(writer);
+ }
}
}
diff --git a/service/src/com/android/car/hal/AudioHalService.java b/service/src/com/android/car/hal/AudioHalService.java
index 59fb6c8..e83cfe9 100644
--- a/service/src/com/android/car/hal/AudioHalService.java
+++ b/service/src/com/android/car/hal/AudioHalService.java
@@ -16,8 +16,8 @@
package com.android.car.hal;
import com.android.car.vehiclenetwork.VehicleNetworkConsts;
-import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequestType;
-import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusStateType;
+import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequest;
+import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusState;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioStreamState;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
@@ -29,33 +29,33 @@
public class AudioHalService extends HalServiceBase {
public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN =
- VehicleAudioFocusRequestType.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN;
+ VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN;
public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT =
- VehicleAudioFocusRequestType.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT;
+ VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT;
public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK =
- VehicleAudioFocusRequestType.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK;
+ VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK;
public static final int VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE =
- VehicleAudioFocusRequestType.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE;
+ VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE;
public static String audioFocusRequestToString(int request) {
- return VehicleAudioFocusRequestType.enumToString(request);
+ return VehicleAudioFocusRequest.enumToString(request);
}
public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN =
- VehicleAudioFocusStateType.VEHICLE_AUDIO_FOCUS_STATE_GAIN;
+ VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN;
public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT =
- VehicleAudioFocusStateType.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT;
+ VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT;
public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK =
- VehicleAudioFocusStateType.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK;
+ VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK;
public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT =
- VehicleAudioFocusStateType.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT;
+ VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT;
public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS =
- VehicleAudioFocusStateType.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
+ VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS;
public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE =
- VehicleAudioFocusStateType.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE;
+ VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE;
public static String audioFocusStateToString(int state) {
- return VehicleAudioFocusStateType.enumToString(state);
+ return VehicleAudioFocusState.enumToString(state);
}
public static final int VEHICLE_AUDIO_STREAM_STATE_STOPPED =
@@ -115,10 +115,12 @@
VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS);
mVehicleHal.unsubscribeProperty(this,
VehicleNetworkConsts.VEHICLE_PROPERTY_INTERNAL_AUDIO_STREAM_STATE);
+ mFocusSupported = false;
}
if (mVolumeSupported) {
mVehicleHal.unsubscribeProperty(this,
VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_VOLUME);
+ mVolumeSupported = false;
}
}
diff --git a/service/src/com/android/car/hal/SensorHalService.java b/service/src/com/android/car/hal/SensorHalService.java
index 4fb8398..e7fb8f4 100644
--- a/service/src/com/android/car/hal/SensorHalService.java
+++ b/service/src/com/android/car/hal/SensorHalService.java
@@ -38,7 +38,7 @@
*/
public class SensorHalService extends SensorHalServiceBase {
- private static final boolean DBG_EVENTS = true;
+ private static final boolean DBG_EVENTS = false;
private static final int SENSOR_TYPE_INVALD = -1;
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index d41def1..4652324 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -147,6 +147,19 @@
// keep the looper thread as should be kept for the whole life cycle.
}
+ public void startMocking() {
+ reinitHals();
+ }
+
+ public void stopMocking() {
+ reinitHals();
+ }
+
+ private void reinitHals() {
+ release();
+ doInit();
+ }
+
public SensorHalService getSensorHal() {
return mSensorHal;
}
@@ -159,18 +172,6 @@
return mAudioHal;
}
- /**
- * Start mocking HAL with given mock. Actual H/W will be stop functioning until mocking is
- * stopped. The call will be blocked until all pending events are delivered to upper layer.
- */
- public void startHalMocking(HalMock mock) {
- //TODO
- }
-
- public void stopHalMocking() {
- //TODO
- }
-
private void assertServiceOwner(HalServiceBase service, int property) {
if (service != mPropertyHandlers.get(property)) {
throw new IllegalArgumentException("not owned");