Create CarPropertyService and CarPropertyManager
CarPropertyService replaces Cabin, Hvac, Info, Sensor,
and VendorExtension services.
Bug: 78782959
Bug: 36649684
Bug: 68056035
Test: runtest -x packages/services/Car/tests/android_car_api_test
runtest -x packages/services/Car/tests/carservice_unit_test
Change-Id: I69756654473fe66ef95e9e2cd4f3c1045e3ac938
Merged-In: Ic0a94805f83cc0222fb2bcf9674b6031bc050986
(cherry picked from commit fc0257133967edcb217e07e9ab942690eeaae3de)
(cherry picked from commit 0265d8348716b2971f76e697f410f4cf7128371c)
diff --git a/car-lib/api/current.txt b/car-lib/api/current.txt
index 71eb12c..8bbc15b 100644
--- a/car-lib/api/current.txt
+++ b/car-lib/api/current.txt
@@ -245,20 +245,20 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.car.hardware.CarSensorEvent> CREATOR;
- field public static final int GEAR_DRIVE = 100; // 0x64
- field public static final int GEAR_EIGHTH = 8; // 0x8
- field public static final int GEAR_FIFTH = 5; // 0x5
- field public static final int GEAR_FIRST = 1; // 0x1
- field public static final int GEAR_FOURTH = 4; // 0x4
- field public static final int GEAR_NEUTRAL = 0; // 0x0
- field public static final int GEAR_NINTH = 9; // 0x9
- field public static final int GEAR_PARK = 101; // 0x65
- field public static final int GEAR_REVERSE = 102; // 0x66
- field public static final int GEAR_SECOND = 2; // 0x2
- field public static final int GEAR_SEVENTH = 7; // 0x7
- field public static final int GEAR_SIXTH = 6; // 0x6
- field public static final int GEAR_TENTH = 10; // 0xa
- field public static final int GEAR_THIRD = 3; // 0x3
+ field public static final int GEAR_DRIVE = 8; // 0x8
+ field public static final int GEAR_EIGHTH = 2048; // 0x800
+ field public static final int GEAR_FIFTH = 256; // 0x100
+ field public static final int GEAR_FIRST = 16; // 0x10
+ field public static final int GEAR_FOURTH = 128; // 0x80
+ field public static final int GEAR_NEUTRAL = 1; // 0x1
+ field public static final int GEAR_NINTH = 4096; // 0x1000
+ field public static final int GEAR_PARK = 4; // 0x4
+ field public static final int GEAR_REVERSE = 2; // 0x2
+ field public static final int GEAR_SECOND = 32; // 0x20
+ field public static final int GEAR_SEVENTH = 1024; // 0x400
+ field public static final int GEAR_SIXTH = 512; // 0x200
+ field public static final int GEAR_TENTH = 8192; // 0x2000
+ field public static final int GEAR_THIRD = 64; // 0x40
field public static final int IGNITION_STATE_ACC = 3; // 0x3
field public static final int IGNITION_STATE_LOCK = 1; // 0x1
field public static final int IGNITION_STATE_OFF = 2; // 0x2
@@ -293,28 +293,27 @@
method public boolean registerListener(android.car.hardware.CarSensorManager.OnSensorChangedListener, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
method public void unregisterListener(android.car.hardware.CarSensorManager.OnSensorChangedListener);
method public void unregisterListener(android.car.hardware.CarSensorManager.OnSensorChangedListener, int);
- field public static final int SENSOR_RATE_FAST = 1; // 0x1
- field public static final int SENSOR_RATE_FASTEST = 0; // 0x0
- field public static final int SENSOR_RATE_NORMAL = 3; // 0x3
- field public static final int SENSOR_RATE_UI = 2; // 0x2
- field public static final int SENSOR_TYPE_ABS_ACTIVE = 24; // 0x18
- field public static final int SENSOR_TYPE_CAR_SPEED = 2; // 0x2
+ field public static final int SENSOR_RATE_FAST = 10; // 0xa
+ field public static final int SENSOR_RATE_FASTEST = 100; // 0x64
+ field public static final int SENSOR_RATE_NORMAL = 1; // 0x1
+ field public static final int SENSOR_RATE_UI = 5; // 0x5
+ field public static final int SENSOR_TYPE_ABS_ACTIVE = 287310858; // 0x1120040a
+ field public static final int SENSOR_TYPE_CAR_SPEED = 291504647; // 0x11600207
field public static final int SENSOR_TYPE_ENVIRONMENT = 12; // 0xc
- field public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 31; // 0x1f
- field public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 28; // 0x1c
- field public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 30; // 0x1e
- field public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 29; // 0x1d
- field public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 27; // 0x1b
- field public static final int SENSOR_TYPE_FUEL_LEVEL = 5; // 0x5
- field public static final int SENSOR_TYPE_GEAR = 7; // 0x7
- field public static final int SENSOR_TYPE_IGNITION_STATE = 22; // 0x16
- field public static final int SENSOR_TYPE_NIGHT = 9; // 0x9
- field public static final int SENSOR_TYPE_ODOMETER = 4; // 0x4
- field public static final int SENSOR_TYPE_PARKING_BRAKE = 6; // 0x6
- field public static final int SENSOR_TYPE_RPM = 3; // 0x3
- field public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25; // 0x19
- field public static final int SENSOR_TYPE_VENDOR_EXTENSION_END = 1879048191; // 0x6fffffff
- field public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 23; // 0x17
+ field public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 291504908; // 0x1160030c
+ field public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 291504905; // 0x11600309
+ field public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 287310603; // 0x1120030b
+ field public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 287310602; // 0x1120030a
+ field public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 287310600; // 0x11200308
+ field public static final int SENSOR_TYPE_FUEL_LEVEL = 291504903; // 0x11600307
+ field public static final int SENSOR_TYPE_GEAR = 289408000; // 0x11400400
+ field public static final int SENSOR_TYPE_IGNITION_STATE = 289408009; // 0x11400409
+ field public static final int SENSOR_TYPE_NIGHT = 287310855; // 0x11200407
+ field public static final int SENSOR_TYPE_ODOMETER = 291504644; // 0x11600204
+ field public static final int SENSOR_TYPE_PARKING_BRAKE = 287310850; // 0x11200402
+ field public static final int SENSOR_TYPE_RPM = 291504901; // 0x11600305
+ field public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 287310859; // 0x1120040b
+ field public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 290521862; // 0x11510306
}
public static abstract interface CarSensorManager.OnSensorChangedListener {
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index e18e573..38cddf7 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -32,6 +32,7 @@
field public static final java.lang.String PERMISSION_VMS_SUBSCRIBER = "android.car.permission.VMS_SUBSCRIBER";
field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String PROJECTION_SERVICE = "projection";
+ field public static final java.lang.String PROPERTY_SERVICE = "property";
field public static final java.lang.String STORAGE_MONITORING_SERVICE = "storage_monitoring";
field public static final java.lang.String TEST_SERVICE = "car-service-test";
field public static final java.lang.String VENDOR_EXTENSION_SERVICE = "vendor_extension";
@@ -559,7 +560,7 @@
method public void registerCallback(android.car.hardware.CarVendorExtensionManager.CarVendorExtensionCallback) throws android.car.CarNotConnectedException;
method public <E> void setGlobalProperty(java.lang.Class<E>, int, E) throws android.car.CarNotConnectedException;
method public <E> void setProperty(java.lang.Class<E>, int, int, E) throws android.car.CarNotConnectedException;
- method public void unregisterCallback(android.car.hardware.CarVendorExtensionManager.CarVendorExtensionCallback);
+ method public void unregisterCallback(android.car.hardware.CarVendorExtensionManager.CarVendorExtensionCallback) throws android.car.CarNotConnectedException;
}
public static abstract interface CarVendorExtensionManager.CarVendorExtensionCallback {
@@ -581,46 +582,46 @@
method public void setBooleanProperty(int, int, boolean) throws android.car.CarNotConnectedException;
method public void setFloatProperty(int, int, float) throws android.car.CarNotConnectedException;
method public void setIntProperty(int, int, int) throws android.car.CarNotConnectedException;
- method public synchronized void unregisterCallback(android.car.hardware.cabin.CarCabinManager.CarCabinEventCallback);
- field public static final int ID_DOOR_LOCK = 3; // 0x3
- field public static final int ID_DOOR_MOVE = 2; // 0x2
- field public static final int ID_DOOR_POS = 1; // 0x1
- field public static final int ID_MIRROR_FOLD = 4102; // 0x1006
- field public static final int ID_MIRROR_LOCK = 4101; // 0x1005
- field public static final int ID_MIRROR_Y_MOVE = 4100; // 0x1004
- field public static final int ID_MIRROR_Y_POS = 4099; // 0x1003
- field public static final int ID_MIRROR_Z_MOVE = 4098; // 0x1002
- field public static final int ID_MIRROR_Z_POS = 4097; // 0x1001
- field public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 8201; // 0x2009
- field public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 8200; // 0x2008
- field public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 8203; // 0x200b
- field public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 8202; // 0x200a
- field public static final int ID_SEAT_BELT_BUCKLED = 8195; // 0x2003
- field public static final int ID_SEAT_BELT_HEIGHT_MOVE = 8197; // 0x2005
- field public static final int ID_SEAT_BELT_HEIGHT_POS = 8196; // 0x2004
- field public static final int ID_SEAT_DEPTH_MOVE = 8207; // 0x200f
- field public static final int ID_SEAT_DEPTH_POS = 8206; // 0x200e
- field public static final int ID_SEAT_FORE_AFT_MOVE = 8199; // 0x2007
- field public static final int ID_SEAT_FORE_AFT_POS = 8198; // 0x2006
- field public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 8217; // 0x2019
- field public static final int ID_SEAT_HEADREST_ANGLE_POS = 8216; // 0x2018
- field public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 8219; // 0x201b
- field public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 8218; // 0x201a
- field public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 8215; // 0x2017
- field public static final int ID_SEAT_HEADREST_HEIGHT_POS = 8214; // 0x2016
- field public static final int ID_SEAT_HEIGHT_MOVE = 8205; // 0x200d
- field public static final int ID_SEAT_HEIGHT_POS = 8204; // 0x200c
- field public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 8211; // 0x2013
- field public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 8210; // 0x2012
- field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 8213; // 0x2015
- field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 8212; // 0x2014
- field public static final int ID_SEAT_MEMORY_SELECT = 8193; // 0x2001
- field public static final int ID_SEAT_MEMORY_SET = 8194; // 0x2002
- field public static final int ID_SEAT_TILT_MOVE = 8209; // 0x2011
- field public static final int ID_SEAT_TILT_POS = 8208; // 0x2010
- field public static final int ID_WINDOW_LOCK = 12291; // 0x3003
- field public static final int ID_WINDOW_MOVE = 12290; // 0x3002
- field public static final int ID_WINDOW_POS = 12289; // 0x3001
+ method public synchronized void unregisterCallback(android.car.hardware.cabin.CarCabinManager.CarCabinEventCallback) throws android.car.CarNotConnectedException;
+ field public static final int ID_DOOR_LOCK = 371198722; // 0x16200b02
+ field public static final int ID_DOOR_MOVE = 373295873; // 0x16400b01
+ field public static final int ID_DOOR_POS = 373295872; // 0x16400b00
+ field public static final int ID_MIRROR_FOLD = 287312709; // 0x11200b45
+ field public static final int ID_MIRROR_LOCK = 287312708; // 0x11200b44
+ field public static final int ID_MIRROR_Y_MOVE = 339741507; // 0x14400b43
+ field public static final int ID_MIRROR_Y_POS = 339741506; // 0x14400b42
+ field public static final int ID_MIRROR_Z_MOVE = 339741505; // 0x14400b41
+ field public static final int ID_MIRROR_Z_POS = 339741504; // 0x14400b40
+ field public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 356518792; // 0x15400b88
+ field public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 356518791; // 0x15400b87
+ field public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 356518794; // 0x15400b8a
+ field public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 356518793; // 0x15400b89
+ field public static final int ID_SEAT_BELT_BUCKLED = 354421634; // 0x15200b82
+ field public static final int ID_SEAT_BELT_HEIGHT_MOVE = 356518788; // 0x15400b84
+ field public static final int ID_SEAT_BELT_HEIGHT_POS = 356518787; // 0x15400b83
+ field public static final int ID_SEAT_DEPTH_MOVE = 356518798; // 0x15400b8e
+ field public static final int ID_SEAT_DEPTH_POS = 356518797; // 0x15400b8d
+ field public static final int ID_SEAT_FORE_AFT_MOVE = 356518790; // 0x15400b86
+ field public static final int ID_SEAT_FORE_AFT_POS = 356518789; // 0x15400b85
+ field public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 356518808; // 0x15400b98
+ field public static final int ID_SEAT_HEADREST_ANGLE_POS = 356518807; // 0x15400b97
+ field public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 356518810; // 0x15400b9a
+ field public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 356518809; // 0x15400b99
+ field public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 356518806; // 0x15400b96
+ field public static final int ID_SEAT_HEADREST_HEIGHT_POS = 356518805; // 0x15400b95
+ field public static final int ID_SEAT_HEIGHT_MOVE = 356518796; // 0x15400b8c
+ field public static final int ID_SEAT_HEIGHT_POS = 356518795; // 0x15400b8b
+ field public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 356518802; // 0x15400b92
+ field public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 356518801; // 0x15400b91
+ field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 356518804; // 0x15400b94
+ field public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 356518803; // 0x15400b93
+ field public static final int ID_SEAT_MEMORY_SELECT = 356518784; // 0x15400b80
+ field public static final int ID_SEAT_MEMORY_SET = 356518785; // 0x15400b81
+ field public static final int ID_SEAT_TILT_MOVE = 356518800; // 0x15400b90
+ field public static final int ID_SEAT_TILT_POS = 356518799; // 0x15400b8f
+ field public static final int ID_WINDOW_LOCK = 322964420; // 0x13400bc4
+ field public static final int ID_WINDOW_MOVE = 322964417; // 0x13400bc1
+ field public static final int ID_WINDOW_POS = 322964416; // 0x13400bc0
}
public static abstract interface CarCabinManager.CarCabinEventCallback {
@@ -638,7 +639,6 @@
method public int getIntProperty(int, int) throws android.car.CarNotConnectedException;
method public java.util.List<android.car.hardware.CarPropertyConfig> getPropertyList() throws android.car.CarNotConnectedException;
method public boolean isPropertyAvailable(int, int) throws android.car.CarNotConnectedException;
- method public static boolean isZonedProperty(int);
method public synchronized void registerCallback(android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback) throws android.car.CarNotConnectedException;
method public void setBooleanProperty(int, int, boolean) throws android.car.CarNotConnectedException;
method public void setFloatProperty(int, int, float) throws android.car.CarNotConnectedException;
@@ -647,26 +647,26 @@
field public static final int FAN_DIRECTION_DEFROST = 4; // 0x4
field public static final int FAN_DIRECTION_FACE = 1; // 0x1
field public static final int FAN_DIRECTION_FLOOR = 2; // 0x2
- field public static final int ID_MIRROR_DEFROSTER_ON = 1; // 0x1
- field public static final int ID_OUTSIDE_AIR_TEMP = 3; // 0x3
- field public static final int ID_STEERING_WHEEL_HEAT = 2; // 0x2
- field public static final int ID_TEMPERATURE_DISPLAY_UNITS = 4; // 0x4
- field public static final int ID_WINDOW_DEFROSTER_ON = 20481; // 0x5001
- field public static final int ID_ZONED_AC_ON = 16393; // 0x4009
- field public static final int ID_ZONED_AIR_RECIRCULATION_ON = 16395; // 0x400b
- field public static final int ID_ZONED_AUTOMATIC_MODE_ON = 16394; // 0x400a
- field public static final int ID_ZONED_DUAL_ZONE_ON = 16397; // 0x400d
- field public static final int ID_ZONED_FAN_DIRECTION = 16391; // 0x4007
- field public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 16390; // 0x4006
- field public static final int ID_ZONED_FAN_SPEED_RPM = 16389; // 0x4005
- field public static final int ID_ZONED_FAN_SPEED_SETPOINT = 16388; // 0x4004
- field public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 16399; // 0x400f
- field public static final int ID_ZONED_HVAC_POWER_ON = 16387; // 0x4003
- field public static final int ID_ZONED_MAX_AC_ON = 16396; // 0x400c
- field public static final int ID_ZONED_MAX_DEFROST_ON = 16398; // 0x400e
- field public static final int ID_ZONED_SEAT_TEMP = 16392; // 0x4008
- field public static final int ID_ZONED_TEMP_ACTUAL = 16386; // 0x4002
- field public static final int ID_ZONED_TEMP_SETPOINT = 16385; // 0x4001
+ field public static final int ID_MIRROR_DEFROSTER_ON = 339739916; // 0x1440050c
+ field public static final int ID_OUTSIDE_AIR_TEMP = 291505923; // 0x11600703
+ field public static final int ID_STEERING_WHEEL_HEAT = 289408269; // 0x1140050d
+ field public static final int ID_TEMPERATURE_DISPLAY_UNITS = 289408270; // 0x1140050e
+ field public static final int ID_WINDOW_DEFROSTER_ON = 320865540; // 0x13200504
+ field public static final int ID_ZONED_AC_ON = 354419973; // 0x15200505
+ field public static final int ID_ZONED_AIR_RECIRCULATION_ON = 354419976; // 0x15200508
+ field public static final int ID_ZONED_AUTOMATIC_MODE_ON = 354419978; // 0x1520050a
+ field public static final int ID_ZONED_DUAL_ZONE_ON = 354419977; // 0x15200509
+ field public static final int ID_ZONED_FAN_DIRECTION = 356517121; // 0x15400501
+ field public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 356582673; // 0x15410511
+ field public static final int ID_ZONED_FAN_SPEED_RPM = 356517135; // 0x1540050f
+ field public static final int ID_ZONED_FAN_SPEED_SETPOINT = 356517120; // 0x15400500
+ field public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 354419986; // 0x15200512
+ field public static final int ID_ZONED_HVAC_POWER_ON = 354419984; // 0x15200510
+ field public static final int ID_ZONED_MAX_AC_ON = 354419974; // 0x15200506
+ field public static final int ID_ZONED_MAX_DEFROST_ON = 354419975; // 0x15200507
+ field public static final int ID_ZONED_SEAT_TEMP = 356517131; // 0x1540050b
+ field public static final int ID_ZONED_TEMP_ACTUAL = 358614274; // 0x15600502
+ field public static final int ID_ZONED_TEMP_SETPOINT = 358614275; // 0x15600503
}
public static abstract interface CarHvacManager.CarHvacEventCallback {
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index 5d16640..738a423 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -29,6 +29,7 @@
import android.car.hardware.cabin.CarCabinManager;
import android.car.hardware.hvac.CarHvacManager;
import android.car.hardware.power.CarPowerManager;
+import android.car.hardware.property.CarPropertyManager;
import android.car.media.CarAudioManager;
import android.car.navigation.CarNavigationStatusManager;
import android.car.settings.CarConfigurationManager;
@@ -126,6 +127,12 @@
* @hide
*/
@SystemApi
+ public static final String PROPERTY_SERVICE = "property";
+
+ /**
+ * @hide
+ */
+ @SystemApi
public static final String VENDOR_EXTENSION_SERVICE = "vendor_extension";
/**
@@ -766,6 +773,10 @@
case PROJECTION_SERVICE:
manager = new CarProjectionManager(binder, mEventHandler);
break;
+ case PROPERTY_SERVICE:
+ manager = new CarPropertyManager(binder, mEventHandler, false,
+ "CarPropertyManager");
+ break;
case VENDOR_EXTENSION_SERVICE:
manager = new CarVendorExtensionManager(binder, mEventHandler);
break;
diff --git a/car-lib/src/android/car/CarInfoManager.java b/car-lib/src/android/car/CarInfoManager.java
index 47d90c9..b228ca7 100644
--- a/car-lib/src/android/car/CarInfoManager.java
+++ b/car-lib/src/android/car/CarInfoManager.java
@@ -16,45 +16,46 @@
package android.car;
+import static java.lang.Integer.toHexString;
+
import android.annotation.Nullable;
-import android.car.EvConnectorType;
-import android.car.FuelType;
-import android.car.annotation.FutureFeature;
import android.car.annotation.ValueTypeDef;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.ICarProperty;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-
-
-import com.android.internal.annotations.GuardedBy;
+import android.util.Log;
/**
* Utility to retrieve various static information from car. Each data are grouped as {@link Bundle}
* and relevant data can be checked from {@link Bundle} using pre-specified keys.
*/
-public final class CarInfoManager implements CarManagerBase {
+public final class CarInfoManager implements CarManagerBase{
+ private static final boolean DBG = false;
+ private static final String TAG = "CarInfoManager";
/**
* Key for manufacturer of the car. Passed in basic info Bundle.
* @hide
*/
- @ValueTypeDef(type = String.class)
- public static final String BASIC_INFO_KEY_MANUFACTURER = "android.car.manufacturer";
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_KEY_MANUFACTURER = 0x11100101;
/**
* Key for model name of the car. This information may not necessarily allow distinguishing
* different car models as the same name may be used for different cars depending on
* manufacturers. Passed in basic info Bundle.
* @hide
*/
- @ValueTypeDef(type = String.class)
- public static final String BASIC_INFO_KEY_MODEL = "android.car.model";
+ @ValueTypeDef(type = Integer.class)
+ public static final int BASIC_INFO_KEY_MODEL = 0x11100102;
/**
* Key for model year of the car in AC. Passed in basic info Bundle.
* @hide
*/
@ValueTypeDef(type = Integer.class)
- public static final String BASIC_INFO_KEY_MODEL_YEAR = "android.car.model-year";
+ public static final int BASIC_INFO_KEY_MODEL_YEAR = 0x11400103;
/**
* Key for unique identifier for the car. This is not VIN, and id is persistent until user
* resets it. Passed in basic info Bundle.
@@ -92,38 +93,38 @@
* @hide
*/
@ValueTypeDef(type = Integer.class)
- public static final String BASIC_INFO_FUEL_CAPACITY = "android.car.fuel-capacity";
+ public static final int BASIC_INFO_FUEL_CAPACITY = 0x11600104;
/**
* Key for Fuel Types. This is an array of fuel types the vehicle supports.
* Passed in basic info Bundle.
* @hide
*/
@ValueTypeDef(type = Integer.class)
- public static final String BASIC_INFO_FUEL_TYPES = "android.car.fuel-types";
+ public static final int BASIC_INFO_FUEL_TYPES = 0x11410105;
/**
* Key for EV Battery Capacity in WH. Passed in basic info Bundle.
* @hide
*/
@ValueTypeDef(type = Integer.class)
- public static final String BASIC_INFO_EV_BATTERY_CAPACITY = "android.car.ev-battery-capacity";
+ public static final int BASIC_INFO_EV_BATTERY_CAPACITY = 0x11600106;
/**
* Key for EV Connector Types. This is an array of connector types the vehicle supports.
* Passed in basic info Bundle.
* @hide
*/
@ValueTypeDef(type = Integer.class)
- public static final String BASIC_INFO_EV_CONNECTOR_TYPES = "android.car.ev-connector-types";
+ public static final int BASIC_INFO_EV_CONNECTOR_TYPES = 0x11410107;
- private final ICarInfo mService;
-
- @GuardedBy("this")
- private Bundle mBasicInfo;
+ private final ICarProperty mService;
/**
* @return Manufacturer of the car. Null if not available.
*/
- public @android.annotation.Nullable String getManufacturer() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_MANUFACTURER);
+ @Nullable
+ public String getManufacturer() throws CarNotConnectedException {
+ CarPropertyValue<String> carProp = getProperty(String.class,
+ BASIC_INFO_KEY_MANUFACTURER, 0);
+ return carProp != null ? carProp.getValue() : null;
}
/**
@@ -131,24 +132,30 @@
* may not necessarily allow distinguishing different car models as the same
* name may be used for different cars depending on manufacturers.
*/
- public @Nullable String getModel() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_MODEL);
+ @Nullable
+ public String getModel() throws CarNotConnectedException {
+ CarPropertyValue<String> carProp = getProperty(String.class, BASIC_INFO_KEY_MODEL, 0);
+ return carProp != null ? carProp.getValue() : null;
}
/**
* @return Model year of the car in AC. Null if not available.
*/
- public @Nullable String getModelYear() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_MODEL_YEAR);
+ @Nullable
+ public String getModelYear() throws CarNotConnectedException {
+ CarPropertyValue<String> carProp = getProperty(String.class,
+ BASIC_INFO_KEY_MODEL_YEAR, 0);
+ return carProp != null ? carProp.getValue() : null;
}
/**
* @return Unique identifier for the car. This is not VIN, and vehicle id is
* persistent until user resets it. This ID is guaranteed to be always
* available.
+ * TODO: BASIC_INFO_KEY_VEHICLE_ID property?
*/
public String getVehicleId() throws CarNotConnectedException {
- return getBasicInfo().getString(BASIC_INFO_KEY_VEHICLE_ID);
+ return "";
}
/**
@@ -156,7 +163,9 @@
* fuel.
*/
public float getFuelCapacity() throws CarNotConnectedException {
- return getBasicInfo().getFloat(BASIC_INFO_FUEL_CAPACITY);
+ CarPropertyValue<Float> carProp = getProperty(Float.class,
+ BASIC_INFO_FUEL_CAPACITY, 0);
+ return carProp != null ? carProp.getValue() : 0f;
}
/**
@@ -164,7 +173,8 @@
* types available.
*/
public @FuelType.Enum int[] getFuelTypes() throws CarNotConnectedException {
- return getIntArray(BASIC_INFO_FUEL_TYPES);
+ CarPropertyValue<int[]> carProp = getProperty(int[].class, BASIC_INFO_FUEL_TYPES, 0);
+ return carProp != null ? carProp.getValue() : new int[0];
}
/**
@@ -172,7 +182,9 @@
* battery.
*/
public float getEvBatteryCapacity() throws CarNotConnectedException {
- return getBasicInfo().getFloat(BASIC_INFO_EV_BATTERY_CAPACITY);
+ CarPropertyValue<Float> carProp = getProperty(Float.class,
+ BASIC_INFO_EV_BATTERY_CAPACITY, 0);
+ return carProp != null ? carProp.getValue() : 0f;
}
/**
@@ -180,77 +192,42 @@
* no connector types available.
*/
public @EvConnectorType.Enum int[] getEvConnectorTypes() throws CarNotConnectedException {
- return getIntArray(BASIC_INFO_EV_CONNECTOR_TYPES);
- }
-
- /**
- * Get product configuration string. Contents of this string is product specific but it should
- * be composed of key-value pairs with the format of:
- * key1=value1;key2=value2;...
- * @return null if such information is not available in this car.
- * @throws CarNotConnectedException
- * @hide
- */
- @FutureFeature
- public @Nullable String getProductConfiguration() throws CarNotConnectedException {
- try {
- return mService.getStringInfo(INFO_KEY_PRODUCT_CONFIGURATION);
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
- }
- return null;
- }
-
- /**
- * Get {@link android.os.Bundle} containing basic car information. Check
- * {@link #BASIC_INFO_KEY_MANUFACTURER}, {@link #BASIC_INFO_KEY_MODEL},
- * {@link #BASIC_INFO_KEY_MODEL_YEAR}, and {@link #BASIC_INFO_KEY_VEHICLE_ID} for supported
- * keys in the {@link android.os.Bundle}.
- * @return {@link android.os.Bundle} containing basic car info.
- * @throws CarNotConnectedException
- */
- private synchronized Bundle getBasicInfo() throws CarNotConnectedException {
- if (mBasicInfo != null) {
- return mBasicInfo;
- }
- try {
- mBasicInfo = mService.getBasicInfo();
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
- }
- return mBasicInfo;
- }
-
- /**
- * Get int array from property ID.
- * @param id property ID to get
- * @return array of property values or empty array if the property isn't
- * available.
- * @throws CarNotConnectedException
- */
- private int[] getIntArray(String id) throws CarNotConnectedException {
- int[] retVal = getBasicInfo().getIntArray(id);
- if (retVal == null) {
- // Create an empty array
- retVal = new int[0];
- }
- return retVal;
+ CarPropertyValue<int[]> carProp = getProperty(int[].class,
+ BASIC_INFO_EV_CONNECTOR_TYPES, 0);
+ return carProp != null ? carProp.getValue() : new int[0];
}
/** @hide */
CarInfoManager(IBinder service) {
- mService = ICarInfo.Stub.asInterface(service);
+ mService = ICarProperty.Stub.asInterface(service);
}
/** @hide */
- @Override
public void onCarDisconnected() {
- synchronized (this) {
- mBasicInfo = null;
+ }
+
+ private <E> CarPropertyValue<E> getProperty(Class<E> clazz, int propId, int area)
+ throws CarNotConnectedException {
+ if (DBG) {
+ Log.d(TAG, "getProperty, propId: 0x" + toHexString(propId)
+ + ", area: 0x" + toHexString(area) + ", class: " + clazz);
+ }
+ try {
+ CarPropertyValue<E> propVal = mService.getProperty(propId, area);
+ if (propVal != null && propVal.getValue() != null) {
+ Class<?> actualClass = propVal.getValue().getClass();
+ if (actualClass != clazz) {
+ throw new IllegalArgumentException("Invalid property type. " + "Expected: "
+ + clazz + ", but was: " + actualClass);
+ }
+ }
+ return propVal;
+ } catch (RemoteException e) {
+ Log.e(TAG, "getProperty failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalArgumentException e) {
+ return null;
}
}
}
diff --git a/car-lib/src/android/car/hardware/CarSensorEvent.java b/car-lib/src/android/car/hardware/CarSensorEvent.java
index abf2b2a..86af063 100644
--- a/car-lib/src/android/car/hardware/CarSensorEvent.java
+++ b/car-lib/src/android/car/hardware/CarSensorEvent.java
@@ -37,39 +37,39 @@
* sensor type.
* GEAR_NEUTRAL means transmission gear is in neutral state, and the car may be moving.
*/
- public static final int GEAR_NEUTRAL = 0;
+ public static final int GEAR_NEUTRAL = 0x0001;
/**
* intValues[0] from 1 to 99 represents transmission gear number for moving forward.
* GEAR_FIRST is for gear number 1.
*/
- public static final int GEAR_FIRST = 1;
+ public static final int GEAR_FIRST = 0x0010;
/** Gear number 2. */
- public static final int GEAR_SECOND = 2;
+ public static final int GEAR_SECOND = 0x0020;
/** Gear number 3. */
- public static final int GEAR_THIRD = 3;
+ public static final int GEAR_THIRD = 0x0040;
/** Gear number 4. */
- public static final int GEAR_FOURTH = 4;
+ public static final int GEAR_FOURTH = 0x0080;
/** Gear number 5. */
- public static final int GEAR_FIFTH = 5;
+ public static final int GEAR_FIFTH = 0x0100;
/** Gear number 6. */
- public static final int GEAR_SIXTH = 6;
+ public static final int GEAR_SIXTH = 0x0200;
/** Gear number 7. */
- public static final int GEAR_SEVENTH = 7;
+ public static final int GEAR_SEVENTH = 0x0400;
/** Gear number 8. */
- public static final int GEAR_EIGHTH = 8;
+ public static final int GEAR_EIGHTH = 0x0800;
/** Gear number 9. */
- public static final int GEAR_NINTH = 9;
+ public static final int GEAR_NINTH = 0x1000;
/** Gear number 10. */
- public static final int GEAR_TENTH = 10;
+ public static final int GEAR_TENTH = 0x2000;
/**
* This is for transmission without specific gear number for moving forward like CVT. It tells
* that car is in a transmission state to move it forward.
*/
- public static final int GEAR_DRIVE = 100;
+ public static final int GEAR_DRIVE = 0x0008;
/** Gear in parking state */
- public static final int GEAR_PARK = 101;
+ public static final int GEAR_PARK = 0x0004;
/** Gear in reverse */
- public static final int GEAR_REVERSE = 102;
+ public static final int GEAR_REVERSE = 0x0002;
/**
* Ignition state is unknown.
diff --git a/car-lib/src/android/car/hardware/CarSensorManager.java b/car-lib/src/android/car/hardware/CarSensorManager.java
index dd05bc8..fc97c9d 100644
--- a/car-lib/src/android/car/hardware/CarSensorManager.java
+++ b/car-lib/src/android/car/hardware/CarSensorManager.java
@@ -24,28 +24,30 @@
import android.car.CarLibLog;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
+import android.car.hardware.property.CarPropertyManager;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArraySet;
import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.car.internal.CarRatedListeners;
-import com.android.car.internal.SingleMessageHandler;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
-import java.util.function.Consumer;
+
/**
* API for monitoring car sensor data.
*/
public final class CarSensorManager implements CarManagerBase {
+ private static final boolean DBG = false;
+ private static final String TAG = "CarSensorManager";
+ private final CarPropertyManager mCarPropertyMgr;
/** @hide */
public static final int SENSOR_TYPE_RESERVED1 = 1;
/**
@@ -53,41 +55,41 @@
* Sensor data in {@link CarSensorEvent} is a float which will be >= 0.
* This requires {@link Car#PERMISSION_SPEED} permission.
*/
- public static final int SENSOR_TYPE_CAR_SPEED = 2;
+ public static final int SENSOR_TYPE_CAR_SPEED = 0x11600207;
/**
* Represents engine RPM of the car. Sensor data in {@link CarSensorEvent} is a float.
*/
- public static final int SENSOR_TYPE_RPM = 3;
+ public static final int SENSOR_TYPE_RPM = 0x11600305;
/**
* Total travel distance of the car in Kilometer. Sensor data is a float.
* This requires {@link Car#PERMISSION_MILEAGE} permission.
*/
- public static final int SENSOR_TYPE_ODOMETER = 4;
+ public static final int SENSOR_TYPE_ODOMETER = 0x11600204;
/**
* Indicates fuel level of the car.
* In {@link CarSensorEvent}, represents fuel level in milliliters.
* This requires {@link Car#PERMISSION_ENERGY} permission.
*/
- public static final int SENSOR_TYPE_FUEL_LEVEL = 5;
+ public static final int SENSOR_TYPE_FUEL_LEVEL = 0x11600307;
/**
* Represents the current status of parking brake. Sensor data in {@link CarSensorEvent} is an
* intValues[0]. Value of 1 represents parking brake applied while 0 means the other way
* around. For this sensor, rate in {@link #registerListener(OnSensorChangedListener, int, int)}
* will be ignored and all changes will be notified.
*/
- public static final int SENSOR_TYPE_PARKING_BRAKE = 6;
+ public static final int SENSOR_TYPE_PARKING_BRAKE = 0x11200402;
/**
* This represents the current position of transmission gear. Sensor data in
* {@link CarSensorEvent} is an intValues[0]. For the meaning of the value, check
* {@link CarSensorEvent#GEAR_NEUTRAL} and other GEAR_*.
*/
- public static final int SENSOR_TYPE_GEAR = 7;
+ public static final int SENSOR_TYPE_GEAR = 0x11400400;
/** @hide */
public static final int SENSOR_TYPE_RESERVED8 = 8;
/**
* Day/night sensor. Sensor data is intValues[0].
*/
- public static final int SENSOR_TYPE_NIGHT = 9;
+ public static final int SENSOR_TYPE_NIGHT = 0x11200407;
/** @hide */
public static final int SENSOR_TYPE_RESERVED10 = 10;
/** @hide */
@@ -118,7 +120,7 @@
* Represents ignition state. The value should be one of the constants that starts with
* IGNITION_STATE_* in {@link CarSensorEvent}.
*/
- public static final int SENSOR_TYPE_IGNITION_STATE = 22;
+ public static final int SENSOR_TYPE_IGNITION_STATE = 0x11400409;
/**
* Represents wheel distance in millimeters. Some cars may not have individual sensors on each
* wheel. If a value is not available, Long.MAX_VALUE will be reported. The wheel distance
@@ -126,23 +128,23 @@
* distance shall be reset to zero each time a vehicle is started by the user.
* This requires {@link Car#PERMISSION_SPEED} permission.
*/
- public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 23;
+ public static final int SENSOR_TYPE_WHEEL_TICK_DISTANCE = 0x11510306;
/**
* Set to true when ABS is active. This sensor is event driven.
* This requires {@link Car#PERMISSION_CAR_DYNAMICS_STATE} permission.
*/
- public static final int SENSOR_TYPE_ABS_ACTIVE = 24;
+ public static final int SENSOR_TYPE_ABS_ACTIVE = 0x1120040a;
/**
* Set to true when traction control is active. This sensor is event driven.
* This requires {@link Car#PERMISSION_CAR_DYNAMICS_STATE} permission.
*/
- public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 25;
+ public static final int SENSOR_TYPE_TRACTION_CONTROL_ACTIVE = 0x1120040b;
/** @hide */
public static final int SENSOR_TYPE_RESERVED26 = 26;
/**
* Set to true if the fuel door is open.
*/
- public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 27;
+ public static final int SENSOR_TYPE_FUEL_DOOR_OPEN = 0x11200308;
/**
* Indicates battery level of the car.
@@ -152,129 +154,156 @@
* of the vehicle.
* This requires {@link Car#PERMISSION_ENERGY} permission.
*/
- public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 28;
+ public static final int SENSOR_TYPE_EV_BATTERY_LEVEL = 0x11600309;
/**
* Set to true if EV charging port is open.
*/
- public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 29;
+ public static final int SENSOR_TYPE_EV_CHARGE_PORT_OPEN = 0x1120030a;
/**
* Set to true if EV charging port is connected.
*/
- public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 30;
+ public static final int SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED = 0x1120030b;
/**
* Indicates the instantaneous battery charging rate in mW.
* This requires {@link Car#PERMISSION_ENERGY} permission.
*/
- public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 31;
+ public static final int SENSOR_TYPE_EV_BATTERY_CHARGE_RATE = 0x1160030c;
/**
* Oil level sensor.
* This requires {@link Car#PERMISSION_CAR_ENGINE_DETAILED} permission
* @hide
*/
- public static final int SENSOR_TYPE_ENGINE_OIL_LEVEL = 32;
+ public static final int SENSOR_TYPE_ENGINE_OIL_LEVEL = 0x11400303;
- /**
- * Sensor type bigger than this is invalid. Always update this after adding a new sensor.
- * @hide
- */
- private static final int SENSOR_TYPE_MAX = SENSOR_TYPE_ENGINE_OIL_LEVEL;
-
- /**
- * Sensors defined in this range [{@link #SENSOR_TYPE_VENDOR_EXTENSION_START},
- * {@link #SENSOR_TYPE_VENDOR_EXTENSION_END}] is for each car vendor's to use.
- * This should be only used for system app to access sensors not defined as standard types.
- * So the sensor supported in this range can vary depending on car models / manufacturers.
- * 3rd party apps should not use sensors in this range as they are not compatible across
- * different cars. Additionally 3rd party apps trying to access sensor in this range will get
- * security exception as their access is restricted to system apps.
- *
- * @hide
- */
- public static final int SENSOR_TYPE_VENDOR_EXTENSION_START = 0x60000000;
- public static final int SENSOR_TYPE_VENDOR_EXTENSION_END = 0x6fffffff;
/** @hide */
@IntDef({
- SENSOR_TYPE_CAR_SPEED,
- SENSOR_TYPE_RPM,
- SENSOR_TYPE_ODOMETER,
- SENSOR_TYPE_FUEL_LEVEL,
- SENSOR_TYPE_PARKING_BRAKE,
- SENSOR_TYPE_GEAR,
- SENSOR_TYPE_NIGHT,
- SENSOR_TYPE_ENVIRONMENT,
- SENSOR_TYPE_IGNITION_STATE,
- SENSOR_TYPE_WHEEL_TICK_DISTANCE,
- SENSOR_TYPE_ABS_ACTIVE,
- SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
- SENSOR_TYPE_FUEL_DOOR_OPEN,
- SENSOR_TYPE_EV_BATTERY_LEVEL,
- SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
- SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
- SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
- SENSOR_TYPE_ENGINE_OIL_LEVEL,
+ SENSOR_TYPE_CAR_SPEED,
+ SENSOR_TYPE_RPM,
+ SENSOR_TYPE_ODOMETER,
+ SENSOR_TYPE_FUEL_LEVEL,
+ SENSOR_TYPE_PARKING_BRAKE,
+ SENSOR_TYPE_GEAR,
+ SENSOR_TYPE_NIGHT,
+ SENSOR_TYPE_ENVIRONMENT,
+ SENSOR_TYPE_IGNITION_STATE,
+ SENSOR_TYPE_WHEEL_TICK_DISTANCE,
+ SENSOR_TYPE_ABS_ACTIVE,
+ SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
+ SENSOR_TYPE_FUEL_DOOR_OPEN,
+ SENSOR_TYPE_EV_BATTERY_LEVEL,
+ SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
+ SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
+ SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
+ SENSOR_TYPE_ENGINE_OIL_LEVEL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorType {}
+ private final ArraySet<Integer> mSensorConfigIds = new ArraySet<>(Arrays.asList(new Integer[]{
+ SENSOR_TYPE_CAR_SPEED,
+ SENSOR_TYPE_RPM,
+ SENSOR_TYPE_ODOMETER,
+ SENSOR_TYPE_FUEL_LEVEL,
+ SENSOR_TYPE_PARKING_BRAKE,
+ SENSOR_TYPE_GEAR,
+ SENSOR_TYPE_NIGHT,
+ SENSOR_TYPE_ENVIRONMENT,
+ SENSOR_TYPE_IGNITION_STATE,
+ SENSOR_TYPE_WHEEL_TICK_DISTANCE,
+ SENSOR_TYPE_ABS_ACTIVE,
+ SENSOR_TYPE_TRACTION_CONTROL_ACTIVE,
+ SENSOR_TYPE_FUEL_DOOR_OPEN,
+ SENSOR_TYPE_EV_BATTERY_LEVEL,
+ SENSOR_TYPE_EV_CHARGE_PORT_OPEN,
+ SENSOR_TYPE_EV_CHARGE_PORT_CONNECTED,
+ SENSOR_TYPE_EV_BATTERY_CHARGE_RATE,
+ SENSOR_TYPE_ENGINE_OIL_LEVEL,
+ }));
+
/** Read sensor in default normal rate set for each sensors. This is default rate. */
- public static final int SENSOR_RATE_NORMAL = 3;
- public static final int SENSOR_RATE_UI = 2;
- public static final int SENSOR_RATE_FAST = 1;
+ public static final int SENSOR_RATE_NORMAL = 1;
+ public static final int SENSOR_RATE_UI = 5;
+ public static final int SENSOR_RATE_FAST = 10;
/** Read sensor at the maximum rate. Actual rate will be different depending on the sensor. */
- public static final int SENSOR_RATE_FASTEST = 0;
+ public static final int SENSOR_RATE_FASTEST = 100;
/** @hide */
@IntDef({
- SENSOR_RATE_NORMAL,
- SENSOR_RATE_UI,
- SENSOR_RATE_FAST,
- SENSOR_RATE_FASTEST
+ SENSOR_RATE_NORMAL,
+ SENSOR_RATE_UI,
+ SENSOR_RATE_FAST,
+ SENSOR_RATE_FASTEST
})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorRate {}
- private static final int MSG_SENSOR_EVENTS = 0;
-
- private final ICarSensor mService;
-
- private CarSensorEventListenerToService mCarSensorEventListenerToService;
+ private CarPropertyEventListenerToBase mCarPropertyEventListener = null;
/**
- * To keep record of locally active sensors. Key is sensor type. This is used as a basic lock
- * for all client accesses.
+ * To keep record of CarPropertyEventListenerToBase
*/
- private final SparseArray<CarSensorListeners> mActiveSensorListeners = new SparseArray<>();
+ private final HashMap<OnSensorChangedListener, CarPropertyEventListenerToBase> mListenerMap =
+ new HashMap<>();
+ /**
+ * Listener for car sensor data change.
+ * Callbacks are called in the Looper context.
+ */
+ public interface OnSensorChangedListener {
+ /**
+ * Called when there is a new sensor data from car.
+ * @param event Incoming sensor event for the given sensor type.
+ */
+ void onSensorChanged(CarSensorEvent event);
+ }
- /** Handles call back into clients. */
- private final SingleMessageHandler<CarSensorEvent> mHandlerCallback;
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener{
+ private final WeakReference<CarSensorManager> mManager;
+ private final OnSensorChangedListener mListener;
+ CarPropertyEventListenerToBase(CarSensorManager manager, OnSensorChangedListener listener) {
+ mManager = new WeakReference<>(manager);
+ mListener = listener;
+ }
-
- /** @hide */
- public CarSensorManager(IBinder service, Context context, Handler handler) {
- mService = ICarSensor.Stub.asInterface(service);
- mHandlerCallback = new SingleMessageHandler<CarSensorEvent>(handler.getLooper(),
- MSG_SENSOR_EVENTS) {
- @Override
- protected void handleEvent(CarSensorEvent event) {
- CarSensorListeners listeners;
- synchronized (mActiveSensorListeners) {
- listeners = mActiveSensorListeners.get(event.sensorType);
- }
- if (listeners != null) {
- listeners.onSensorChanged(event);
+ @Override
+ public void onChangeEvent(CarPropertyValue value) {
+ synchronized (this) {
+ CarSensorManager manager = mManager.get();
+ if (manager != null) {
+ manager.handleOnChangeEvent(value, mListener);
}
}
- };
+ }
+
+ @Override
+ public void onErrorEvent(int propertyId, int zone) {
+
+ }
+ }
+
+ private void handleOnChangeEvent(CarPropertyValue value, OnSensorChangedListener listener) {
+ synchronized (mListenerMap) {
+ CarSensorEvent event = createCarSensorEvent(value);
+ listener.onSensorChanged(event);
+ }
+ }
+
+ private void handleOnErrorEvent(int propertyId, int zone) {
+
+ }
+ /** @hide */
+ public CarSensorManager(IBinder service, Context context, Handler handler) {
+ mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
/** @hide */
@Override
public void onCarDisconnected() {
- synchronized(mActiveSensorListeners) {
- mActiveSensorListeners.clear();
- mCarSensorEventListenerToService = null;
+ synchronized (mListenerMap) {
+ mListenerMap.clear();
}
+ mCarPropertyMgr.onCarDisconnected();
}
/**
@@ -284,15 +313,21 @@
*/
public int[] getSupportedSensors() throws CarNotConnectedException {
try {
- return mService.getSupportedSensors();
+ List<CarPropertyConfig> carPropertyConfigList = getPropertyList();
+ int[] supportedSensors = new int[carPropertyConfigList.size()];
+ for (int i = 0; i < supportedSensors.length; i++) {
+ supportedSensors[i] = carPropertyConfigList.get(i).getPropertyId();
+ }
+ return supportedSensors;
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
}
return new int[0];
}
+ private List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
+ return mCarPropertyMgr.getPropertyList(mSensorConfigIds);
+ }
/**
* Tells if given sensor is supported or not.
* @param sensorType
@@ -325,18 +360,6 @@
}
/**
- * Listener for car sensor data change.
- * Callbacks are called in the Looper context.
- */
- public interface OnSensorChangedListener {
- /**
- * Called when there is a new sensor data from car.
- * @param event Incoming sensor event for the given sensor type.
- */
- void onSensorChanged(final CarSensorEvent event);
- }
-
- /**
* Register {@link OnSensorChangedListener} to get repeated sensor updates. Multiple listeners
* can be registered for a single sensor or the same listener can be used for different sensors.
* If the same listener is registered again for the same sensor, it will be either ignored or
@@ -368,33 +391,21 @@
conditional=true)
public boolean registerListener(OnSensorChangedListener listener, @SensorType int sensorType,
@SensorRate int rate) throws CarNotConnectedException, IllegalArgumentException {
- assertSensorType(sensorType);
if (rate != SENSOR_RATE_FASTEST && rate != SENSOR_RATE_NORMAL
&& rate != SENSOR_RATE_UI && rate != SENSOR_RATE_FAST) {
throw new IllegalArgumentException("wrong rate " + rate);
}
- synchronized(mActiveSensorListeners) {
- if (mCarSensorEventListenerToService == null) {
- mCarSensorEventListenerToService = new CarSensorEventListenerToService(this);
- }
- boolean needsServerUpdate = false;
- CarSensorListeners listeners;
- listeners = mActiveSensorListeners.get(sensorType);
- if (listeners == null) {
- listeners = new CarSensorListeners(rate);
- mActiveSensorListeners.put(sensorType, listeners);
- needsServerUpdate = true;
- }
- if (listeners.addAndUpdateRate(listener, rate)) {
- needsServerUpdate = true;
- }
- if (needsServerUpdate) {
- if (!registerOrUpdateSensorListener(sensorType, rate)) {
- return false;
- }
- }
+ if (mListenerMap.get(listener) == null) {
+ mCarPropertyEventListener = new CarPropertyEventListenerToBase(this, listener);
+ } else {
+ mCarPropertyEventListener = mListenerMap.get(listener);
}
- return true;
+ if (mCarPropertyMgr.registerListener(mCarPropertyEventListener, sensorType, rate)) {
+ mListenerMap.put(listener, mCarPropertyEventListener);
+ return true;
+ } else {
+ return false;
+ }
}
/**
@@ -404,10 +415,10 @@
*/
public void unregisterListener(OnSensorChangedListener listener) {
//TODO: removing listener should reset update rate, bug: 32060307
- synchronized(mActiveSensorListeners) {
- for (int i = 0; i < mActiveSensorListeners.size(); i++) {
- doUnregisterListenerLocked(listener, mActiveSensorListeners.keyAt(i));
- }
+ synchronized (mListenerMap) {
+ mCarPropertyEventListener = mListenerMap.get(listener);
+ mCarPropertyMgr.unregisterListener(mCarPropertyEventListener);
+ mListenerMap.remove(listener);
}
}
@@ -418,49 +429,10 @@
* @param sensorType
*/
public void unregisterListener(OnSensorChangedListener listener, @SensorType int sensorType) {
- synchronized(mActiveSensorListeners) {
- doUnregisterListenerLocked(listener, sensorType);
+ synchronized (mListenerMap) {
+ mCarPropertyEventListener = mListenerMap.get(listener);
}
- }
-
- private void doUnregisterListenerLocked(OnSensorChangedListener listener, Integer sensor) {
- CarSensorListeners listeners = mActiveSensorListeners.get(sensor);
- if (listeners != null) {
- boolean needsServerUpdate = false;
- if (listeners.contains(listener)) {
- needsServerUpdate = listeners.remove(listener);
- }
- if (listeners.isEmpty()) {
- try {
- mService.unregisterSensorListener(sensor.intValue(),
- mCarSensorEventListenerToService);
- } catch (RemoteException e) {
- //ignore
- }
- mActiveSensorListeners.remove(sensor);
- } else if (needsServerUpdate) {
- try {
- registerOrUpdateSensorListener(sensor, listeners.getRate());
- } catch (CarNotConnectedException e) {
- // ignore
- }
- }
- }
- }
-
- private boolean registerOrUpdateSensorListener(int sensor, int rate)
- throws CarNotConnectedException {
- try {
- if (!mService.registerOrUpdateSensorListener(sensor, rate,
- mCarSensorEventListenerToService)) {
- return false;
- }
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch (RemoteException e) {
- throw new CarNotConnectedException(e);
- }
- return true;
+ mCarPropertyMgr.unregisterListener(mCarPropertyEventListener, sensorType);
}
/**
@@ -473,13 +445,11 @@
*/
public CarSensorEvent getLatestSensorEvent(@SensorType int type)
throws CarNotConnectedException {
- assertSensorType(type);
try {
- return mService.getLatestSensorEvent(type);
+ CarPropertyValue propertyValue = mCarPropertyMgr.getProperty(type, 0);
+ return createCarSensorEvent(propertyValue);
} catch (IllegalStateException e) {
CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch(RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
}
return null;
}
@@ -492,58 +462,25 @@
throw new CarNotConnectedException();
}
- private void assertSensorType(int sensorType) {
- if (sensorType == 0 || !((sensorType <= SENSOR_TYPE_MAX) ||
- ((sensorType >= SENSOR_TYPE_VENDOR_EXTENSION_START) &&
- (sensorType <= SENSOR_TYPE_VENDOR_EXTENSION_END)))) {
- throw new IllegalArgumentException("invalid sensor type " + sensorType);
+ private CarSensorEvent createCarSensorEvent(CarPropertyValue propertyValue) {
+ Class<?> actualClass = propertyValue.getValue().getClass();
+ CarSensorEvent event = null;
+ if (actualClass == Float.class) {
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 1, 0, 0);
+ event.floatValues[0] = (float) propertyValue.getValue();
+ } else if (actualClass == Integer.class) {
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 0, 1, 0);
+ event.intValues[0] = (int) propertyValue.getValue();
+ } else if (actualClass == Boolean.class) {
+ event = new CarSensorEvent(propertyValue.getPropertyId(),
+ propertyValue.getTimestamp(), 0, 1, 0);
+ event.intValues[0] = (boolean) propertyValue.getValue() ? 1 : 0;
+ } else {
+ // TODO: handle int64_vec and mixed type
}
- }
-
- private void handleOnSensorChanged(List<CarSensorEvent> events) {
- mHandlerCallback.sendEvents(events);
- }
-
- private static class CarSensorEventListenerToService extends ICarSensorEventListener.Stub {
- private final WeakReference<CarSensorManager> mManager;
-
- public CarSensorEventListenerToService(CarSensorManager manager) {
- mManager = new WeakReference<>(manager);
- }
-
- @Override
- public void onSensorChanged(List<CarSensorEvent> events) {
- CarSensorManager manager = mManager.get();
- if (manager != null) {
- manager.handleOnSensorChanged(events);
- }
- }
- }
-
- private class CarSensorListeners extends CarRatedListeners<OnSensorChangedListener> {
- CarSensorListeners(int rate) {
- super(rate);
- }
-
- void onSensorChanged(final CarSensorEvent event) {
- // throw away old sensor data as oneway binder call can change order.
- long updateTime = event.timestamp;
- if (updateTime < mLastUpdateTime) {
- Log.w(CarLibLog.TAG_SENSOR, "dropping old sensor data");
- return;
- }
- mLastUpdateTime = updateTime;
- List<OnSensorChangedListener> listeners;
- synchronized (mActiveSensorListeners) {
- listeners = new ArrayList<>(getListeners());
- }
- listeners.forEach(new Consumer<OnSensorChangedListener>() {
- @Override
- public void accept(OnSensorChangedListener listener) {
- listener.onSensorChanged(event);
- }
- });
- }
+ return event;
}
/**
@@ -558,15 +495,43 @@
* @hide
*/
public CarSensorConfig getSensorConfig(@SensorType int type)
- throws CarNotConnectedException {
- assertSensorType(type);
- try {
- return mService.getSensorConfig(type);
- } catch (IllegalStateException e) {
- CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
- } catch(RemoteException e) {
- handleCarServiceRemoteExceptionAndThrow(e);
+ throws CarNotConnectedException {
+ Bundle b = null;
+ switch (type) {
+ case SENSOR_TYPE_WHEEL_TICK_DISTANCE:
+ List<CarPropertyConfig> propertyConfigs = mCarPropertyMgr.getPropertyList();
+ for (CarPropertyConfig p : propertyConfigs) {
+ if (p.getPropertyId() == type) {
+ b = createWheelDistanceTickBundle(p.getConfigArray());
+ }
+ }
+ break;
+ default:
+ b = Bundle.EMPTY;
+ break;
}
- return new CarSensorConfig(0, Bundle.EMPTY);
+ return new CarSensorConfig(type, b);
+ }
+
+ private static final int INDEX_WHEEL_DISTANCE_ENABLE_FLAG = 0;
+ private static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1;
+ private static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2;
+ private static final int INDEX_WHEEL_DISTANCE_REAR_RIGHT = 3;
+ private static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4;
+ private static final int WHEEL_TICK_DISTANCE_BUNDLE_SIZE = 6;
+
+ private Bundle createWheelDistanceTickBundle(List<Integer> configArray) {
+ Bundle b = new Bundle(WHEEL_TICK_DISTANCE_BUNDLE_SIZE);
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS,
+ configArray.get(INDEX_WHEEL_DISTANCE_ENABLE_FLAG));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_LEFT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_FRONT_LEFT));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_FRONT_RIGHT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_FRONT_RIGHT));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_RIGHT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_REAR_RIGHT));
+ b.putInt(CarSensorConfig.WHEEL_TICK_DISTANCE_REAR_LEFT_UM_PER_TICK,
+ configArray.get(INDEX_WHEEL_DISTANCE_REAR_LEFT));
+ return b;
}
}
diff --git a/car-lib/src/android/car/hardware/CarVendorExtensionManager.java b/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
index bdaa8cd..ce2831c 100644
--- a/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
+++ b/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
@@ -20,14 +20,15 @@
import android.car.Car;
import android.car.CarManagerBase;
import android.car.CarNotConnectedException;
-import android.car.hardware.property.CarPropertyManagerBase;
-import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback;
+import android.car.hardware.property.CarPropertyManager;
import android.os.Handler;
import android.os.IBinder;
import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
+import java.lang.ref.WeakReference;
+import java.util.Collection;
import java.util.List;
/**
@@ -42,12 +43,60 @@
private final static boolean DBG = false;
private final static String TAG = CarVendorExtensionManager.class.getSimpleName();
- private final CarPropertyManagerBase mPropertyManager;
+ private final CarPropertyManager mPropertyManager;
+ private CarPropertyEventListenerToBase mListenerToBase = null;
@GuardedBy("mLock")
- private ArraySet<CarVendorExtensionCallback> mCallbacks;
+ private final ArraySet<CarVendorExtensionCallback> mCallbacks = new ArraySet<>();
private final Object mLock = new Object();
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener{
+ private final WeakReference<CarVendorExtensionManager> mManager;
+
+ CarPropertyEventListenerToBase(CarVendorExtensionManager manager) {
+ mManager = new WeakReference<>(manager);
+ }
+
+ @Override
+ public void onChangeEvent(CarPropertyValue value) {
+ CarVendorExtensionManager manager = mManager.get();
+ if (manager != null) {
+ manager.handleOnChangeEvent(value);
+ }
+ }
+
+ @Override
+ public void onErrorEvent(int propertyId, int zone) {
+ CarVendorExtensionManager manager = mManager.get();
+ if (manager != null) {
+ manager.handleOnErrorEvent(propertyId, zone);
+ }
+ }
+ }
+
+ private void handleOnChangeEvent(CarPropertyValue value) {
+ Collection<CarVendorExtensionCallback> callbacks;
+ synchronized (this) {
+ callbacks = new ArraySet<>(mCallbacks);
+ }
+ for (CarVendorExtensionCallback l: callbacks) {
+ l.onChangeEvent(value);
+ }
+ }
+
+ private void handleOnErrorEvent(int propertyId, int zone) {
+ Collection<CarVendorExtensionCallback> listeners;
+ synchronized (this) {
+ listeners = new ArraySet<>(mCallbacks);
+ }
+ if (!listeners.isEmpty()) {
+ for (CarVendorExtensionCallback l: listeners) {
+ l.onErrorEvent(propertyId, zone);
+ }
+ }
+ }
+
/**
* Creates an instance of the {@link CarVendorExtensionManager}.
*
@@ -55,7 +104,7 @@
* @hide
*/
public CarVendorExtensionManager(IBinder service, Handler handler) {
- mPropertyManager = new CarPropertyManagerBase(service, handler, DBG, TAG);
+ mPropertyManager = new CarPropertyManager(service, handler, DBG, TAG);
}
/**
@@ -77,43 +126,32 @@
public void registerCallback(CarVendorExtensionCallback callback)
throws CarNotConnectedException {
synchronized (mLock) {
- if (mCallbacks == null) {
- mPropertyManager.registerCallback(new CarPropertyEventCallback() {
- @Override
- public void onChangeEvent(CarPropertyValue value) {
- for (CarVendorExtensionCallback listener: getCallbacks()) {
- listener.onChangeEvent(value);
- }
- }
+ if (mCallbacks.isEmpty()) {
+ mListenerToBase = new CarPropertyEventListenerToBase(this);
+ }
- @Override
- public void onErrorEvent(int propertyId, int zone) {
- for (CarVendorExtensionCallback listener: getCallbacks()) {
- listener.onErrorEvent(propertyId, zone);
- }
- }
- });
- mCallbacks = new ArraySet<>(1 /* We expect at least one element */);
+ List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mPropertyManager.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
}
}
/** Unregisters listener that was previously registered. */
- public void unregisterCallback(CarVendorExtensionCallback callback) {
+ public void unregisterCallback(CarVendorExtensionCallback callback)
+ throws CarNotConnectedException {
synchronized (mLock) {
mCallbacks.remove(callback);
- if (mCallbacks.isEmpty()) {
- mPropertyManager.unregisterCallback();
- mCallbacks = null;
+ List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mPropertyManager.unregisterListener(mListenerToBase, c.getPropertyId());
}
- }
- }
-
- /** Returns copy of listeners. Thread safe. */
- private CarVendorExtensionCallback[] getCallbacks() {
- synchronized (mLock) {
- return mCallbacks.toArray(new CarVendorExtensionCallback[mCallbacks.size()]);
+ if (mCallbacks.isEmpty()) {
+ mListenerToBase = null;
+ }
}
}
diff --git a/car-lib/src/android/car/hardware/cabin/CarCabinManager.java b/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
index c27b414..1dee2b0 100644
--- a/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
+++ b/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
@@ -23,8 +23,7 @@
import android.car.CarNotConnectedException;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
-import android.car.hardware.property.CarPropertyManagerBase;
-import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback;
+import android.car.hardware.property.CarPropertyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
@@ -33,6 +32,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -57,7 +57,7 @@
public final class CarCabinManager implements CarManagerBase {
private final static boolean DBG = false;
private final static String TAG = "CarCabinManager";
- private final CarPropertyManagerBase mMgr;
+ private final CarPropertyManager mCarPropertyMgr;
private final ArraySet<CarCabinEventCallback> mCallbacks = new ArraySet<>();
private CarPropertyEventListenerToBase mListenerToBase = null;
@@ -69,45 +69,45 @@
* Some vehicles (minivans) can open the door electronically. Hence, the ability
* to write this property.
*/
- public static final int ID_DOOR_POS = 0x0001;
+ public static final int ID_DOOR_POS = 0x16400b00;
/** door move, int type
* Positive values open the door, negative values close it.
*/
- public static final int ID_DOOR_MOVE = 0x0002;
+ public static final int ID_DOOR_MOVE = 0x16400b01;
/** door lock, bool type
* 'true' indicates door is locked.
*/
- public static final int ID_DOOR_LOCK = 0x0003;
+ public static final int ID_DOOR_LOCK = 0x16200b02;
/** Mirror properties are zoned by VehicleAreaMirror */
/**
* mirror z position, int type
* Positive value indicates tilt upwards, negative value tilt downwards.
*/
- public static final int ID_MIRROR_Z_POS = 0x1001;
+ public static final int ID_MIRROR_Z_POS = 0x14400b40;
/** mirror z move, int type
* Positive value tilts the mirror upwards, negative value tilts downwards.
*/
- public static final int ID_MIRROR_Z_MOVE = 0x1002;
+ public static final int ID_MIRROR_Z_MOVE = 0x14400b41;
/**
* mirror y position, int type
* Positive value indicates tilt right, negative value tilt left
*/
- public static final int ID_MIRROR_Y_POS = 0x1003;
+ public static final int ID_MIRROR_Y_POS = 0x14400b42;
/** mirror y move, int type
* Positive value tilts the mirror right, negative value tilts left.
*/
- public static final int ID_MIRROR_Y_MOVE = 0x1004;
+ public static final int ID_MIRROR_Y_MOVE = 0x14400b43;
/**
* mirror lock, bool type
* True indicates mirror positions are locked and not changeable.
*/
- public static final int ID_MIRROR_LOCK = 0x1005;
+ public static final int ID_MIRROR_LOCK = 0x11200b44;
/**
* mirror fold, bool type
* True indicates mirrors are folded.
*/
- public static final int ID_MIRROR_FOLD = 0x1006;
+ public static final int ID_MIRROR_FOLD = 0x11200b45;
/** Seat properties are zoned by VehicleAreaSeat */
/**
@@ -120,173 +120,173 @@
* When the user wants to select a preset, the desired preset number (1, 2, or 3)
* is set.
*/
- public static final int ID_SEAT_MEMORY_SELECT = 0x2001;
+ public static final int ID_SEAT_MEMORY_SELECT = 0x15400b80;
/**
* seat memory set, int type
* This setting allows the user to save the current seat position settings into
* the selected preset slot. The maxValue for each seat position shall match
* the maxValue for VEHICLE_PROPERTY_SEAT_MEMORY_SELECT.
*/
- public static final int ID_SEAT_MEMORY_SET = 0x2002;
+ public static final int ID_SEAT_MEMORY_SET = 0x15400b81;
/**
* seat belt buckled, bool type
* True indicates belt is buckled.
*/
- public static final int ID_SEAT_BELT_BUCKLED = 0x2003;
+ public static final int ID_SEAT_BELT_BUCKLED = 0x15200b82;
/**
* seat belt height position, int type
* Adjusts the shoulder belt anchor point.
* Max value indicates highest position.
* Min value indicates lowest position.
*/
- public static final int ID_SEAT_BELT_HEIGHT_POS = 0x2004;
+ public static final int ID_SEAT_BELT_HEIGHT_POS = 0x15400b83;
/** seat belt height move, int type
* Adjusts the shoulder belt anchor point.
* Positive value moves towards highest point.
* Negative value moves towards lowest point.
*/
- public static final int ID_SEAT_BELT_HEIGHT_MOVE = 0x2005;
+ public static final int ID_SEAT_BELT_HEIGHT_MOVE = 0x15400b84;
/**
* seat fore/aft position, int type
* Sets the seat position forward (closer to steering wheel) and backwards.
* Max value indicates closest to wheel, min value indicates most rearward position.
*/
- public static final int ID_SEAT_FORE_AFT_POS = 0x2006;
+ public static final int ID_SEAT_FORE_AFT_POS = 0x15400b85;
/**
* seat fore/aft move, int type
* Positive value moves seat forward (closer to steering wheel).
* Negative value moves seat rearward.
*/
- public static final int ID_SEAT_FORE_AFT_MOVE = 0x2007;
+ public static final int ID_SEAT_FORE_AFT_MOVE = 0x15400b86;
/**
* seat backrest angle #1 position, int type
* Backrest angle 1 is the actuator closest to the bottom of the seat.
* Max value indicates angling forward towards the steering wheel.
* Min value indicates full recline.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 0x2008;
+ public static final int ID_SEAT_BACKREST_ANGLE_1_POS = 0x15400b87;
/** seat backrest angle #1 move, int type
* Backrest angle 1 is the actuator closest to the bottom of the seat.
* Positive value angles seat towards the steering wheel.
* Negatie value angles away from steering wheel.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 0x2009;
+ public static final int ID_SEAT_BACKREST_ANGLE_1_MOVE = 0x15400b88;
/**
* seat backrest angle #2 position, int type
* Backrest angle 2 is the next actuator up from the bottom of the seat.
* Max value indicates angling forward towards the steering wheel.
* Min value indicates full recline.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 0x200A;
+ public static final int ID_SEAT_BACKREST_ANGLE_2_POS = 0x15400b89;
/** seat backrest angle #2 move, int type
* Backrest angle 2 is the next actuator up from the bottom of the seat.
* Positive value tilts forward towards the steering wheel.
* Negative value tilts backwards.
*/
- public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 0x200B;
+ public static final int ID_SEAT_BACKREST_ANGLE_2_MOVE = 0x15400b8a;
/**
* seat height position, int type
* Sets the seat height.
* Max value indicates highest position.
* Min value indicates lowest position.
*/
- public static final int ID_SEAT_HEIGHT_POS = 0x200C;
+ public static final int ID_SEAT_HEIGHT_POS = 0x15400b8b;
/** seat height move, int type
* Sets the seat height.
* Positive value raises the seat.
* Negative value lowers the seat.
* */
- public static final int ID_SEAT_HEIGHT_MOVE = 0x200D;
+ public static final int ID_SEAT_HEIGHT_MOVE = 0x15400b8c;
/**
* seat depth position, int type
* Sets the seat depth, distance from back rest to front edge of seat.
* Max value indicates longest depth position.
* Min value indicates shortest position.
*/
- public static final int ID_SEAT_DEPTH_POS = 0x200E;
+ public static final int ID_SEAT_DEPTH_POS = 0x15400b8d;
/** seat depth move, int type
* Adjusts the seat depth, distance from back rest to front edge of seat.
* Positive value increases the distance from back rest to front edge of seat.
* Negative value decreases this distance.
*/
- public static final int ID_SEAT_DEPTH_MOVE = 0x200F;
+ public static final int ID_SEAT_DEPTH_MOVE = 0x15400b8e;
/**
* seat tilt position, int type
* Sets the seat tilt.
* Max value indicates front edge of seat higher than back edge.
* Min value indicates front edge of seat lower than back edge.
*/
- public static final int ID_SEAT_TILT_POS = 0x2010;
+ public static final int ID_SEAT_TILT_POS = 0x15400b8f;
/** seat tilt move, int type
* Adjusts the seat tilt.
* Positive value lifts front edge of seat higher than back edge.
* Negative value lowers front edge of seat in relation to back edge.
*/
- public static final int ID_SEAT_TILT_MOVE = 0x2011;
+ public static final int ID_SEAT_TILT_MOVE = 0x15400b90;
/**
* seat lumbar fore/aft position, int type
* Pushes the lumbar support forward and backwards.
* Max value indicates most forward position.
* Min value indicates most rearward position.
*/
- public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 0x2012;
+ public static final int ID_SEAT_LUMBAR_FORE_AFT_POS = 0x15400b91;
/** seat lumbar fore/aft move, int type
* Adjusts the lumbar support forwards and backwards.
* Positive value moves lumbar support forward.
* Negative value moves lumbar support rearward.
*/
- public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 0x2013;
+ public static final int ID_SEAT_LUMBAR_FORE_AFT_MOVE = 0x15400b92;
/**
* seat lumbar side support position, int type
* Sets the amount of lateral lumbar support.
* Max value indicates widest lumbar setting (i.e. least support)
* Min value indicates thinnest lumbar setting.
*/
- public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x2014;
+ public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x15400b93;
/** seat lumbar side support move, int type
* Adjusts the amount of lateral lumbar support.
* Positive value widens the lumbar area.
* Negative value makes the lumbar area thinner.
*/
- public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x2015;
+ public static final int ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x15400b94;
/**
* seat headrest height position, int type
* Sets the headrest height.
* Max value indicates tallest setting.
* Min value indicates shortest setting.
*/
- public static final int ID_SEAT_HEADREST_HEIGHT_POS = 0x2016;
+ public static final int ID_SEAT_HEADREST_HEIGHT_POS = 0x15400b95;
/** seat headrest height move, int type
* Postive value moves the headrest higher.
* Negative value moves the headrest lower.
*/
- public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 0x2017;
+ public static final int ID_SEAT_HEADREST_HEIGHT_MOVE = 0x15400b96;
/**
* seat headrest angle position, int type
* Sets the angle of the headrest.
* Max value indicates most upright angle.
* Min value indicates shallowest headrest angle.
*/
- public static final int ID_SEAT_HEADREST_ANGLE_POS = 0x2018;
+ public static final int ID_SEAT_HEADREST_ANGLE_POS = 0x15400b97;
/** seat headrest angle move, int type
* Adjusts the angle of the headrest.
* Positive value angles headrest towards most upright angle.
* Negative value angles headrest towards shallowest headrest angle.
*/
- public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 0x2019;
+ public static final int ID_SEAT_HEADREST_ANGLE_MOVE = 0x15400b98;
/**
* seat headrest fore/aft position, int type
* Sets the headrest forwards and backwards.
* Max value indicates position closest to front of car.
* Min value indicates position closest to rear of car.
*/
- public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 0x201A;
+ public static final int ID_SEAT_HEADREST_FORE_AFT_POS = 0x15400b99;
/** seat headrest fore/aft move, int type
* Adjsuts the headrest forwards and backwards.
* Positive value moves the headrest closer to front of car.
* Negative value moves the headrest closer to rear of car.
*/
- public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 0x201B;
+ public static final int ID_SEAT_HEADREST_FORE_AFT_MOVE = 0x15400b9a;
/** Window properties are zoned by VehicleAreaWindow */
/**
@@ -294,62 +294,103 @@
* Max = window down / open.
* Min = window up / closed.
*/
- public static final int ID_WINDOW_POS = 0x3001;
+ public static final int ID_WINDOW_POS = 0x13400bc0;
/** window move, int type
* Positive value moves window down / opens window.
* Negative value moves window up / closes window.
*/
- public static final int ID_WINDOW_MOVE = 0x3002;
+ public static final int ID_WINDOW_MOVE = 0x13400bc1;
/**
* window lock, bool type
* True indicates windows are locked and can't be moved.
*/
- public static final int ID_WINDOW_LOCK = 0x3003;
+ public static final int ID_WINDOW_LOCK = 0x13400bc4;
/** @hide */
@IntDef({
- ID_DOOR_POS,
- ID_DOOR_MOVE,
- ID_DOOR_LOCK,
- ID_MIRROR_Z_POS,
- ID_MIRROR_Z_MOVE,
- ID_MIRROR_Y_POS,
- ID_MIRROR_Y_MOVE,
- ID_MIRROR_LOCK,
- ID_MIRROR_FOLD,
- ID_SEAT_MEMORY_SELECT,
- ID_SEAT_MEMORY_SET,
- ID_SEAT_BELT_BUCKLED,
- ID_SEAT_BELT_HEIGHT_POS,
- ID_SEAT_BELT_HEIGHT_MOVE,
- ID_SEAT_FORE_AFT_POS,
- ID_SEAT_FORE_AFT_MOVE,
- ID_SEAT_BACKREST_ANGLE_1_POS,
- ID_SEAT_BACKREST_ANGLE_1_MOVE,
- ID_SEAT_BACKREST_ANGLE_2_POS,
- ID_SEAT_BACKREST_ANGLE_2_MOVE,
- ID_SEAT_HEIGHT_POS,
- ID_SEAT_HEIGHT_MOVE,
- ID_SEAT_DEPTH_POS,
- ID_SEAT_DEPTH_MOVE,
- ID_SEAT_TILT_POS,
- ID_SEAT_TILT_MOVE,
- ID_SEAT_LUMBAR_FORE_AFT_POS,
- ID_SEAT_LUMBAR_FORE_AFT_MOVE,
- ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
- ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
- ID_SEAT_HEADREST_HEIGHT_POS,
- ID_SEAT_HEADREST_HEIGHT_MOVE,
- ID_SEAT_HEADREST_ANGLE_POS,
- ID_SEAT_HEADREST_ANGLE_MOVE,
- ID_SEAT_HEADREST_FORE_AFT_POS,
- ID_SEAT_HEADREST_FORE_AFT_MOVE,
- ID_WINDOW_POS,
- ID_WINDOW_MOVE,
- ID_WINDOW_LOCK
+ ID_DOOR_POS,
+ ID_DOOR_MOVE,
+ ID_DOOR_LOCK,
+ ID_MIRROR_Z_POS,
+ ID_MIRROR_Z_MOVE,
+ ID_MIRROR_Y_POS,
+ ID_MIRROR_Y_MOVE,
+ ID_MIRROR_LOCK,
+ ID_MIRROR_FOLD,
+ ID_SEAT_MEMORY_SELECT,
+ ID_SEAT_MEMORY_SET,
+ ID_SEAT_BELT_BUCKLED,
+ ID_SEAT_BELT_HEIGHT_POS,
+ ID_SEAT_BELT_HEIGHT_MOVE,
+ ID_SEAT_FORE_AFT_POS,
+ ID_SEAT_FORE_AFT_MOVE,
+ ID_SEAT_BACKREST_ANGLE_1_POS,
+ ID_SEAT_BACKREST_ANGLE_1_MOVE,
+ ID_SEAT_BACKREST_ANGLE_2_POS,
+ ID_SEAT_BACKREST_ANGLE_2_MOVE,
+ ID_SEAT_HEIGHT_POS,
+ ID_SEAT_HEIGHT_MOVE,
+ ID_SEAT_DEPTH_POS,
+ ID_SEAT_DEPTH_MOVE,
+ ID_SEAT_TILT_POS,
+ ID_SEAT_TILT_MOVE,
+ ID_SEAT_LUMBAR_FORE_AFT_POS,
+ ID_SEAT_LUMBAR_FORE_AFT_MOVE,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
+ ID_SEAT_HEADREST_HEIGHT_POS,
+ ID_SEAT_HEADREST_HEIGHT_MOVE,
+ ID_SEAT_HEADREST_ANGLE_POS,
+ ID_SEAT_HEADREST_ANGLE_MOVE,
+ ID_SEAT_HEADREST_FORE_AFT_POS,
+ ID_SEAT_HEADREST_FORE_AFT_MOVE,
+ ID_WINDOW_POS,
+ ID_WINDOW_MOVE,
+ ID_WINDOW_LOCK
})
@Retention(RetentionPolicy.SOURCE)
public @interface PropertyId {}
+ private final ArraySet<Integer> mCabinPropertyIds = new ArraySet<>(Arrays.asList(new Integer[]{
+ ID_DOOR_POS,
+ ID_DOOR_MOVE,
+ ID_DOOR_LOCK,
+ ID_MIRROR_Z_POS,
+ ID_MIRROR_Z_MOVE,
+ ID_MIRROR_Y_POS,
+ ID_MIRROR_Y_MOVE,
+ ID_MIRROR_LOCK,
+ ID_MIRROR_FOLD,
+ ID_SEAT_MEMORY_SELECT,
+ ID_SEAT_MEMORY_SET,
+ ID_SEAT_BELT_BUCKLED,
+ ID_SEAT_BELT_HEIGHT_POS,
+ ID_SEAT_BELT_HEIGHT_MOVE,
+ ID_SEAT_FORE_AFT_POS,
+ ID_SEAT_FORE_AFT_MOVE,
+ ID_SEAT_BACKREST_ANGLE_1_POS,
+ ID_SEAT_BACKREST_ANGLE_1_MOVE,
+ ID_SEAT_BACKREST_ANGLE_2_POS,
+ ID_SEAT_BACKREST_ANGLE_2_MOVE,
+ ID_SEAT_HEIGHT_POS,
+ ID_SEAT_HEIGHT_MOVE,
+ ID_SEAT_DEPTH_POS,
+ ID_SEAT_DEPTH_MOVE,
+ ID_SEAT_TILT_POS,
+ ID_SEAT_TILT_MOVE,
+ ID_SEAT_LUMBAR_FORE_AFT_POS,
+ ID_SEAT_LUMBAR_FORE_AFT_MOVE,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_POS,
+ ID_SEAT_LUMBAR_SIDE_SUPPORT_MOVE,
+ ID_SEAT_HEADREST_HEIGHT_POS,
+ ID_SEAT_HEADREST_HEIGHT_MOVE,
+ ID_SEAT_HEADREST_ANGLE_POS,
+ ID_SEAT_HEADREST_ANGLE_MOVE,
+ ID_SEAT_HEADREST_FORE_AFT_POS,
+ ID_SEAT_HEADREST_FORE_AFT_MOVE,
+ ID_WINDOW_POS,
+ ID_WINDOW_MOVE,
+ ID_WINDOW_LOCK
+ }));
/**
* Application registers CarCabinEventCallback object to receive updates and changes to
@@ -370,7 +411,8 @@
void onErrorEvent(@PropertyId int propertyId, int zone);
}
- private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback {
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener{
private final WeakReference<CarCabinManager> mManager;
public CarPropertyEventListenerToBase(CarCabinManager manager) {
@@ -426,7 +468,7 @@
* @hide
*/
public CarCabinManager(IBinder service, Context context, Handler handler) {
- mMgr = new CarPropertyManagerBase(service, handler, DBG, TAG);
+ mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
/**
@@ -447,9 +489,15 @@
CarNotConnectedException {
if (mCallbacks.isEmpty()) {
mListenerToBase = new CarPropertyEventListenerToBase(this);
- mMgr.registerCallback(mListenerToBase);
+ }
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
+
+
}
/**
@@ -457,10 +505,15 @@
* this listener, all listening will be stopped.
* @param callback
*/
- public synchronized void unregisterCallback(CarCabinEventCallback callback) {
+ public synchronized void unregisterCallback(CarCabinEventCallback callback)
+ throws CarNotConnectedException {
mCallbacks.remove(callback);
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
+ }
if (mCallbacks.isEmpty()) {
- mMgr.unregisterCallback();
mListenerToBase = null;
}
}
@@ -471,7 +524,7 @@
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
- return mMgr.getPropertyList();
+ return mCarPropertyMgr.getPropertyList(mCabinPropertyIds);
}
/**
@@ -483,7 +536,7 @@
*/
public boolean getBooleanProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getBooleanProperty(propertyId, area);
+ return mCarPropertyMgr.getBooleanProperty(propertyId, area);
}
/**
@@ -495,7 +548,7 @@
*/
public float getFloatProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getFloatProperty(propertyId, area);
+ return mCarPropertyMgr.getFloatProperty(propertyId, area);
}
/**
@@ -507,7 +560,7 @@
*/
public int getIntProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getIntProperty(propertyId, area);
+ return mCarPropertyMgr.getIntProperty(propertyId, area);
}
/**
@@ -519,7 +572,9 @@
*/
public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val)
throws CarNotConnectedException {
- mMgr.setBooleanProperty(propertyId, area, val);
+ if (mCabinPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
+ }
}
/**
@@ -531,7 +586,9 @@
*/
public void setFloatProperty(@PropertyId int propertyId, int area, float val)
throws CarNotConnectedException {
- mMgr.setFloatProperty(propertyId, area, val);
+ if (mCabinPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setFloatProperty(propertyId, area, val);
+ }
}
/**
@@ -543,12 +600,14 @@
*/
public void setIntProperty(@PropertyId int propertyId, int area, int val)
throws CarNotConnectedException {
- mMgr.setIntProperty(propertyId, area, val);
+ if (mCabinPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setIntProperty(propertyId, area, val);
+ }
}
/** @hide */
@Override
public void onCarDisconnected() {
- mMgr.onCarDisconnected();
+ mCarPropertyMgr.onCarDisconnected();
}
}
diff --git a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
index af4e190..c953d6f 100644
--- a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
+++ b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
@@ -23,16 +23,17 @@
import android.car.CarNotConnectedException;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
-import android.car.hardware.property.CarPropertyManagerBase;
-import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback;
+import android.car.hardware.property.CarPropertyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.util.ArraySet;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -44,10 +45,11 @@
public final class CarHvacManager implements CarManagerBase {
private final static boolean DBG = false;
private final static String TAG = "CarHvacManager";
- private final CarPropertyManagerBase mMgr;
+ private final CarPropertyManager mCarPropertyMgr;
private final ArraySet<CarHvacEventCallback> mCallbacks = new ArraySet<>();
private CarPropertyEventListenerToBase mListenerToBase = null;
+
/**
* HVAC property IDs for get/set methods
*/
@@ -59,31 +61,24 @@
* Mirror defrosters state, bool type
* true indicates mirror defroster is on
*/
- public static final int ID_MIRROR_DEFROSTER_ON = 0x0001;
+ public static final int ID_MIRROR_DEFROSTER_ON = 0x1440050c;
/**
* Steering wheel temp, int type
* Positive values indicate heating.
* Negative values indicate cooling
*/
- public static final int ID_STEERING_WHEEL_HEAT = 0x0002;
+ public static final int ID_STEERING_WHEEL_HEAT = 0x1140050d;
/**
* Outside air temperature, float type
* Value is in degrees Celsius
*/
- public static final int ID_OUTSIDE_AIR_TEMP = 0x0003;
+ public static final int ID_OUTSIDE_AIR_TEMP = 0x11600703;
/**
* Temperature units being used, int type
* 0x30 = Celsius
* 0x31 = Fahrenheit
*/
- public static final int ID_TEMPERATURE_DISPLAY_UNITS = 0x0004;
-
-
- /**
- * The maximum id that can be assigned to global (non-zoned) property.
- * @hide
- */
- public static final int ID_MAX_GLOBAL_PROPERTY_ID = 0x3fff;
+ public static final int ID_TEMPERATURE_DISPLAY_UNITS = 0x1140050e;
/**
* ID_ZONED_* represents properties available on a per-zone basis. All zones in a car are
@@ -93,85 +88,85 @@
* Temperature setpoint, float type
* Temperature set by the user, units are in degrees Celsius.
*/
- public static final int ID_ZONED_TEMP_SETPOINT = 0x4001;
+ public static final int ID_ZONED_TEMP_SETPOINT = 0x15600503;
/**
* Actual temperature, float type
* Actual zone temperature is read only value, in terms of F or C.
*/
- public static final int ID_ZONED_TEMP_ACTUAL = 0x4002;
+ public static final int ID_ZONED_TEMP_ACTUAL = 0x15600502;
/**
* HVAC system powered on / off, bool type
* In many vehicles, if the HVAC system is powered off, the SET and GET command will
* throw an IllegalStateException. To correct this, need to turn on the HVAC module first
* before manipulating a parameter.
*/
- public static final int ID_ZONED_HVAC_POWER_ON = 0x4003;
+ public static final int ID_ZONED_HVAC_POWER_ON = 0x15200510;
/**
* Fan speed setpoint, int type
* Fan speed is an integer from 0-n, depending on number of fan speeds available.
*/
- public static final int ID_ZONED_FAN_SPEED_SETPOINT = 0x4004;
+ public static final int ID_ZONED_FAN_SPEED_SETPOINT = 0x15400500;
/**
* Actual fan speed, int type
* Actual fan speed is a read-only value, expressed in RPM.
*/
- public static final int ID_ZONED_FAN_SPEED_RPM = 0x4005;
+ public static final int ID_ZONED_FAN_SPEED_RPM = 0x1540050f;
/**
* Fan direction available, int vector type
* Fan direction is a bitmask of directions available for each zone.
*/
- public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 0x4006;
+ public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 0x15410511;
/**
* Current fan direction setting, int type. The value must be one of the FAN_DIRECTION_AVAILABLE
* values declared above.
*/
- public static final int ID_ZONED_FAN_DIRECTION = 0x4007;
+ public static final int ID_ZONED_FAN_DIRECTION = 0x15400501;
/**
* Seat temperature, int type
* Seat temperature is negative for cooling, positive for heating. Temperature is a
* setting, i.e. -3 to 3 for 3 levels of cooling and 3 levels of heating.
*/
- public static final int ID_ZONED_SEAT_TEMP = 0x4008;
+ public static final int ID_ZONED_SEAT_TEMP = 0x1540050b;
/**
* Air ON, bool type
* true indicates AC is ON.
*/
- public static final int ID_ZONED_AC_ON = 0x4009;
+ public static final int ID_ZONED_AC_ON = 0x15200505;
/**
* Automatic Mode ON, bool type
* true indicates HVAC is in automatic mode
*/
- public static final int ID_ZONED_AUTOMATIC_MODE_ON = 0x400A;
+ public static final int ID_ZONED_AUTOMATIC_MODE_ON = 0x1520050A;
/**
* Air recirculation ON, bool type
* true indicates recirculation is active.
*/
- public static final int ID_ZONED_AIR_RECIRCULATION_ON = 0x400B;
+ public static final int ID_ZONED_AIR_RECIRCULATION_ON = 0x15200508;
/**
* Max AC ON, bool type
* true indicates MAX AC is ON
*/
- public static final int ID_ZONED_MAX_AC_ON = 0x400C;
+ public static final int ID_ZONED_MAX_AC_ON = 0x15200506;
/** Dual zone ON, bool type
* true indicates dual zone mode is ON
*/
- public static final int ID_ZONED_DUAL_ZONE_ON = 0x400D;
+ public static final int ID_ZONED_DUAL_ZONE_ON = 0x15200509;
/**
* Max Defrost ON, bool type
* true indicates max defrost is active.
*/
- public static final int ID_ZONED_MAX_DEFROST_ON = 0x400E;
+ public static final int ID_ZONED_MAX_DEFROST_ON = 0x15200507;
/**
* Automatic recirculation mode ON
* true indicates recirculation is in automatic mode
*/
- public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 0x400F;
+ public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 0x15200512;
/**
* Defroster ON, bool type
* Defroster controls are based on window position.
* True indicates the defroster is ON.
*/
- public static final int ID_WINDOW_DEFROSTER_ON = 0x5001;
+ public static final int ID_WINDOW_DEFROSTER_ON = 0x13200504;
/** @hide */
@IntDef({
@@ -194,10 +189,33 @@
ID_ZONED_MAX_DEFROST_ON,
ID_ZONED_HVAC_POWER_ON,
ID_ZONED_HVAC_AUTO_RECIRC_ON,
- ID_WINDOW_DEFROSTER_ON,
+ ID_WINDOW_DEFROSTER_ON
})
@Retention(RetentionPolicy.SOURCE)
public @interface PropertyId {}
+ private final ArraySet<Integer> mHvacPropertyIds = new ArraySet<>(Arrays.asList(new Integer [] {
+ ID_MIRROR_DEFROSTER_ON,
+ ID_STEERING_WHEEL_HEAT,
+ ID_OUTSIDE_AIR_TEMP,
+ ID_TEMPERATURE_DISPLAY_UNITS,
+ ID_ZONED_TEMP_SETPOINT,
+ ID_ZONED_TEMP_ACTUAL,
+ ID_ZONED_FAN_SPEED_SETPOINT,
+ ID_ZONED_FAN_SPEED_RPM,
+ ID_ZONED_FAN_DIRECTION_AVAILABLE,
+ ID_ZONED_FAN_DIRECTION,
+ ID_ZONED_SEAT_TEMP,
+ ID_ZONED_AC_ON,
+ ID_ZONED_AUTOMATIC_MODE_ON,
+ ID_ZONED_AIR_RECIRCULATION_ON,
+ ID_ZONED_MAX_AC_ON,
+ ID_ZONED_DUAL_ZONE_ON,
+ ID_ZONED_MAX_DEFROST_ON,
+ ID_ZONED_HVAC_POWER_ON,
+ ID_ZONED_HVAC_AUTO_RECIRC_ON,
+ ID_WINDOW_DEFROSTER_ON
+ }));
+
/**
* Represents fan direction when air flows through face directed vents.
@@ -234,7 +252,8 @@
void onErrorEvent(@PropertyId int propertyId, int zone);
}
- private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback {
+ private static class CarPropertyEventListenerToBase implements
+ CarPropertyManager.CarPropertyEventListener {
private final WeakReference<CarHvacManager> mManager;
public CarPropertyEventListenerToBase(CarHvacManager manager) {
@@ -292,28 +311,22 @@
* @hide
*/
public CarHvacManager(IBinder service, Context context, Handler handler) {
- mMgr = new CarPropertyManagerBase(service, handler, DBG, TAG);
+ mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
-
/**
- * Determine if a property is zoned or not.
- * @param propertyId
- * @return true if property is a zoned type.
- */
- public static boolean isZonedProperty(@PropertyId int propertyId) {
- return propertyId > ID_MAX_GLOBAL_PROPERTY_ID;
- }
-
- /**
- * Implement wrappers for contained CarPropertyManagerBase object
+ * Implement wrappers for contained CarPropertyManager object
* @param callback
* @throws CarNotConnectedException
*/
- public synchronized void registerCallback(CarHvacEventCallback callback) throws
- CarNotConnectedException {
+ public synchronized void registerCallback(CarHvacEventCallback callback)
+ throws CarNotConnectedException {
if (mCallbacks.isEmpty()) {
mListenerToBase = new CarPropertyEventListenerToBase(this);
- mMgr.registerCallback(mListenerToBase);
+ }
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
}
@@ -325,8 +338,17 @@
*/
public synchronized void unregisterCallback(CarHvacEventCallback callback) {
mCallbacks.remove(callback);
+ try {
+ List<CarPropertyConfig> configs = getPropertyList();
+ for (CarPropertyConfig c : configs) {
+ // Register each individual propertyId
+ mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "getPropertyList exception ", e);
+ }
if (mCallbacks.isEmpty()) {
- mMgr.unregisterCallback();
+ mCarPropertyMgr.unregisterListener(mListenerToBase);
mListenerToBase = null;
}
}
@@ -337,7 +359,7 @@
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
- return mMgr.getPropertyList();
+ return mCarPropertyMgr.getPropertyList(mHvacPropertyIds);
}
/**
@@ -346,7 +368,7 @@
*/
public boolean isPropertyAvailable(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.isPropertyAvailable(propertyId, area);
+ return mCarPropertyMgr.isPropertyAvailable(propertyId, area);
}
/**
@@ -358,7 +380,7 @@
*/
public boolean getBooleanProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getBooleanProperty(propertyId, area);
+ return mCarPropertyMgr.getBooleanProperty(propertyId, area);
}
/**
@@ -370,7 +392,7 @@
*/
public float getFloatProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getFloatProperty(propertyId, area);
+ return mCarPropertyMgr.getFloatProperty(propertyId, area);
}
/**
@@ -382,7 +404,7 @@
*/
public int getIntProperty(@PropertyId int propertyId, int area)
throws CarNotConnectedException {
- return mMgr.getIntProperty(propertyId, area);
+ return mCarPropertyMgr.getIntProperty(propertyId, area);
}
/**
@@ -394,7 +416,9 @@
*/
public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val)
throws CarNotConnectedException {
- mMgr.setBooleanProperty(propertyId, area, val);
+ if (mHvacPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
+ }
}
/**
@@ -406,7 +430,9 @@
*/
public void setFloatProperty(@PropertyId int propertyId, int area, float val)
throws CarNotConnectedException {
- mMgr.setFloatProperty(propertyId, area, val);
+ if (mHvacPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setFloatProperty(propertyId, area, val);
+ }
}
/**
@@ -418,12 +444,13 @@
*/
public void setIntProperty(@PropertyId int propertyId, int area, int val)
throws CarNotConnectedException {
- mMgr.setIntProperty(propertyId, area, val);
+ if (mHvacPropertyIds.contains(propertyId)) {
+ mCarPropertyMgr.setIntProperty(propertyId, area, val);
+ }
}
/** @hide */
- @Override
public void onCarDisconnected() {
- mMgr.onCarDisconnected();
+ mCarPropertyMgr.onCarDisconnected();
}
}
diff --git a/car-lib/src/android/car/hardware/property/CarPropertyManager.java b/car-lib/src/android/car/hardware/property/CarPropertyManager.java
new file mode 100644
index 0000000..d59ce58
--- /dev/null
+++ b/car-lib/src/android/car/hardware/property/CarPropertyManager.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2018 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 android.car.hardware.property;
+
+import static java.lang.Integer.toHexString;
+
+import android.car.CarApiUtil;
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.car.internal.CarRatedListeners2;
+import com.android.car.internal.SingleMessageHandler;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+
+/**
+ * API for creating Car*Manager
+ * @hide
+ */
+public class CarPropertyManager implements CarManagerBase {
+ private final boolean mDbg;
+ private final SingleMessageHandler<CarPropertyEvent> mHandler;
+ private final ICarProperty mService;
+ private final String mTag;
+ private static final int MSG_GENERIC_EVENT = 0;
+
+ private CarPropertyEventListenerToService mCarPropertyEventToService;
+
+
+ /** Record of locally active properties. Key is propertyId */
+ private final SparseArray<CarPropertyListeners> mActivePropertyListener =
+ new SparseArray<>();
+
+ /** Callback functions for property events */
+ public interface CarPropertyEventListener {
+ /** Called when a property is updated */
+ void onChangeEvent(CarPropertyValue value);
+
+ /** Called when an error is detected with a property */
+ void onErrorEvent(int propId, int zone);
+ }
+
+ /**
+ * Get an instance of the CarPropertyManager.
+ */
+ public CarPropertyManager(IBinder service, Handler handler, boolean dbg, String tag) {
+ mDbg = dbg;
+ mTag = tag;
+ mService = ICarProperty.Stub.asInterface(service);
+ mHandler = new SingleMessageHandler<CarPropertyEvent>(handler.getLooper(),
+ MSG_GENERIC_EVENT) {
+ @Override
+ protected void handleEvent(CarPropertyEvent event) {
+ CarPropertyListeners listeners;
+ synchronized (mActivePropertyListener) {
+ listeners = mActivePropertyListener.get(
+ event.getCarPropertyValue().getPropertyId());
+ }
+ if (listeners != null) {
+ switch (event.getEventType()) {
+ case CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE:
+ listeners.onPropertyChanged(event);
+ break;
+ case CarPropertyEvent.PROPERTY_EVENT_ERROR:
+ listeners.onErrorEvent(event);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+ };
+ }
+
+ /** Use to register or update Callback for properties */
+ public boolean registerListener(CarPropertyEventListener listener, int propertyId, float rate)
+ throws CarNotConnectedException {
+ synchronized (mActivePropertyListener) {
+ if (mCarPropertyEventToService == null) {
+ mCarPropertyEventToService = new CarPropertyEventListenerToService(this);
+ }
+ boolean needsServerUpdate = false;
+ CarPropertyListeners listeners;
+ listeners = mActivePropertyListener.get(propertyId);
+ if (listeners == null) {
+ listeners = new CarPropertyListeners(rate);
+ mActivePropertyListener.put(propertyId, listeners);
+ needsServerUpdate = true;
+ }
+ if (listeners.addAndUpdateRate(listener, rate)) {
+ needsServerUpdate = true;
+ }
+ if (needsServerUpdate) {
+ if (!registerOrUpdatePropertyListener(propertyId, rate)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean registerOrUpdatePropertyListener(int propertyId, float rate)
+ throws CarNotConnectedException {
+ try {
+ mService.registerListener(propertyId, rate, mCarPropertyEventToService);
+ } catch (IllegalStateException e) {
+ CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
+ } catch (RemoteException e) {
+ throw new CarNotConnectedException(e);
+ }
+ return true;
+ }
+
+ private class CarPropertyEventListenerToService extends ICarPropertyEventListener.Stub{
+ private final WeakReference<CarPropertyManager> mMgr;
+
+ CarPropertyEventListenerToService(CarPropertyManager mgr) {
+ mMgr = new WeakReference<>(mgr);
+ }
+
+ @Override
+ public void onEvent(List<CarPropertyEvent> events) throws RemoteException {
+ CarPropertyManager manager = mMgr.get();
+ if (manager != null) {
+ manager.handleEvent(events);
+ }
+ }
+ }
+
+ private void handleEvent(List<CarPropertyEvent> events) {
+ mHandler.sendEvents(events);
+ }
+
+ /**
+ * Stop getting sensor update for the given listener. If there are multiple registrations for
+ * this listener, all listening will be stopped.
+ * @param listener
+ */
+ public void unregisterListener(CarPropertyEventListener listener) {
+ synchronized (mActivePropertyListener) {
+ for (int i = 0; i < mActivePropertyListener.size(); i++) {
+ doUnregisterListenerLocked(listener, mActivePropertyListener.keyAt(i));
+ }
+ }
+ }
+
+ /**
+ * Stop getting sensor update for the given listener and sensor. If the same listener is used
+ * for other sensors, those subscriptions will not be affected.
+ * @param listener
+ * @param propertyId
+ */
+ public void unregisterListener(CarPropertyEventListener listener, int propertyId) {
+ synchronized (mActivePropertyListener) {
+ doUnregisterListenerLocked(listener, propertyId);
+ }
+ }
+
+ private void doUnregisterListenerLocked(CarPropertyEventListener listener, int propertyId) {
+ CarPropertyListeners listeners = mActivePropertyListener.get(propertyId);
+ if (listeners != null) {
+ boolean needsServerUpdate = false;
+ if (listeners.contains(listener)) {
+ needsServerUpdate = listeners.remove(listener);
+ }
+ if (listeners.isEmpty()) {
+ try {
+ mService.unregisterListener(propertyId, mCarPropertyEventToService);
+ } catch (RemoteException e) {
+ //ignore
+ }
+ mActivePropertyListener.remove(propertyId);
+ } else if (needsServerUpdate) {
+ try {
+ registerOrUpdatePropertyListener(propertyId, listeners.getRate());
+ } catch (CarNotConnectedException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the list of properties implemented by this car.
+ *
+ * @return Caller must check the property type and typecast to the appropriate subclass
+ * (CarPropertyBooleanProperty, CarPropertyFloatProperty, CarrPropertyIntProperty)
+ */
+ public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
+ try {
+ return mService.getPropertyList();
+ } catch (RemoteException e) {
+ Log.e(mTag, "getPropertyList exception ", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns the list of properties implemented by this car in given property id list.
+ *
+ * @return Caller must check the property type and typecast to the appropriate subclass
+ * (CarPropertyBooleanProperty, CarPropertyFloatProperty, CarrPropertyIntProperty)
+ */
+ public List<CarPropertyConfig> getPropertyList(ArraySet<Integer> propertyIds)
+ throws CarNotConnectedException {
+ try {
+ List<CarPropertyConfig> configs = new ArrayList<>();
+ for (CarPropertyConfig c : mService.getPropertyList()) {
+ if (propertyIds.contains(c.getPropertyId())) {
+ configs.add(c);
+ }
+ }
+ return configs;
+ } catch (RemoteException e) {
+ Log.e(mTag, "getPropertyList exception ", e);
+ throw new CarNotConnectedException(e);
+ }
+
+ }
+
+ /**
+ * Check whether a given property is available or disabled based on the car's current state.
+ * @return true if STATUS_AVAILABLE, false otherwise (eg STATUS_UNAVAILABLE)
+ * @throws CarNotConnectedException
+ */
+ public boolean isPropertyAvailable(int propId, int area) throws CarNotConnectedException {
+ try {
+ CarPropertyValue propValue = mService.getProperty(propId, area);
+ return (propValue != null)
+ && (propValue.getStatus() == CarPropertyValue.STATUS_AVAILABLE);
+ } catch (RemoteException e) {
+ Log.e(mTag, "isPropertyAvailable failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Returns value of a bool property
+ *
+ * @param prop Property ID to get
+ * @param area Area of the property to get
+ */
+ public boolean getBooleanProperty(int prop, int area) throws CarNotConnectedException {
+ CarPropertyValue<Boolean> carProp = getProperty(Boolean.class, prop, area);
+ return carProp != null ? carProp.getValue() : false;
+ }
+
+ /**
+ * Returns value of a float property
+ *
+ * @param prop Property ID to get
+ * @param area Area of the property to get
+ */
+ public float getFloatProperty(int prop, int area) throws CarNotConnectedException {
+ CarPropertyValue<Float> carProp = getProperty(Float.class, prop, area);
+ return carProp != null ? carProp.getValue() : 0f;
+ }
+
+ /**
+ * Returns value of a integer property
+ *
+ * @param prop Property ID to get
+ * @param area Zone of the property to get
+ */
+ public int getIntProperty(int prop, int area) throws CarNotConnectedException {
+ CarPropertyValue<Integer> carProp = getProperty(Integer.class, prop, area);
+ return carProp != null ? carProp.getValue() : 0;
+ }
+
+ /** Return CarPropertyValue */
+ @SuppressWarnings("unchecked")
+ public <E> CarPropertyValue<E> getProperty(Class<E> clazz, int propId, int area)
+ throws CarNotConnectedException {
+ if (mDbg) {
+ Log.d(mTag, "getProperty, propId: 0x" + toHexString(propId)
+ + ", area: 0x" + toHexString(area) + ", class: " + clazz);
+ }
+ try {
+ CarPropertyValue<E> propVal = mService.getProperty(propId, area);
+ if (propVal != null && propVal.getValue() != null) {
+ Class<?> actualClass = propVal.getValue().getClass();
+ if (actualClass != clazz) {
+ throw new IllegalArgumentException("Invalid property type. " + "Expected: "
+ + clazz + ", but was: " + actualClass);
+ }
+ }
+ return propVal;
+ } catch (RemoteException e) {
+ Log.e(mTag, "getProperty failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /** Return raw CarPropertyValue */
+ public <E> CarPropertyValue<E> getProperty(int propId, int area)
+ throws CarNotConnectedException {
+ try {
+ CarPropertyValue<E> propVal = mService.getProperty(propId, area);
+ return propVal;
+ } catch (RemoteException e) {
+ Log.e(mTag, "getProperty failed with " + e.toString()
+ + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /** Set CarPropertyValue */
+ public <E> void setProperty(Class<E> clazz, int propId, int area, E val)
+ throws CarNotConnectedException {
+ if (mDbg) {
+ Log.d(mTag, "setProperty, propId: 0x" + toHexString(propId)
+ + ", area: 0x" + toHexString(area) + ", class: " + clazz + ", val: " + val);
+ }
+ try {
+ mService.setProperty(new CarPropertyValue<>(propId, area, val));
+ } catch (RemoteException e) {
+ Log.e(mTag, "setProperty failed with " + e.toString(), e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
+ * Modifies a property. If the property modification doesn't occur, an error event shall be
+ * generated and propagated back to the application.
+ *
+ * @param prop Property ID to modify
+ * @param area Area to apply the modification.
+ * @param val Value to set
+ */
+ public void setBooleanProperty(int prop, int area, boolean val)
+ throws CarNotConnectedException {
+ setProperty(Boolean.class, prop, area, val);
+ }
+
+ /** Set float value of property*/
+ public void setFloatProperty(int prop, int area, float val) throws CarNotConnectedException {
+ setProperty(Float.class, prop, area, val);
+ }
+ /** Set int value of property*/
+ public void setIntProperty(int prop, int area, int val) throws CarNotConnectedException {
+ setProperty(Integer.class, prop, area, val);
+ }
+
+
+ private class CarPropertyListeners extends CarRatedListeners2<CarPropertyEventListener> {
+ CarPropertyListeners(float rate) {
+ super(rate);
+ }
+ void onPropertyChanged(final CarPropertyEvent event) {
+ // throw away old sensor data as oneway binder call can change order.
+ long updateTime = event.getCarPropertyValue().getTimestamp();
+ if (updateTime < mLastUpdateTime) {
+ Log.w(mTag, "dropping old property data");
+ return;
+ }
+ mLastUpdateTime = updateTime;
+ List<CarPropertyEventListener> listeners;
+ synchronized (mActivePropertyListener) {
+ listeners = new ArrayList<>(getListeners());
+ }
+ listeners.forEach(new Consumer<CarPropertyEventListener>() {
+ @Override
+ public void accept(CarPropertyEventListener listener) {
+ listener.onChangeEvent(event.getCarPropertyValue());
+ }
+ });
+ }
+
+ void onErrorEvent(final CarPropertyEvent event) {
+ List<CarPropertyEventListener> listeners;
+ CarPropertyValue value = event.getCarPropertyValue();
+ synchronized (mActivePropertyListener) {
+ listeners = new ArrayList<>(getListeners());
+ }
+ listeners.forEach(new Consumer<CarPropertyEventListener>() {
+ @Override
+ public void accept(CarPropertyEventListener listener) {
+ listener.onErrorEvent(value.getPropertyId(), value.getAreaId());
+ }
+ });
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void onCarDisconnected() {
+ synchronized (mActivePropertyListener) {
+ mActivePropertyListener.clear();
+ mCarPropertyEventToService = null;
+ }
+ }
+}
diff --git a/car-lib/src/android/car/hardware/property/CarPropertyManagerBase.java b/car-lib/src/android/car/hardware/property/CarPropertyManagerBase.java
deleted file mode 100644
index 002284d..0000000
--- a/car-lib/src/android/car/hardware/property/CarPropertyManagerBase.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.car.hardware.property;
-
-import static java.lang.Integer.toHexString;
-
-import android.annotation.Nullable;
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.hardware.CarPropertyConfig;
-import android.car.hardware.CarPropertyValue;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.lang.ref.WeakReference;
-import java.util.List;
-
-/**
- * API for creating Car*Manager
- * @hide
- */
-public class CarPropertyManagerBase {
- private final boolean mDbg;
- private final Handler mHandler;
- private final ICarProperty mService;
- private final String mTag;
-
- @GuardedBy("mLock")
- private ICarPropertyEventListener mListenerToService;
- @GuardedBy("mLock")
- private CarPropertyEventCallback mCallback;
-
- private final Object mLock = new Object();
-
- /** Callback functions for property events */
- public interface CarPropertyEventCallback {
- /** Called when a property is updated */
- void onChangeEvent(CarPropertyValue value);
-
- /** Called when an error is detected with a property */
- void onErrorEvent(int propertyId, int zone);
- }
-
- private final static class EventCallbackHandler extends Handler {
- /** Constants handled in the handler */
- private static final int MSG_GENERIC_EVENT = 0;
-
- private final WeakReference<CarPropertyManagerBase> mMgr;
-
- EventCallbackHandler(CarPropertyManagerBase mgr, Looper looper) {
- super(looper);
- mMgr = new WeakReference<>(mgr);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_GENERIC_EVENT:
- CarPropertyManagerBase mgr = mMgr.get();
- if (mgr != null) {
- mgr.dispatchEventToClient((CarPropertyEvent) msg.obj);
- }
- break;
- default:
- Log.e("EventtCallbackHandler", "Event type not handled: " + msg);
- break;
- }
- }
- }
-
- /**
- * Get an instance of the CarPropertyManagerBase.
- */
- public CarPropertyManagerBase(IBinder service, Handler handler, boolean dbg,
- String tag) {
- mDbg = dbg;
- mTag = tag;
- mService = ICarProperty.Stub.asInterface(service);
- mHandler = new EventCallbackHandler(this, handler.getLooper());
- }
-
- public void registerCallback(CarPropertyEventCallback callback)
- throws CarNotConnectedException {
- synchronized (mLock) {
- if (mCallback != null) {
- throw new IllegalStateException("Callback is already registered.");
- }
-
- mCallback = callback;
- mListenerToService = new ICarPropertyEventListener.Stub() {
- @Override
- public void onEvent(CarPropertyEvent event) throws RemoteException {
- handleEvent(event);
- }
- };
- }
-
- try {
- mService.registerListener(mListenerToService);
- } catch (RemoteException ex) {
- Log.e(mTag, "Could not connect: ", ex);
- throw new CarNotConnectedException(ex);
- } catch (IllegalStateException ex) {
- Car.checkCarNotConnectedExceptionFromCarService(ex);
- }
- }
-
- public void unregisterCallback() {
- ICarPropertyEventListener listenerToService;
- synchronized (mLock) {
- listenerToService = mListenerToService;
- mCallback = null;
- mListenerToService = null;
- }
-
- if (listenerToService == null) {
- Log.w(mTag, "unregisterListener: listener was not registered");
- return;
- }
-
- try {
- mService.unregisterListener(listenerToService);
- } catch (RemoteException ex) {
- Log.e(mTag, "Failed to unregister listener", ex);
- //ignore
- } catch (IllegalStateException ex) {
- Car.hideCarNotConnectedExceptionFromCarService(ex);
- }
- }
-
- /**
- * Returns the list of properties implemented by this car.
- *
- * @return Caller must check the property type and typecast to the appropriate subclass
- * (CarPropertyBooleanProperty, CarPropertyFloatProperty, CarrPropertyIntProperty)
- */
- public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
- try {
- return mService.getPropertyList();
- } catch (RemoteException e) {
- Log.e(mTag, "Exception in getPropertyList", e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Check whether a given property is available or disabled based on the car's current state.
- * @return true if STATUS_AVAILABLE, false otherwise (eg STATUS_UNAVAILABLE)
- * @throws CarNotConnectedException
- */
- public boolean isPropertyAvailable(int propId, int area) throws CarNotConnectedException {
- try {
- CarPropertyValue propValue = mService.getProperty(propId, area);
- return (propValue != null) &&
- (propValue.getStatus() == CarPropertyValue.STATUS_AVAILABLE);
- } catch (RemoteException e) {
- Log.e(mTag, "isPropertyAvailable failed with " + e.toString()
- + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Returns value of a bool property
- *
- * @param prop Property ID to get
- * @param area Area of the property to get
- */
- public boolean getBooleanProperty(int prop, int area) throws CarNotConnectedException {
- CarPropertyValue<Boolean> carProp = getProperty(Boolean.class, prop, area);
- return carProp != null ? carProp.getValue() : false;
- }
-
- /**
- * Returns value of a float property
- *
- * @param prop Property ID to get
- * @param area Area of the property to get
- */
- public float getFloatProperty(int prop, int area) throws CarNotConnectedException {
- CarPropertyValue<Float> carProp = getProperty(Float.class, prop, area);
- return carProp != null ? carProp.getValue() : 0f;
- }
-
- /**
- * Returns value of a integer property
- *
- * @param prop Property ID to get
- * @param area Zone of the property to get
- */
- public int getIntProperty(int prop, int area) throws CarNotConnectedException {
- CarPropertyValue<Integer> carProp = getProperty(Integer.class, prop, area);
- return carProp != null ? carProp.getValue() : 0;
- }
-
- @Nullable
- @SuppressWarnings("unchecked")
- public <E> CarPropertyValue<E> getProperty(Class<E> clazz, int propId, int area)
- throws CarNotConnectedException {
- if (mDbg) {
- Log.d(mTag, "getProperty, propId: 0x" + toHexString(propId)
- + ", area: 0x" + toHexString(area) + ", class: " + clazz);
- }
- try {
- CarPropertyValue<E> propVal = mService.getProperty(propId, area);
- if (propVal != null && propVal.getValue() != null) {
- Class<?> actualClass = propVal.getValue().getClass();
- if (actualClass != clazz) {
- throw new IllegalArgumentException("Invalid property type. " + "Expected: "
- + clazz + ", but was: " + actualClass);
- }
- }
- return propVal;
- } catch (RemoteException e) {
- Log.e(mTag, "getProperty failed with " + e.toString()
- + ", propId: 0x" + toHexString(propId) + ", area: 0x" + toHexString(area), e);
- throw new CarNotConnectedException(e);
- }
- }
-
- public <E> void setProperty(Class<E> clazz, int propId, int area, E val)
- throws CarNotConnectedException {
- if (mDbg) {
- Log.d(mTag, "setProperty, propId: 0x" + toHexString(propId)
- + ", area: 0x" + toHexString(area) + ", class: " + clazz + ", val: " + val);
- }
- try {
- mService.setProperty(new CarPropertyValue<>(propId, area, val));
- } catch (RemoteException e) {
- Log.e(mTag, "setProperty failed with " + e.toString(), e);
- throw new CarNotConnectedException(e);
- }
- }
-
- /**
- * Modifies a property. If the property modification doesn't occur, an error event shall be
- * generated and propagated back to the application.
- *
- * @param prop Property ID to modify
- * @param area Area to apply the modification.
- * @param val Value to set
- */
- public void setBooleanProperty(int prop, int area, boolean val)
- throws CarNotConnectedException {
- setProperty(Boolean.class, prop, area, val);
- }
-
- public void setFloatProperty(int prop, int area, float val) throws CarNotConnectedException {
- setProperty(Float.class, prop, area, val);
- }
-
- public void setIntProperty(int prop, int area, int val) throws CarNotConnectedException {
- setProperty(Integer.class, prop, area, val);
- }
-
- private void dispatchEventToClient(CarPropertyEvent event) {
- CarPropertyEventCallback listener;
- synchronized (mLock) {
- listener = mCallback;
- }
-
- if (listener == null) {
- Log.e(mTag, "Listener died, not dispatching event.");
- return;
- }
-
- CarPropertyValue propVal = event.getCarPropertyValue();
- switch(event.getEventType()) {
- case CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE:
- listener.onChangeEvent(propVal);
- break;
- case CarPropertyEvent.PROPERTY_EVENT_ERROR:
- listener.onErrorEvent(propVal.getPropertyId(), propVal.getAreaId());
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- private void handleEvent(CarPropertyEvent event) {
- mHandler.sendMessage(mHandler.obtainMessage(EventCallbackHandler.MSG_GENERIC_EVENT, event));
- }
-
- /** @hide */
- public void onCarDisconnected() {
-
- ICarPropertyEventListener listenerToService;
- synchronized (mLock) {
- listenerToService = mListenerToService;
- }
-
- if (listenerToService != null) {
- unregisterCallback();
- }
- }
-}
diff --git a/car-lib/src/android/car/hardware/property/ICarProperty.aidl b/car-lib/src/android/car/hardware/property/ICarProperty.aidl
index 2121ebb..3e7e5c9 100644
--- a/car-lib/src/android/car/hardware/property/ICarProperty.aidl
+++ b/car-lib/src/android/car/hardware/property/ICarProperty.aidl
@@ -25,9 +25,9 @@
*/
interface ICarProperty {
- void registerListener(in ICarPropertyEventListener callback) = 0;
+ void registerListener(int propId, float rate, in ICarPropertyEventListener callback) = 0;
- void unregisterListener(in ICarPropertyEventListener callback) = 1;
+ void unregisterListener(int propId, in ICarPropertyEventListener callback) = 1;
List<CarPropertyConfig> getPropertyList() = 2;
diff --git a/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl b/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl
index b0d57fc..ebda47c 100644
--- a/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl
+++ b/car-lib/src/android/car/hardware/property/ICarPropertyEventListener.aidl
@@ -28,6 +28,6 @@
* Called when an event is triggered in response to one of the calls (such as on tune) or
* asynchronously (such as on announcement).
*/
- void onEvent(in CarPropertyEvent event) = 0;
+ void onEvent(in List<CarPropertyEvent> events) = 0;
}
diff --git a/car-lib/src/com/android/car/internal/CarRatedListeners2.java b/car-lib/src/com/android/car/internal/CarRatedListeners2.java
new file mode 100644
index 0000000..8708cd4
--- /dev/null
+++ b/car-lib/src/com/android/car/internal/CarRatedListeners2.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 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.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Represent listeners for a property grouped by their rate.
+ * @param <EventListenerType>
+ * @hide
+ */
+public class CarRatedListeners2<EventListenerType> {
+ private final Map<EventListenerType, Float> mListenersToRate = new HashMap<>(4);
+
+ private float mUpdateRate;
+
+ protected long mLastUpdateTime = -1;
+
+ protected CarRatedListeners2(float rate) {
+ mUpdateRate = rate;
+ }
+
+ /** Check listener */
+ public boolean contains(EventListenerType listener) {
+ return mListenersToRate.containsKey(listener);
+ }
+ /** Return current rate after updating */
+ public float getRate() {
+ return mUpdateRate;
+ }
+
+ /**
+ * Remove given listener from the list and update rate if necessary.
+ *
+ * @param listener
+ * @return true if rate was updated. Otherwise, returns false.
+ */
+ public boolean remove(EventListenerType listener) {
+ mListenersToRate.remove(listener);
+ if (mListenersToRate.isEmpty()) {
+ return false;
+ }
+ Float updateRate = Collections.max(mListenersToRate.values());
+ if (updateRate != mUpdateRate) {
+ mUpdateRate = updateRate;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isEmpty() {
+ return mListenersToRate.isEmpty();
+ }
+
+ /**
+ * Add given listener to the list and update rate if necessary.
+ *
+ * @param listener if null, add part is skipped.
+ * @param updateRate
+ * @return true if rate was updated. Otherwise, returns false.
+ */
+ public boolean addAndUpdateRate(EventListenerType listener, float updateRate) {
+ Float oldUpdateRate = mListenersToRate.put(listener, updateRate);
+ if (mUpdateRate < updateRate) {
+ mUpdateRate = updateRate;
+ return true;
+ } else if (oldUpdateRate != null && oldUpdateRate == mUpdateRate) {
+ mUpdateRate = Collections.max(mListenersToRate.values());
+ }
+ return false;
+ }
+
+ public Collection<EventListenerType> getListeners() {
+ return mListenersToRate.keySet();
+ }
+}
+
diff --git a/car-lib/src/com/android/car/internal/SingleMessageHandler.java b/car-lib/src/com/android/car/internal/SingleMessageHandler.java
index f61309c..57788a7 100644
--- a/car-lib/src/com/android/car/internal/SingleMessageHandler.java
+++ b/car-lib/src/com/android/car/internal/SingleMessageHandler.java
@@ -20,6 +20,7 @@
import android.os.Handler.Callback;
import android.os.Looper;
import android.os.Message;
+
import java.util.List;
import java.util.function.Consumer;
@@ -60,4 +61,5 @@
public void sendEvents(List<EventType> events) {
mHandler.sendMessage(mHandler.obtainMessage(mHandledMessageWhat, events));
}
+
}