Merge "Send freeze frames via diagnostic_injector"
diff --git a/car-lib/api/1.txt b/car-lib/api/1.txt
new file mode 100644
index 0000000..556aaae
--- /dev/null
+++ b/car-lib/api/1.txt
@@ -0,0 +1,290 @@
+package android.car {
+
+ public final class Car {
+ method public void connect() throws java.lang.IllegalStateException;
+ method public static android.car.Car createCar(android.content.Context, android.content.ServiceConnection, android.os.Handler);
+ method public static android.car.Car createCar(android.content.Context, android.content.ServiceConnection);
+ method public void disconnect();
+ method public int getCarConnectionType();
+ method public java.lang.Object getCarManager(java.lang.String) throws android.car.CarNotConnectedException;
+ method public boolean isConnected();
+ method public boolean isConnecting();
+ field public static final java.lang.String APP_FOCUS_SERVICE = "app_focus";
+ field public static final java.lang.String AUDIO_SERVICE = "audio";
+ field public static final int CONNECTION_TYPE_EMBEDDED = 5; // 0x5
+ field public static final java.lang.String INFO_SERVICE = "info";
+ field public static final java.lang.String PACKAGE_SERVICE = "package";
+ field public static final java.lang.String PERMISSION_CAR_CONTROL_AUDIO_VOLUME = "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
+ field public static final java.lang.String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
+ field public static final java.lang.String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
+ field public static final java.lang.String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
+ field public static final java.lang.String SENSOR_SERVICE = "sensor";
+ field public static final int VERSION = 1; // 0x1
+ }
+
+ public final class CarAppFocusManager {
+ method public void abandonAppFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback, int);
+ method public void abandonAppFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback);
+ method public void addFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener, int) throws android.car.CarNotConnectedException;
+ method public boolean isOwningFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback, int) throws android.car.CarNotConnectedException;
+ method public void removeFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener, int);
+ method public void removeFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener);
+ method public int requestAppFocus(int, android.car.CarAppFocusManager.OnAppFocusOwnershipCallback) throws android.car.CarNotConnectedException, java.lang.SecurityException;
+ field public static final int APP_FOCUS_REQUEST_FAILED = 0; // 0x0
+ field public static final int APP_FOCUS_REQUEST_SUCCEEDED = 1; // 0x1
+ field public static final int APP_FOCUS_TYPE_NAVIGATION = 1; // 0x1
+ field public static final int APP_FOCUS_TYPE_VOICE_COMMAND = 2; // 0x2
+ }
+
+ public static abstract interface CarAppFocusManager.OnAppFocusChangedListener {
+ method public abstract void onAppFocusChanged(int, boolean);
+ }
+
+ public static abstract interface CarAppFocusManager.OnAppFocusOwnershipCallback {
+ method public abstract void onAppFocusOwnershipGranted(int);
+ method public abstract void onAppFocusOwnershipLost(int);
+ }
+
+ public final class CarInfoManager {
+ method public java.lang.String getManufacturer() throws android.car.CarNotConnectedException;
+ method public java.lang.String getModel() throws android.car.CarNotConnectedException;
+ method public java.lang.String getModelYear() throws android.car.CarNotConnectedException;
+ method public java.lang.String getVehicleId() throws android.car.CarNotConnectedException;
+ }
+
+ public class CarNotConnectedException extends java.lang.Exception {
+ ctor public CarNotConnectedException();
+ ctor public CarNotConnectedException(java.lang.String);
+ ctor public CarNotConnectedException(java.lang.String, java.lang.Throwable);
+ ctor public CarNotConnectedException(java.lang.Exception);
+ }
+
+}
+
+package android.car.app.menu {
+
+ public abstract class CarMenuCallbacks {
+ ctor public CarMenuCallbacks();
+ method public abstract android.car.app.menu.RootMenu getRootMenu(android.os.Bundle);
+ method public abstract void onCarMenuClosed();
+ method public abstract void onCarMenuClosing();
+ method public abstract void onCarMenuOpened();
+ method public abstract void onCarMenuOpening();
+ method public abstract void onItemClicked(java.lang.String);
+ method public abstract boolean onItemLongClicked(java.lang.String);
+ method public abstract boolean onMenuClicked();
+ method public abstract void subscribe(java.lang.String, android.car.app.menu.SubscriptionCallbacks);
+ method public abstract void unsubscribe(java.lang.String, android.car.app.menu.SubscriptionCallbacks);
+ }
+
+ public class CarMenuConstants {
+ ctor public CarMenuConstants();
+ }
+
+ public static class CarMenuConstants.MenuItemConstants {
+ ctor public CarMenuConstants.MenuItemConstants();
+ field public static final int FLAG_BROWSABLE = 1; // 0x1
+ field public static final int FLAG_FIRSTITEM = 2; // 0x2
+ field public static final java.lang.String KEY_EMPTY_PLACEHOLDER = "android.car.app.menu.empty_placeholder";
+ field public static final java.lang.String KEY_FLAGS = "android.car.app.menu.flags";
+ field public static final java.lang.String KEY_ID = "android.car.app.menu.id";
+ field public static final java.lang.String KEY_LEFTICON = "android.car.app.menu.leftIcon";
+ field public static final java.lang.String KEY_REMOTEVIEWS = "android.car.app.menu.remoteViews";
+ field public static final java.lang.String KEY_RIGHTICON = "android.car.app.menu.rightIcon";
+ field public static final java.lang.String KEY_RIGHTTEXT = "android.car.app.menu.rightText";
+ field public static final java.lang.String KEY_TEXT = "android.car.app.menu.text";
+ field public static final java.lang.String KEY_TITLE = "android.car.app.menu.title";
+ field public static final java.lang.String KEY_WIDGET = "android.car.app.menu.widget";
+ field public static final java.lang.String KEY_WIDGET_STATE = "android.car.app.menu.widget_state";
+ field public static final int WIDGET_CHECKBOX = 1; // 0x1
+ field public static final int WIDGET_TEXT_VIEW = 2; // 0x2
+ }
+
+ public static abstract class CarMenuConstants.MenuItemConstants.MenuItemFlags implements java.lang.annotation.Annotation {
+ }
+
+ public static abstract class CarMenuConstants.MenuItemConstants.WidgetTypes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class CarUiEntry {
+ ctor public CarUiEntry(android.content.Context, android.content.Context);
+ method public abstract void closeDrawer();
+ method public abstract android.view.View getContentView();
+ method public abstract int getFragmentContainerId();
+ method public abstract java.lang.CharSequence getSearchBoxText();
+ method public abstract void hideMenuButton();
+ method public abstract void hideTitle();
+ method public abstract void onPause();
+ method public abstract void onRestoreInstanceState(android.os.Bundle);
+ method public abstract void onResume();
+ method public abstract void onSaveInstanceState(android.os.Bundle);
+ method public abstract void onStart();
+ method public abstract void onStop();
+ method public abstract void openDrawer();
+ method public abstract void restoreMenuDrawable();
+ method public abstract void setAutoLightDarkMode();
+ method public abstract void setBackground(android.graphics.Bitmap);
+ method public abstract void setCarMenuCallbacks(android.car.app.menu.CarMenuCallbacks);
+ method public abstract void setDarkMode();
+ method public abstract void setLightMode();
+ method public abstract void setMenuButtonBitmap(android.graphics.Bitmap);
+ method public abstract void setMenuButtonColor(int);
+ method public abstract void setScrimColor(int);
+ method public abstract void setSearchBoxColors(int, int, int, int);
+ method public abstract void setSearchBoxEditListener(android.car.app.menu.SearchBoxEditListener);
+ method public abstract void setSearchBoxEndView(android.view.View);
+ method public abstract void setTitle(java.lang.CharSequence);
+ method public abstract void showMenu(java.lang.String, java.lang.String);
+ method public abstract void showSearchBox(android.view.View.OnClickListener);
+ method public abstract void showTitle();
+ method public abstract void showToast(java.lang.String, long);
+ method public abstract android.widget.EditText startInput(java.lang.String, android.view.View.OnClickListener);
+ method public abstract void stopInput();
+ field protected final android.content.Context mAppContext;
+ field protected final android.content.Context mUiLibContext;
+ }
+
+ public class RootMenu {
+ ctor public RootMenu(java.lang.String);
+ ctor public RootMenu(java.lang.String, android.os.Bundle);
+ method public android.os.Bundle getBundle();
+ method public java.lang.String getId();
+ }
+
+ public abstract class SearchBoxEditListener {
+ ctor public SearchBoxEditListener();
+ method public abstract void onEdit(java.lang.String);
+ method public abstract void onSearch(java.lang.String);
+ }
+
+ public abstract class SubscriptionCallbacks {
+ ctor public SubscriptionCallbacks();
+ method public abstract void onChildChanged(java.lang.String, android.os.Bundle);
+ method public abstract void onChildrenLoaded(java.lang.String, java.util.List<android.os.Bundle>);
+ method public abstract void onError(java.lang.String);
+ }
+
+}
+
+package android.car.content.pm {
+
+ public final class CarPackageManager {
+ method public boolean isActivityAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ method public boolean isServiceAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ }
+
+}
+
+package android.car.hardware {
+
+ public class CarSensorEvent implements android.os.Parcelable {
+ 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 DRIVE_STATUS_FULLY_RESTRICTED = 31; // 0x1f
+ field public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 16; // 0x10
+ field public static final int DRIVE_STATUS_NO_CONFIG = 8; // 0x8
+ field public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 2; // 0x2
+ field public static final int DRIVE_STATUS_NO_VIDEO = 1; // 0x1
+ field public static final int DRIVE_STATUS_NO_VOICE_INPUT = 4; // 0x4
+ field public static final int DRIVE_STATUS_UNRESTRICTED = 0; // 0x0
+ 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 INDEX_ENVIRONMENT_PRESSURE = 1; // 0x1
+ field public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0; // 0x0
+ field public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1; // 0x1
+ field public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0; // 0x0
+ field public static final int INDEX_FUEL_LOW_WARNING = 0; // 0x0
+ field public final float[] floatValues;
+ field public final int[] intValues;
+ field public int sensorType;
+ field public long timestamp;
+ }
+
+ public static class CarSensorEvent.EnvironmentData {
+ field public float pressure;
+ field public float temperature;
+ field public long timestamp;
+ }
+
+ public final class CarSensorManager {
+ method public android.car.hardware.CarSensorEvent getLatestSensorEvent(int) throws android.car.CarNotConnectedException;
+ method public int[] getSupportedSensors() throws android.car.CarNotConnectedException;
+ method public boolean isSensorSupported(int) throws android.car.CarNotConnectedException;
+ method public static boolean isSensorSupported(int[], int);
+ 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_CAR_SPEED = 2; // 0x2
+ field public static final int SENSOR_TYPE_DRIVING_STATUS = 11; // 0xb
+ field public static final int SENSOR_TYPE_ENVIRONMENT = 12; // 0xc
+ 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_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_VENDOR_EXTENSION_END = 1879048191; // 0x6fffffff
+ }
+
+ public static abstract interface CarSensorManager.OnSensorChangedListener {
+ method public abstract void onSensorChanged(android.car.hardware.CarSensorEvent);
+ }
+
+}
+
+package android.car.media {
+
+ public final class CarAudioManager {
+ method public void abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
+ method public android.media.AudioAttributes getAudioAttributesForCarUsage(int) throws android.car.CarNotConnectedException;
+ method public int getStreamMaxVolume(int) throws android.car.CarNotConnectedException;
+ method public int getStreamMinVolume(int) throws android.car.CarNotConnectedException;
+ method public int getStreamVolume(int) throws android.car.CarNotConnectedException;
+ method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
+ method public void setStreamVolume(int, int, int) throws android.car.CarNotConnectedException;
+ field public static final int CAR_AUDIO_USAGE_ALARM = 6; // 0x6
+ field public static final int CAR_AUDIO_USAGE_DEFAULT = 0; // 0x0
+ field public static final int CAR_AUDIO_USAGE_MUSIC = 1; // 0x1
+ field public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3; // 0x3
+ field public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7; // 0x7
+ field public static final int CAR_AUDIO_USAGE_RADIO = 2; // 0x2
+ field public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9; // 0x9
+ field public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8; // 0x8
+ field public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4; // 0x4
+ field public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5; // 0x5
+ }
+
+}
+
+package android.car.settings {
+
+ public class CarSettings {
+ ctor public CarSettings();
+ }
+
+ public static final class CarSettings.Global {
+ ctor public CarSettings.Global();
+ field public static final java.lang.String KEY_GARAGE_MODE_ENABLED = "android.car.GARAGE_MODE_ENABLED";
+ field public static final java.lang.String KEY_GARAGE_MODE_MAINTENANCE_WINDOW = "android.car.GARAGE_MODE_MAINTENANCE_WINDOW";
+ field public static final java.lang.String KEY_GARAGE_MODE_WAKE_UP_TIME = "android.car.GARAGE_MODE_WAKE_UP_TIME";
+ }
+
+}
+
diff --git a/car-lib/api/current.txt b/car-lib/api/current.txt
index 72658fc..fb94b19 100644
--- a/car-lib/api/current.txt
+++ b/car-lib/api/current.txt
@@ -19,7 +19,7 @@
field public static final java.lang.String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
field public static final java.lang.String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
field public static final java.lang.String SENSOR_SERVICE = "sensor";
- field public static final int VERSION = 1; // 0x1
+ field public static final int VERSION = 2; // 0x2
}
public final class CarAppFocusManager {
diff --git a/car-lib/api/system-1.txt b/car-lib/api/system-1.txt
new file mode 100644
index 0000000..763114b
--- /dev/null
+++ b/car-lib/api/system-1.txt
@@ -0,0 +1,787 @@
+package android.car {
+
+ public final class Car {
+ method public void connect() throws java.lang.IllegalStateException;
+ method public static android.car.Car createCar(android.content.Context, android.content.ServiceConnection, android.os.Handler);
+ method public static android.car.Car createCar(android.content.Context, android.content.ServiceConnection);
+ method public void disconnect();
+ method public int getCarConnectionType();
+ method public java.lang.Object getCarManager(java.lang.String) throws android.car.CarNotConnectedException;
+ method public boolean isConnected();
+ method public boolean isConnecting();
+ field public static final java.lang.String APP_FOCUS_SERVICE = "app_focus";
+ field public static final java.lang.String AUDIO_SERVICE = "audio";
+ field public static final java.lang.String CABIN_SERVICE = "cabin";
+ field public static final java.lang.String CAMERA_SERVICE = "camera";
+ field public static final int CONNECTION_TYPE_EMBEDDED = 5; // 0x5
+ field public static final java.lang.String HVAC_SERVICE = "hvac";
+ field public static final java.lang.String INFO_SERVICE = "info";
+ field public static final java.lang.String PACKAGE_SERVICE = "package";
+ field public static final java.lang.String PERMISSION_CAR_CABIN = "android.car.permission.CAR_CABIN";
+ field public static final java.lang.String PERMISSION_CAR_CAMERA = "android.car.permission.CAR_CAMERA";
+ field public static final java.lang.String PERMISSION_CAR_CONTROL_AUDIO_VOLUME = "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
+ field public static final java.lang.String PERMISSION_CAR_HVAC = "android.car.permission.CAR_HVAC";
+ field public static final java.lang.String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
+ field public static final java.lang.String PERMISSION_CAR_RADIO = "android.car.permission.CAR_RADIO";
+ field public static final java.lang.String PERMISSION_CONTROL_APP_BLOCKING = "android.car.permission.CONTROL_APP_BLOCKING";
+ field public static final java.lang.String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
+ field public static final java.lang.String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
+ field public static final java.lang.String PERMISSION_MOCK_VEHICLE_HAL = "android.car.permission.CAR_MOCK_VEHICLE_HAL";
+ field public static final java.lang.String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
+ field public static final java.lang.String PERMISSION_VENDOR_EXTENSION = "android.car.permission.CAR_VENDOR_EXTENSION";
+ field public static final java.lang.String PROJECTION_SERVICE = "projection";
+ field public static final java.lang.String RADIO_SERVICE = "radio";
+ field public static final java.lang.String SENSOR_SERVICE = "sensor";
+ field public static final java.lang.String TEST_SERVICE = "car-service-test";
+ field public static final java.lang.String VENDOR_EXTENSION_SERVICE = "vendor_extension";
+ field public static final int VERSION = 1; // 0x1
+ }
+
+ public final class CarAppFocusManager {
+ method public void abandonAppFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback, int);
+ method public void abandonAppFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback);
+ method public void addFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener, int) throws android.car.CarNotConnectedException;
+ method public boolean isOwningFocus(android.car.CarAppFocusManager.OnAppFocusOwnershipCallback, int) throws android.car.CarNotConnectedException;
+ method public void removeFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener, int);
+ method public void removeFocusListener(android.car.CarAppFocusManager.OnAppFocusChangedListener);
+ method public int requestAppFocus(int, android.car.CarAppFocusManager.OnAppFocusOwnershipCallback) throws android.car.CarNotConnectedException, java.lang.SecurityException;
+ field public static final int APP_FOCUS_REQUEST_FAILED = 0; // 0x0
+ field public static final int APP_FOCUS_REQUEST_SUCCEEDED = 1; // 0x1
+ field public static final int APP_FOCUS_TYPE_NAVIGATION = 1; // 0x1
+ field public static final int APP_FOCUS_TYPE_VOICE_COMMAND = 2; // 0x2
+ }
+
+ public static abstract interface CarAppFocusManager.OnAppFocusChangedListener {
+ method public abstract void onAppFocusChanged(int, boolean);
+ }
+
+ public static abstract interface CarAppFocusManager.OnAppFocusOwnershipCallback {
+ method public abstract void onAppFocusOwnershipGranted(int);
+ method public abstract void onAppFocusOwnershipLost(int);
+ }
+
+ public final class CarInfoManager {
+ method public java.lang.String getManufacturer() throws android.car.CarNotConnectedException;
+ method public java.lang.String getModel() throws android.car.CarNotConnectedException;
+ method public java.lang.String getModelYear() throws android.car.CarNotConnectedException;
+ method public java.lang.String getVehicleId() throws android.car.CarNotConnectedException;
+ }
+
+ public class CarNotConnectedException extends java.lang.Exception {
+ ctor public CarNotConnectedException();
+ ctor public CarNotConnectedException(java.lang.String);
+ ctor public CarNotConnectedException(java.lang.String, java.lang.Throwable);
+ ctor public CarNotConnectedException(java.lang.Exception);
+ }
+
+ public final class CarProjectionManager {
+ method public void onCarDisconnected();
+ method public void registerProjectionRunner(android.content.Intent) throws android.car.CarNotConnectedException;
+ method public void regsiterProjectionListener(android.car.CarProjectionManager.CarProjectionListener, int) throws android.car.CarNotConnectedException;
+ method public void unregisterProjectionRunner(android.content.Intent);
+ method public void unregsiterProjectionListener();
+ field public static final int PROJECTION_LONG_PRESS_VOICE_SEARCH = 2; // 0x2
+ field public static final int PROJECTION_VOICE_SEARCH = 1; // 0x1
+ }
+
+ public static abstract interface CarProjectionManager.CarProjectionListener {
+ method public abstract void onVoiceAssistantRequest(boolean);
+ }
+
+ public final class VehicleAreaType {
+ field public static final int VEHICLE_AREA_TYPE_DOOR = 4; // 0x4
+ field public static final int VEHICLE_AREA_TYPE_MIRROR = 5; // 0x5
+ field public static final int VEHICLE_AREA_TYPE_NONE = 0; // 0x0
+ field public static final int VEHICLE_AREA_TYPE_SEAT = 3; // 0x3
+ field public static final int VEHICLE_AREA_TYPE_WINDOW = 2; // 0x2
+ field public static final int VEHICLE_AREA_TYPE_ZONE = 1; // 0x1
+ }
+
+ public final class VehicleDoor {
+ field public static final int DOOR_HOOD = 268435456; // 0x10000000
+ field public static final int DOOR_REAR = 536870912; // 0x20000000
+ field public static final int DOOR_ROW_1_LEFT = 1; // 0x1
+ field public static final int DOOR_ROW_1_RIGHT = 4; // 0x4
+ field public static final int DOOR_ROW_2_LEFT = 16; // 0x10
+ field public static final int DOOR_ROW_2_RIGHT = 64; // 0x40
+ field public static final int DOOR_ROW_3_LEFT = 256; // 0x100
+ field public static final int DOOR_ROW_3_RIGHT = 1024; // 0x400
+ }
+
+ public final class VehicleMirror {
+ field public static final int MIRROR_DRIVER_CENTER = 4; // 0x4
+ field public static final int MIRROR_DRIVER_LEFT = 1; // 0x1
+ field public static final int MIRROR_DRIVER_RIGHT = 2; // 0x2
+ }
+
+ public final class VehicleSeat {
+ field public static final int SEAT_ROW_1_CENTER = 2; // 0x2
+ field public static final int SEAT_ROW_1_LEFT = 1; // 0x1
+ field public static final int SEAT_ROW_1_RIGHT = 4; // 0x4
+ field public static final int SEAT_ROW_2_CENTER = 32; // 0x20
+ field public static final int SEAT_ROW_2_LEFT = 16; // 0x10
+ field public static final int SEAT_ROW_2_RIGHT = 64; // 0x40
+ field public static final int SEAT_ROW_3_CENTER = 512; // 0x200
+ field public static final int SEAT_ROW_3_LEFT = 256; // 0x100
+ field public static final int SEAT_ROW_3_RIGHT = 1024; // 0x400
+ }
+
+ public final class VehicleWindow {
+ field public static final int WINDOW_FRONT_WINDSHIELD = 1; // 0x1
+ field public static final int WINDOW_REAR_WINDSHIELD = 2; // 0x2
+ field public static final int WINDOW_ROOF_TOP = 4; // 0x4
+ field public static final int WINDOW_ROW_1_LEFT = 16; // 0x10
+ field public static final int WINDOW_ROW_1_RIGHT = 32; // 0x20
+ field public static final int WINDOW_ROW_2_LEFT = 256; // 0x100
+ field public static final int WINDOW_ROW_2_RIGHT = 512; // 0x200
+ field public static final int WINDOW_ROW_3_LEFT = 4096; // 0x1000
+ field public static final int WINDOW_ROW_3_RIGHT = 8192; // 0x2000
+ }
+
+ public final class VehicleZone {
+ field public static final int ZONE_ALL = -2147483648; // 0x80000000
+ field public static final int ZONE_ROW_1_ALL = 8; // 0x8
+ field public static final int ZONE_ROW_1_CENTER = 2; // 0x2
+ field public static final int ZONE_ROW_1_LEFT = 1; // 0x1
+ field public static final int ZONE_ROW_1_RIGHT = 4; // 0x4
+ field public static final int ZONE_ROW_2_ALL = 128; // 0x80
+ field public static final int ZONE_ROW_2_CENTER = 32; // 0x20
+ field public static final int ZONE_ROW_2_LEFT = 16; // 0x10
+ field public static final int ZONE_ROW_2_RIGHT = 64; // 0x40
+ field public static final int ZONE_ROW_3_ALL = 2048; // 0x800
+ field public static final int ZONE_ROW_3_CENTER = 512; // 0x200
+ field public static final int ZONE_ROW_3_LEFT = 256; // 0x100
+ field public static final int ZONE_ROW_3_RIGHT = 1024; // 0x400
+ field public static final int ZONE_ROW_4_ALL = 32768; // 0x8000
+ field public static final int ZONE_ROW_4_CENTER = 8192; // 0x2000
+ field public static final int ZONE_ROW_4_LEFT = 4096; // 0x1000
+ field public static final int ZONE_ROW_4_RIGHT = 16384; // 0x4000
+ }
+
+ public final class VehicleZoneUtil {
+ method public static int getFirstZone(int);
+ method public static int getNextZone(int, int) throws java.lang.IllegalArgumentException;
+ method public static int getNumberOfZones(int);
+ method public static int[] listAllZones(int);
+ method public static int zoneToIndex(int, int) throws java.lang.IllegalArgumentException;
+ }
+
+}
+
+package android.car.app.menu {
+
+ public abstract class CarMenuCallbacks {
+ ctor public CarMenuCallbacks();
+ method public abstract android.car.app.menu.RootMenu getRootMenu(android.os.Bundle);
+ method public abstract void onCarMenuClosed();
+ method public abstract void onCarMenuClosing();
+ method public abstract void onCarMenuOpened();
+ method public abstract void onCarMenuOpening();
+ method public abstract void onItemClicked(java.lang.String);
+ method public abstract boolean onItemLongClicked(java.lang.String);
+ method public abstract boolean onMenuClicked();
+ method public abstract void subscribe(java.lang.String, android.car.app.menu.SubscriptionCallbacks);
+ method public abstract void unsubscribe(java.lang.String, android.car.app.menu.SubscriptionCallbacks);
+ }
+
+ public class CarMenuConstants {
+ ctor public CarMenuConstants();
+ }
+
+ public static class CarMenuConstants.MenuItemConstants {
+ ctor public CarMenuConstants.MenuItemConstants();
+ field public static final int FLAG_BROWSABLE = 1; // 0x1
+ field public static final int FLAG_FIRSTITEM = 2; // 0x2
+ field public static final java.lang.String KEY_EMPTY_PLACEHOLDER = "android.car.app.menu.empty_placeholder";
+ field public static final java.lang.String KEY_FLAGS = "android.car.app.menu.flags";
+ field public static final java.lang.String KEY_ID = "android.car.app.menu.id";
+ field public static final java.lang.String KEY_LEFTICON = "android.car.app.menu.leftIcon";
+ field public static final java.lang.String KEY_REMOTEVIEWS = "android.car.app.menu.remoteViews";
+ field public static final java.lang.String KEY_RIGHTICON = "android.car.app.menu.rightIcon";
+ field public static final java.lang.String KEY_RIGHTTEXT = "android.car.app.menu.rightText";
+ field public static final java.lang.String KEY_TEXT = "android.car.app.menu.text";
+ field public static final java.lang.String KEY_TITLE = "android.car.app.menu.title";
+ field public static final java.lang.String KEY_WIDGET = "android.car.app.menu.widget";
+ field public static final java.lang.String KEY_WIDGET_STATE = "android.car.app.menu.widget_state";
+ field public static final int WIDGET_CHECKBOX = 1; // 0x1
+ field public static final int WIDGET_TEXT_VIEW = 2; // 0x2
+ }
+
+ public static abstract class CarMenuConstants.MenuItemConstants.MenuItemFlags implements java.lang.annotation.Annotation {
+ }
+
+ public static abstract class CarMenuConstants.MenuItemConstants.WidgetTypes implements java.lang.annotation.Annotation {
+ }
+
+ public abstract class CarUiEntry {
+ ctor public CarUiEntry(android.content.Context, android.content.Context);
+ method public abstract void closeDrawer();
+ method public abstract android.view.View getContentView();
+ method public abstract int getFragmentContainerId();
+ method public abstract java.lang.CharSequence getSearchBoxText();
+ method public abstract void hideMenuButton();
+ method public abstract void hideTitle();
+ method public abstract void onPause();
+ method public abstract void onRestoreInstanceState(android.os.Bundle);
+ method public abstract void onResume();
+ method public abstract void onSaveInstanceState(android.os.Bundle);
+ method public abstract void onStart();
+ method public abstract void onStop();
+ method public abstract void openDrawer();
+ method public abstract void restoreMenuDrawable();
+ method public abstract void setAutoLightDarkMode();
+ method public abstract void setBackground(android.graphics.Bitmap);
+ method public abstract void setCarMenuCallbacks(android.car.app.menu.CarMenuCallbacks);
+ method public abstract void setDarkMode();
+ method public abstract void setLightMode();
+ method public abstract void setMenuButtonBitmap(android.graphics.Bitmap);
+ method public abstract void setMenuButtonColor(int);
+ method public abstract void setScrimColor(int);
+ method public abstract void setSearchBoxColors(int, int, int, int);
+ method public abstract void setSearchBoxEditListener(android.car.app.menu.SearchBoxEditListener);
+ method public abstract void setSearchBoxEndView(android.view.View);
+ method public abstract void setTitle(java.lang.CharSequence);
+ method public abstract void showMenu(java.lang.String, java.lang.String);
+ method public abstract void showSearchBox(android.view.View.OnClickListener);
+ method public abstract void showTitle();
+ method public abstract void showToast(java.lang.String, long);
+ method public abstract android.widget.EditText startInput(java.lang.String, android.view.View.OnClickListener);
+ method public abstract void stopInput();
+ field protected final android.content.Context mAppContext;
+ field protected final android.content.Context mUiLibContext;
+ }
+
+ public class RootMenu {
+ ctor public RootMenu(java.lang.String);
+ ctor public RootMenu(java.lang.String, android.os.Bundle);
+ method public android.os.Bundle getBundle();
+ method public java.lang.String getId();
+ }
+
+ public abstract class SearchBoxEditListener {
+ ctor public SearchBoxEditListener();
+ method public abstract void onEdit(java.lang.String);
+ method public abstract void onSearch(java.lang.String);
+ }
+
+ public abstract class SubscriptionCallbacks {
+ ctor public SubscriptionCallbacks();
+ method public abstract void onChildChanged(java.lang.String, android.os.Bundle);
+ method public abstract void onChildrenLoaded(java.lang.String, java.util.List<android.os.Bundle>);
+ method public abstract void onError(java.lang.String);
+ }
+
+}
+
+package android.car.cluster.renderer {
+
+ public class DisplayConfiguration implements android.os.Parcelable {
+ ctor public DisplayConfiguration(android.os.Parcel);
+ ctor public DisplayConfiguration(android.graphics.Rect);
+ ctor public DisplayConfiguration(android.graphics.Rect, android.graphics.Rect);
+ method public int describeContents();
+ method public android.graphics.Rect getPrimaryRegion();
+ method public android.graphics.Rect getSecondaryRegion();
+ method public boolean hasSecondaryRegion();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.cluster.renderer.DisplayConfiguration> CREATOR;
+ }
+
+ public abstract class InstrumentClusterRenderer {
+ ctor public InstrumentClusterRenderer();
+ method protected abstract android.car.cluster.renderer.NavigationRenderer createNavigationRenderer();
+ method public synchronized android.car.cluster.renderer.NavigationRenderer getNavigationRenderer();
+ method public final synchronized void initialize();
+ method public abstract void onCreate(android.content.Context);
+ method public abstract void onStart();
+ method public abstract void onStop();
+ }
+
+ public abstract class InstrumentClusterRenderingService extends android.app.Service {
+ ctor public InstrumentClusterRenderingService();
+ method protected abstract android.car.cluster.renderer.NavigationRenderer getNavigationRenderer();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method protected void onKeyEvent(android.view.KeyEvent);
+ }
+
+ public abstract class NavigationRenderer {
+ ctor public NavigationRenderer();
+ method public abstract android.car.navigation.CarNavigationInstrumentCluster getNavigationProperties();
+ method public abstract void onNextTurnChanged(int, java.lang.CharSequence, int, int, android.graphics.Bitmap, int);
+ method public abstract void onNextTurnDistanceChanged(int, int, int, int);
+ method public abstract void onStartNavigation();
+ method public abstract void onStopNavigation();
+ }
+
+}
+
+package android.car.content.pm {
+
+ public class AppBlockingPackageInfo implements android.os.Parcelable {
+ ctor public AppBlockingPackageInfo(java.lang.String, int, int, int, android.content.pm.Signature[], java.lang.String[]);
+ ctor public AppBlockingPackageInfo(android.os.Parcel);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.content.pm.AppBlockingPackageInfo> CREATOR;
+ field public static final int FLAG_SYSTEM_APP = 1; // 0x1
+ field public static final int FLAG_WHOLE_ACTIVITY = 2; // 0x2
+ field public final java.lang.String[] activities;
+ field public final int flags;
+ field public final int maxRevisionCode;
+ field public final int minRevisionCode;
+ field public final java.lang.String packageName;
+ field public final android.content.pm.Signature[] signatures;
+ }
+
+ public class CarAppBlockingPolicy implements android.os.Parcelable {
+ ctor public CarAppBlockingPolicy(android.car.content.pm.AppBlockingPackageInfo[], android.car.content.pm.AppBlockingPackageInfo[]);
+ ctor public CarAppBlockingPolicy(android.os.Parcel);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.content.pm.CarAppBlockingPolicy> CREATOR;
+ field public final android.car.content.pm.AppBlockingPackageInfo[] blacklists;
+ field public final android.car.content.pm.AppBlockingPackageInfo[] whitelists;
+ }
+
+ public abstract class CarAppBlockingPolicyService extends android.app.Service {
+ ctor public CarAppBlockingPolicyService();
+ method protected abstract android.car.content.pm.CarAppBlockingPolicy getAppBlockingPolicy();
+ method public android.os.IBinder onBind(android.content.Intent);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.car.content.pm.CarAppBlockingPolicyService";
+ }
+
+ public final class CarPackageManager {
+ method public boolean isActivityAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ method public boolean isActivityBackedBySafeActivity(android.content.ComponentName) throws android.car.CarNotConnectedException;
+ method public boolean isServiceAllowedWhileDriving(java.lang.String, java.lang.String) throws android.car.CarNotConnectedException;
+ method public void setAppBlockingPolicy(java.lang.String, android.car.content.pm.CarAppBlockingPolicy, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException, java.lang.SecurityException;
+ field public static final int FLAG_SET_POLICY_ADD = 2; // 0x2
+ field public static final int FLAG_SET_POLICY_REMOVE = 4; // 0x4
+ field public static final int FLAG_SET_POLICY_WAIT_FOR_CHANGE = 1; // 0x1
+ }
+
+}
+
+package android.car.hardware {
+
+ public class CarPropertyConfig<T> implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getAreaCount();
+ method public int[] getAreaIds();
+ method public int getAreaType();
+ method public int getFirstAndOnlyAreaId();
+ method public T getMaxValue(int);
+ method public T getMaxValue();
+ method public T getMinValue(int);
+ method public T getMinValue();
+ method public int getPropertyId();
+ method public java.lang.Class<T> getPropertyType();
+ method public boolean hasArea(int);
+ method public boolean isGlobalProperty();
+ method public static <T> android.car.hardware.CarPropertyConfig.Builder<T> newBuilder(java.lang.Class<T>, int, int, int);
+ method public static <T> android.car.hardware.CarPropertyConfig.Builder<T> newBuilder(java.lang.Class<T>, int, int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.hardware.CarPropertyConfig> CREATOR;
+ }
+
+ public static class CarPropertyConfig.AreaConfig<T> implements android.os.Parcelable {
+ method public int describeContents();
+ method public T getMaxValue();
+ method public T getMinValue();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.hardware.CarPropertyConfig.AreaConfig<java.lang.Object>> CREATOR;
+ }
+
+ public static class CarPropertyConfig.Builder<T> {
+ method public android.car.hardware.CarPropertyConfig.Builder<T> addArea(int);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> addAreaConfig(int, T, T);
+ method public android.car.hardware.CarPropertyConfig.Builder<T> addAreas(int[]);
+ method public android.car.hardware.CarPropertyConfig<T> build();
+ }
+
+ public class CarPropertyValue<T> implements android.os.Parcelable {
+ ctor public CarPropertyValue(int, T);
+ ctor public CarPropertyValue(int, int, T);
+ ctor public CarPropertyValue(android.os.Parcel);
+ method public int describeContents();
+ method public int getAreaId();
+ method public int getPropertyId();
+ method public T getValue();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.hardware.CarPropertyValue> CREATOR;
+ }
+
+ public class CarSensorEvent implements android.os.Parcelable {
+ 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 DRIVE_STATUS_FULLY_RESTRICTED = 31; // 0x1f
+ field public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 16; // 0x10
+ field public static final int DRIVE_STATUS_NO_CONFIG = 8; // 0x8
+ field public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 2; // 0x2
+ field public static final int DRIVE_STATUS_NO_VIDEO = 1; // 0x1
+ field public static final int DRIVE_STATUS_NO_VOICE_INPUT = 4; // 0x4
+ field public static final int DRIVE_STATUS_UNRESTRICTED = 0; // 0x0
+ 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 INDEX_ENVIRONMENT_PRESSURE = 1; // 0x1
+ field public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0; // 0x0
+ field public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1; // 0x1
+ field public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0; // 0x0
+ field public static final int INDEX_FUEL_LOW_WARNING = 0; // 0x0
+ field public final float[] floatValues;
+ field public final int[] intValues;
+ field public int sensorType;
+ field public long timestamp;
+ }
+
+ public static class CarSensorEvent.EnvironmentData {
+ field public float pressure;
+ field public float temperature;
+ field public long timestamp;
+ }
+
+ public final class CarSensorManager {
+ method public android.car.hardware.CarSensorEvent getLatestSensorEvent(int) throws android.car.CarNotConnectedException;
+ method public int[] getSupportedSensors() throws android.car.CarNotConnectedException;
+ method public boolean isSensorSupported(int) throws android.car.CarNotConnectedException;
+ method public static boolean isSensorSupported(int[], int);
+ 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_CAR_SPEED = 2; // 0x2
+ field public static final int SENSOR_TYPE_DRIVING_STATUS = 11; // 0xb
+ field public static final int SENSOR_TYPE_ENVIRONMENT = 12; // 0xc
+ 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_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_VENDOR_EXTENSION_END = 1879048191; // 0x6fffffff
+ }
+
+ public static abstract interface CarSensorManager.OnSensorChangedListener {
+ method public abstract void onSensorChanged(android.car.hardware.CarSensorEvent);
+ }
+
+ public final class CarVendorExtensionManager {
+ method public <E> E getGlobalProperty(java.lang.Class<E>, int) throws android.car.CarNotConnectedException;
+ method public java.util.List<android.car.hardware.CarPropertyConfig> getProperties() throws android.car.CarNotConnectedException;
+ method public <E> E getProperty(java.lang.Class<E>, int, int) throws android.car.CarNotConnectedException;
+ 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);
+ }
+
+ public static abstract interface CarVendorExtensionManager.CarVendorExtensionCallback {
+ method public abstract void onChangeEvent(android.car.hardware.CarPropertyValue);
+ method public abstract void onErrorEvent(int, int);
+ }
+
+}
+
+package android.car.hardware.cabin {
+
+ public final class CarCabinManager {
+ method public boolean getBooleanProperty(int, int) throws android.car.CarNotConnectedException;
+ method public float getFloatProperty(int, int) throws android.car.CarNotConnectedException;
+ 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 static boolean isZonedProperty(int);
+ method public synchronized void registerCallback(android.car.hardware.cabin.CarCabinManager.CarCabinEventCallback) 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;
+ 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 = 12293; // 0x3005
+ field public static final int ID_WINDOW_MOVE = 12290; // 0x3002
+ field public static final int ID_WINDOW_POS = 12289; // 0x3001
+ field public static final int ID_WINDOW_VENT_MOVE = 12292; // 0x3004
+ field public static final int ID_WINDOW_VENT_POS = 12291; // 0x3003
+ }
+
+ public static abstract interface CarCabinManager.CarCabinEventCallback {
+ method public abstract void onChangeEvent(android.car.hardware.CarPropertyValue);
+ method public abstract void onErrorEvent(int, int);
+ }
+
+}
+
+package android.car.hardware.camera {
+
+ public class CarCamera {
+ ctor public CarCamera(android.car.hardware.camera.ICarCamera, int);
+ method public android.graphics.Rect getCameraCrop() throws android.car.CarNotConnectedException;
+ method public android.graphics.Rect getCameraPosition() throws android.car.CarNotConnectedException;
+ method public android.car.hardware.camera.CarCameraState getCameraState() throws android.car.CarNotConnectedException;
+ method public int getCapabilities() throws android.car.CarNotConnectedException;
+ method public void setCameraCrop(android.graphics.Rect) throws android.car.CarNotConnectedException;
+ method public void setCameraPosition(android.graphics.Rect) throws android.car.CarNotConnectedException;
+ method public void setCameraState(android.car.hardware.camera.CarCameraState) throws android.car.CarNotConnectedException;
+ field public static final java.lang.String TAG;
+ field public final int mCameraType;
+ }
+
+ public final class CarCameraManager {
+ method public void closeCamera(android.car.hardware.camera.CarCamera);
+ method public int getCameraCapabilities(int) throws android.car.CarNotConnectedException;
+ method public int[] getCameraList() throws android.car.CarNotConnectedException;
+ method public android.car.hardware.camera.CarCamera openCamera(int) throws android.car.CarNotConnectedException;
+ field public static final int ANDROID_OVERLAY_SUPPORT_FLAG = 1; // 0x1
+ field public static final int CAMERA_CROP_SUPPORT_FLAG = 2; // 0x2
+ field public static final int CAMERA_POSITIONING_SUPPORT_FLAG = 4; // 0x4
+ field public static final int CAR_CAMERA_TYPE_NONE = 0; // 0x0
+ field public static final int CAR_CAMERA_TYPE_RVC = 1; // 0x1
+ }
+
+ public class CarCameraState implements android.os.Parcelable {
+ ctor public CarCameraState(android.car.hardware.camera.CarCameraState);
+ ctor public CarCameraState(boolean, boolean);
+ method public int describeContents();
+ method public boolean getCameraIsOn();
+ method public boolean getOverlayIsOn();
+ method public void setCameraIsOn(boolean);
+ method public void setOverlayIsOn(boolean);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.hardware.camera.CarCameraState> CREATOR;
+ }
+
+ public abstract interface ICarCamera implements android.os.IInterface {
+ method public abstract android.graphics.Rect getCameraCrop(int) throws android.os.RemoteException;
+ method public abstract int[] getCameraList() throws android.os.RemoteException;
+ method public abstract android.graphics.Rect getCameraPosition(int) throws android.os.RemoteException;
+ method public abstract android.car.hardware.camera.CarCameraState getCameraState(int) throws android.os.RemoteException;
+ method public abstract int getCapabilities(int) throws android.os.RemoteException;
+ method public abstract void setCameraCrop(int, android.graphics.Rect) throws android.os.RemoteException;
+ method public abstract void setCameraPosition(int, android.graphics.Rect) throws android.os.RemoteException;
+ method public abstract void setCameraState(int, android.car.hardware.camera.CarCameraState) throws android.os.RemoteException;
+ }
+
+}
+
+package android.car.hardware.hvac {
+
+ public final class CarHvacManager {
+ method public boolean getBooleanProperty(int, int) throws android.car.CarNotConnectedException;
+ method public float getFloatProperty(int, int) throws android.car.CarNotConnectedException;
+ 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 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;
+ method public void setIntProperty(int, int, int) throws android.car.CarNotConnectedException;
+ method public synchronized void unregisterCallback(android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback);
+ 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_TEMP = 2; // 0x2
+ field public static final int ID_TEMPERATURE_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_POSITION = 16391; // 0x4007
+ field public static final int ID_ZONED_FAN_POSITION_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_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
+ }
+
+ public static abstract interface CarHvacManager.CarHvacEventCallback {
+ method public abstract void onChangeEvent(android.car.hardware.CarPropertyValue);
+ method public abstract void onErrorEvent(int, int);
+ }
+
+}
+
+package android.car.hardware.radio {
+
+ public class CarRadioEvent implements android.os.Parcelable {
+ ctor public CarRadioEvent(int, android.car.hardware.radio.CarRadioPreset);
+ method public int describeContents();
+ method public int getEventType();
+ method public android.car.hardware.radio.CarRadioPreset getPreset();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.hardware.radio.CarRadioEvent> CREATOR;
+ field public static final int RADIO_PRESET = 0; // 0x0
+ }
+
+ public final class CarRadioManager {
+ method public android.car.hardware.radio.CarRadioPreset getPreset(int) throws android.car.CarNotConnectedException;
+ method public int getPresetCount() throws android.car.CarNotConnectedException;
+ method public synchronized void registerListener(android.car.hardware.radio.CarRadioManager.CarRadioEventListener) throws android.car.CarNotConnectedException;
+ method public boolean setPreset(android.car.hardware.radio.CarRadioPreset) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
+ method public synchronized void unregisterListener();
+ }
+
+ public static abstract interface CarRadioManager.CarRadioEventListener {
+ method public abstract void onEvent(android.car.hardware.radio.CarRadioEvent);
+ }
+
+ public class CarRadioPreset implements android.os.Parcelable {
+ ctor public CarRadioPreset(int, int, int, int);
+ method public int describeContents();
+ method public int getBand();
+ method public int getChannel();
+ method public int getPresetNumber();
+ method public int getSubChannel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.car.hardware.radio.CarRadioPreset> CREATOR;
+ }
+
+}
+
+package android.car.input {
+
+ public abstract class CarInputHandlingService extends android.app.Service {
+ ctor protected CarInputHandlingService(android.car.input.CarInputHandlingService.InputFilter[]);
+ method public android.os.IBinder onBind(android.content.Intent);
+ method protected abstract void onKeyEvent(android.view.KeyEvent, int);
+ field public static final int INPUT_CALLBACK_BINDER_CODE = 1; // 0x1
+ field public static final java.lang.String INPUT_CALLBACK_BINDER_KEY = "callback_binder";
+ }
+
+ public static class CarInputHandlingService.InputFilter implements android.os.Parcelable {
+ ctor public CarInputHandlingService.InputFilter(int, int);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public final int mKeyCode;
+ field public final int mTargetDisplay;
+ }
+
+}
+
+package android.car.media {
+
+ public final class CarAudioManager {
+ method public void abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
+ method public android.media.AudioAttributes getAudioAttributesForCarUsage(int) throws android.car.CarNotConnectedException;
+ method public int getStreamMaxVolume(int) throws android.car.CarNotConnectedException;
+ method public int getStreamMinVolume(int) throws android.car.CarNotConnectedException;
+ method public int getStreamVolume(int) throws android.car.CarNotConnectedException;
+ method public boolean isMediaMuted() throws android.car.CarNotConnectedException;
+ method public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
+ method public boolean setMediaMute(boolean) throws android.car.CarNotConnectedException;
+ method public void setStreamVolume(int, int, int) throws android.car.CarNotConnectedException;
+ method public void setVolumeController(android.media.IVolumeController) throws android.car.CarNotConnectedException;
+ field public static final int CAR_AUDIO_USAGE_ALARM = 6; // 0x6
+ field public static final int CAR_AUDIO_USAGE_DEFAULT = 0; // 0x0
+ field public static final int CAR_AUDIO_USAGE_MUSIC = 1; // 0x1
+ field public static final int CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE = 3; // 0x3
+ field public static final int CAR_AUDIO_USAGE_NOTIFICATION = 7; // 0x7
+ field public static final int CAR_AUDIO_USAGE_RADIO = 2; // 0x2
+ field public static final int CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT = 9; // 0x9
+ field public static final int CAR_AUDIO_USAGE_SYSTEM_SOUND = 8; // 0x8
+ field public static final int CAR_AUDIO_USAGE_VOICE_CALL = 4; // 0x4
+ field public static final int CAR_AUDIO_USAGE_VOICE_COMMAND = 5; // 0x5
+ }
+
+}
+
+package android.car.navigation {
+
+ public class CarNavigationInstrumentCluster implements android.os.Parcelable {
+ ctor public CarNavigationInstrumentCluster(android.car.navigation.CarNavigationInstrumentCluster);
+ method public static android.car.navigation.CarNavigationInstrumentCluster createCluster(int);
+ method public static android.car.navigation.CarNavigationInstrumentCluster createCustomImageCluster(int, int, int, int);
+ method public int describeContents();
+ method public int getImageColorDepthBits();
+ method public int getImageHeight();
+ method public int getImageWidth();
+ method public int getMinIntervalMillis();
+ method public int getType();
+ method public boolean supportsCustomImages();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CLUSTER_TYPE_CUSTOM_IMAGES_SUPPORTED = 1; // 0x1
+ field public static final int CLUSTER_TYPE_IMAGE_CODES_ONLY = 2; // 0x2
+ field public static final android.os.Parcelable.Creator<android.car.navigation.CarNavigationInstrumentCluster> CREATOR;
+ }
+
+}
+
+package android.car.settings {
+
+ public class CarSettings {
+ ctor public CarSettings();
+ }
+
+ public static final class CarSettings.Global {
+ ctor public CarSettings.Global();
+ field public static final java.lang.String KEY_GARAGE_MODE_ENABLED = "android.car.GARAGE_MODE_ENABLED";
+ field public static final java.lang.String KEY_GARAGE_MODE_MAINTENANCE_WINDOW = "android.car.GARAGE_MODE_MAINTENANCE_WINDOW";
+ field public static final java.lang.String KEY_GARAGE_MODE_WAKE_UP_TIME = "android.car.GARAGE_MODE_WAKE_UP_TIME";
+ }
+
+}
+
+package android.car.test {
+
+ public class CarTestManagerBinderWrapper {
+ ctor public CarTestManagerBinderWrapper(android.os.IBinder);
+ method public void onCarDisconnected();
+ field public final android.os.IBinder binder;
+ }
+
+}
+
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index 32460c1..94c21be 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -13,14 +13,11 @@
field public static final java.lang.String AUDIO_SERVICE = "audio";
field public static final java.lang.String CABIN_SERVICE = "cabin";
field public static final int CONNECTION_TYPE_EMBEDDED = 5; // 0x5
- field public static final java.lang.String DIAGNOSTIC_SERVICE = "diagnostic";
field public static final java.lang.String HVAC_SERVICE = "hvac";
field public static final java.lang.String INFO_SERVICE = "info";
field public static final java.lang.String PACKAGE_SERVICE = "package";
field public static final java.lang.String PERMISSION_CAR_CABIN = "android.car.permission.CAR_CABIN";
field public static final java.lang.String PERMISSION_CAR_CONTROL_AUDIO_VOLUME = "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
- field public static final java.lang.String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.DIAGNOSTIC_CLEAR";
- field public static final java.lang.String PERMISSION_CAR_DIAGNOSTIC_READ = "android.car.permission.DIAGNOSTIC_READ";
field public static final java.lang.String PERMISSION_CAR_HVAC = "android.car.permission.CAR_HVAC";
field public static final java.lang.String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
field public static final java.lang.String PERMISSION_CAR_RADIO = "android.car.permission.CAR_RADIO";
@@ -38,7 +35,7 @@
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final java.lang.String TEST_SERVICE = "car-service-test";
field public static final java.lang.String VENDOR_EXTENSION_SERVICE = "vendor_extension";
- field public static final int VERSION = 1; // 0x1
+ field public static final int VERSION = 2; // 0x2
field public static final java.lang.String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service";
}
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index ec554f1..80fabd0 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -59,9 +59,11 @@
public final class Car {
/**
- * Represent the version of Car API.
+ * Represent the version of Car API. This is only updated when there is API change.
+ * 1 : N
+ * 2 : O
*/
- public static final int VERSION = 1;
+ public static final int VERSION = 2;
/** Service name for {@link CarSensorManager}, to be used in {@link #getCarManager(String)}. */
public static final String SENSOR_SERVICE = "sensor";
@@ -92,7 +94,6 @@
/**
* @hide
*/
- @SystemApi
public static final String DIAGNOSTIC_SERVICE = "diagnostic";
/**
@@ -248,7 +249,6 @@
* @hide
*/
@FutureFeature
- @SystemApi
public static final String PERMISSION_CAR_DIAGNOSTIC_READ = "android.car.permission.DIAGNOSTIC_READ";
/**
@@ -257,7 +257,6 @@
* @hide
*/
@FutureFeature
- @SystemApi
public static final String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.DIAGNOSTIC_CLEAR";
/** Type of car connection: platform runs directly in car. */
diff --git a/car-lib/src/android/car/hardware/CarDiagnosticEvent.java b/car-lib/src/android/car/hardware/CarDiagnosticEvent.java
index 303ad53..45f13ad 100644
--- a/car-lib/src/android/car/hardware/CarDiagnosticEvent.java
+++ b/car-lib/src/android/car/hardware/CarDiagnosticEvent.java
@@ -275,6 +275,82 @@
}
@Override
+ public boolean equals(Object otherObject) {
+ if (this == otherObject) {
+ return true;
+ }
+ if (null == otherObject) {
+ return false;
+ }
+ if (!(otherObject instanceof CarDiagnosticEvent)) {
+ return false;
+ }
+ CarDiagnosticEvent otherEvent = (CarDiagnosticEvent)otherObject;
+ if (otherEvent.frameType != frameType)
+ return false;
+ if (otherEvent.timestamp != timestamp)
+ return false;
+ if (otherEvent.intValues.size() != intValues.size())
+ return false;
+ if (otherEvent.floatValues.size() != floatValues.size())
+ return false;
+ if (!Objects.equals(dtc, otherEvent.dtc))
+ return false;
+ for (int i = 0; i < intValues.size(); ++i) {
+ int key = intValues.keyAt(i);
+ int otherKey = otherEvent.intValues.keyAt(i);
+ if (key != otherKey) {
+ return false;
+ }
+ int value = intValues.valueAt(i);
+ int otherValue = otherEvent.intValues.valueAt(i);
+ if (value != otherValue) {
+ return false;
+ }
+ }
+ for (int i = 0; i < floatValues.size(); ++i) {
+ int key = floatValues.keyAt(i);
+ int otherKey = otherEvent.floatValues.keyAt(i);
+ if (key != otherKey) {
+ return false;
+ }
+ float value = floatValues.valueAt(i);
+ float otherValue = otherEvent.floatValues.valueAt(i);
+ if (value != otherValue) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ Integer[] intKeys = new Integer[intValues.size()];
+ Integer[] floatKeys = new Integer[floatValues.size()];
+ Integer[] intValues = new Integer[intKeys.length];
+ Float[] floatValues = new Float[floatKeys.length];
+ for (int i = 0; i < intKeys.length; ++i) {
+ intKeys[i] = this.intValues.keyAt(i);
+ intValues[i] = this.intValues.valueAt(i);
+ }
+ for (int i = 0; i < floatKeys.length; ++i) {
+ floatKeys[i] = this.floatValues.keyAt(i);
+ floatValues[i] = this.floatValues.valueAt(i);
+ }
+ int intKeysHash = Objects.hash((Object[])intKeys);
+ int intValuesHash = Objects.hash((Object[])intValues);
+ int floatKeysHash = Objects.hash((Object[])floatKeys);
+ int floatValuesHash = Objects.hash((Object[])floatValues);
+ return Objects.hash(frameType,
+ timestamp,
+ dtc,
+ intKeysHash,
+ intValuesHash,
+ floatKeysHash,
+ floatValuesHash);
+ }
+
+ @Override
public String toString() {
return String.format(
"%s diagnostic frame {\n"
diff --git a/car-support-lib/Android.mk b/car-support-lib/Android.mk
index 1785658..bb12a9f 100644
--- a/car-support-lib/Android.mk
+++ b/car-support-lib/Android.mk
@@ -27,16 +27,11 @@
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SDK_VERSION := 24
LOCAL_MANIFEST_FILE := AndroidManifest.xml
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
LOCAL_JAVA_LIBRARIES += android.car\
- android-support-v4 \
- android-support-v7-appcompat \
- android-support-v7-recyclerview \
- android-support-v7-cardview \
android-support-annotations
# Specify 1.7 for backwards compatibility.
# Otherwise the lib won't be usable on pre-N devices
@@ -58,15 +53,9 @@
LOCAL_MODULE := android.support.car
-LOCAL_SDK_VERSION := 24
-
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4 \
- android-support-v7-appcompat \
- android-support-v7-recyclerview \
- android-support-v7-cardview \
- android-support-annotations
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-annotations
LOCAL_JAVA_LIBRARIES += android.car
@@ -95,10 +84,6 @@
LOCAL_JAVA_LIBRARIES := \
android.car \
- android-support-v4 \
- android-support-v7-appcompat \
- android-support-v7-recyclerview \
- android-support-v7-cardview \
android-support-annotations
LOCAL_MODULE := android.support.car
diff --git a/obd2-lib/src/com/android/car/obd2/IntegerArrayStream.java b/obd2-lib/src/com/android/car/obd2/IntegerArrayStream.java
index 56f64f7..4768ceb 100644
--- a/obd2-lib/src/com/android/car/obd2/IntegerArrayStream.java
+++ b/obd2-lib/src/com/android/car/obd2/IntegerArrayStream.java
@@ -43,6 +43,10 @@
return mData.length - mIndex;
}
+ public boolean isEmpty() {
+ return residualLength() == 0;
+ }
+
public boolean hasAtLeast(int n) {
return residualLength() >= n;
}
diff --git a/obd2-lib/src/com/android/car/obd2/Obd2Command.java b/obd2-lib/src/com/android/car/obd2/Obd2Command.java
index e3366cf..30fca0c 100644
--- a/obd2-lib/src/com/android/car/obd2/Obd2Command.java
+++ b/obd2-lib/src/com/android/car/obd2/Obd2Command.java
@@ -172,7 +172,7 @@
* @param <ValueType> The Java type that represents the command's result type.
*/
public static class FreezeFrameCommand<ValueType> extends Obd2Command<ValueType> {
- private static final int RESPONSE_MARKER = 0x2;
+ private static final int RESPONSE_MARKER = 0x42;
private int mFrameId;
diff --git a/obd2-lib/src/com/android/car/obd2/Obd2Connection.java b/obd2-lib/src/com/android/car/obd2/Obd2Connection.java
index 577b798..f7a2d36 100644
--- a/obd2-lib/src/com/android/car/obd2/Obd2Connection.java
+++ b/obd2-lib/src/com/android/car/obd2/Obd2Connection.java
@@ -20,12 +20,16 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
/** This class represents a connection between Java code and a "vehicle" that talks OBD2. */
public class Obd2Connection {
+ private static final String TAG = Obd2Connection.class.getSimpleName();
+ private static final boolean DBG = false;
/**
* The transport layer that moves OBD2 requests from us to the remote entity and viceversa. It
@@ -116,6 +120,10 @@
InputStream in = Objects.requireNonNull(mConnection.getInputStream());
OutputStream out = Objects.requireNonNull(mConnection.getOutputStream());
+ if (DBG) {
+ Log.i(TAG, "runImpl(" + command + ")");
+ }
+
out.write((command + "\r").getBytes());
out.flush();
@@ -131,6 +139,11 @@
}
String responseValue = response.toString();
+
+ if (DBG) {
+ Log.i(TAG, "runImpl() returned " + responseValue);
+ }
+
return responseValue;
}
@@ -141,11 +154,30 @@
return response;
}
+ String unpackLongFrame(String response) {
+ // long frames come back to us containing colon separated portions
+ if (response.indexOf(':') < 0) return response;
+
+ // remove everything until the first colon
+ response = response.substring(response.indexOf(':') + 1);
+
+ // then remove the <digit>: portions (sequential frame parts)
+ //TODO(egranata): maybe validate the sequence of digits is progressive
+ return response.replaceAll("[0-9]:", "");
+ }
+
public int[] run(String command) throws IOException, InterruptedException {
String responseValue = runImpl(command);
String originalResponseValue = responseValue;
- if (responseValue.startsWith(command))
- responseValue = responseValue.substring(command.length());
+ String unspacedCommand = command.replaceAll(" ", "");
+ if (responseValue.startsWith(unspacedCommand))
+ responseValue = responseValue.substring(unspacedCommand.length());
+ responseValue = unpackLongFrame(responseValue);
+
+ if (DBG) {
+ Log.i(TAG, "post-processed response " + responseValue);
+ }
+
//TODO(egranata): should probably handle these intelligently
responseValue =
removeSideData(
@@ -161,11 +193,12 @@
if (responseValue.equals("?")) return new int[] {0};
if (responseValue.equals("NODATA")) return new int[] {};
if (responseValue.equals("UNABLETOCONNECT")) throw new IOException("connection failure");
+ if (responseValue.equals("CANERROR")) throw new IOException("CAN bus error");
try {
return toHexValues(responseValue);
} catch (IllegalArgumentException e) {
Log.e(
- "OBD2",
+ TAG,
String.format(
"conversion error: command: '%s', original response: '%s'"
+ ", processed response: '%s'",
@@ -228,7 +261,7 @@
public Set<Integer> getSupportedPIDs() throws IOException, InterruptedException {
Set<Integer> result = new HashSet<>();
String[] pids = new String[] {"0100", "0120", "0140", "0160"};
- int basePid = 0;
+ int basePid = 1;
for (String pid : pids) {
int[] responseData = run(pid);
if (responseData.length >= 6) {
@@ -236,11 +269,19 @@
byte byte1 = (byte) (responseData[3] & 0xFF);
byte byte2 = (byte) (responseData[4] & 0xFF);
byte byte3 = (byte) (responseData[5] & 0xFF);
+ if (DBG) {
+ Log.i(TAG, String.format("supported PID at base %d payload %02X%02X%02X%02X",
+ basePid, byte0, byte1, byte2, byte3));
+ }
FourByteBitSet fourByteBitSet = new FourByteBitSet(byte0, byte1, byte2, byte3);
for (int byteIndex = 0; byteIndex < 4; ++byteIndex) {
for (int bitIndex = 7; bitIndex >= 0; --bitIndex) {
if (fourByteBitSet.getBit(byteIndex, bitIndex)) {
- result.add(basePid + 8 * byteIndex + 7 - bitIndex);
+ int command = basePid + 8 * byteIndex + 7 - bitIndex;
+ if (DBG) {
+ Log.i(TAG, "command " + command + " found supported");
+ }
+ result.add(command);
}
}
}
@@ -250,4 +291,46 @@
return result;
}
+
+ String getDiagnosticTroubleCode(IntegerArrayStream source) {
+ final char[] components = new char[] {'P', 'C', 'B', 'U'};
+ final char[] firstDigits = new char[] {'0', '1', '2', '3'};
+ final char[] otherDigits =
+ new char[] {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ StringBuilder builder = new StringBuilder(5);
+
+ int byte0 = source.consume();
+ int byte1 = source.consume();
+
+ int componentMask = (byte0 & 0xC0) >> 6;
+ int firstDigitMask = (byte0 & 0x30) >> 4;
+ int secondDigitMask = (byte0 & 0x0F);
+ int thirdDigitMask = (byte1 & 0xF0) >> 4;
+ int fourthDigitMask = (byte1 & 0x0F);
+
+ builder.append(components[componentMask]);
+ builder.append(firstDigits[firstDigitMask]);
+ builder.append(otherDigits[secondDigitMask]);
+ builder.append(otherDigits[thirdDigitMask]);
+ builder.append(otherDigits[fourthDigitMask]);
+
+ return builder.toString();
+ }
+
+ public List<String> getDiagnosticTroubleCodes() throws IOException, InterruptedException {
+ List<String> result = new ArrayList<>();
+ int[] response = run("03");
+ IntegerArrayStream stream = new IntegerArrayStream(response);
+ if (stream.isEmpty()) return result;
+ if (!stream.expect(0x43))
+ throw new IllegalArgumentException("data from remote end not a mode 3 response");
+ int count = stream.consume();
+ for (int i = 0; i < count; ++i) {
+ result.add(getDiagnosticTroubleCode(stream));
+ }
+ return result;
+ }
}
diff --git a/obd2-lib/src/com/android/car/obd2/Obd2FreezeFrameGenerator.java b/obd2-lib/src/com/android/car/obd2/Obd2FreezeFrameGenerator.java
new file mode 100644
index 0000000..3de4863
--- /dev/null
+++ b/obd2-lib/src/com/android/car/obd2/Obd2FreezeFrameGenerator.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2017 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.obd2;
+
+import android.os.SystemClock;
+import android.util.JsonWriter;
+import android.util.Log;
+import com.android.car.obd2.Obd2Command.FreezeFrameCommand;
+import com.android.car.obd2.Obd2Command.OutputSemanticHandler;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+public class Obd2FreezeFrameGenerator {
+ public static final String FRAME_TYPE_FREEZE = "freeze";
+ public static final String TAG = Obd2FreezeFrameGenerator.class.getSimpleName();
+
+ private final Obd2Connection mConnection;
+ private final List<OutputSemanticHandler<Integer>> mIntegerCommands = new ArrayList<>();
+ private final List<OutputSemanticHandler<Float>> mFloatCommands = new ArrayList<>();
+
+ private List<String> mPreviousDtcs = new ArrayList<>();
+
+ public Obd2FreezeFrameGenerator(Obd2Connection connection)
+ throws IOException, InterruptedException {
+ mConnection = connection;
+ Set<Integer> connectionPids = connection.getSupportedPIDs();
+ Set<Integer> apiIntegerPids = Obd2Command.getSupportedIntegerCommands();
+ Set<Integer> apiFloatPids = Obd2Command.getSupportedFloatCommands();
+ apiIntegerPids
+ .stream()
+ .filter(connectionPids::contains)
+ .forEach((Integer pid) -> mIntegerCommands.add(Obd2Command.getIntegerCommand(pid)));
+ apiFloatPids
+ .stream()
+ .filter(connectionPids::contains)
+ .forEach((Integer pid) -> mFloatCommands.add(Obd2Command.getFloatCommand(pid)));
+ Log.i(
+ TAG,
+ String.format(
+ "connectionPids = %s\napiIntegerPids=%s\napiFloatPids = %s\n"
+ + "mIntegerCommands = %s\nmFloatCommands = %s\n",
+ connectionPids,
+ apiIntegerPids,
+ apiFloatPids,
+ mIntegerCommands,
+ mFloatCommands));
+ }
+
+ public JsonWriter generate(JsonWriter jsonWriter) throws IOException, InterruptedException {
+ return generate(jsonWriter, SystemClock.elapsedRealtimeNanos());
+ }
+
+ // OBD2 does not have a notion of timestamping the fault codes
+ // As such, we need to perform additional magic in order to figure out
+ // whether a fault code we retrieved is the same as a fault code we already
+ // saw in a past iteration. The logic goes as follows:
+ // for every position i in currentDtcs, if mPreviousDtcs[i] is the same
+ // fault code, then assume they are identical. If they are not the same fault code,
+ // then everything in currentDtcs[i...size()) is assumed to be a new fault code as
+ // something in the list must have moved around; if currentDtcs is shorter than
+ // mPreviousDtcs then obviously exit at the end of currentDtcs; if currentDtcs
+ // is longer, however, anything in currentDtcs past the end of mPreviousDtcs is a new
+ // fault code and will be included
+ private final class FreezeFrameIdentity {
+ public final String dtc;
+ public final int id;
+
+ FreezeFrameIdentity(String dtc, int id) {
+ this.dtc = dtc;
+ this.id = id;
+ }
+ }
+
+ private List<FreezeFrameIdentity> discoverNewDtcs(List<String> currentDtcs) {
+ List<FreezeFrameIdentity> newDtcs = new ArrayList<>();
+ int currentIndex = 0;
+ boolean inCopyAllMode = false;
+
+ for (; currentIndex < currentDtcs.size(); ++currentIndex) {
+ if (currentIndex == mPreviousDtcs.size()) {
+ // we have more current DTCs than previous DTCs, copy everything
+ inCopyAllMode = true;
+ break;
+ }
+ if (!currentDtcs.get(currentIndex).equals(mPreviousDtcs.get(currentIndex))) {
+ // we found a different DTC, copy everything
+ inCopyAllMode = true;
+ break;
+ }
+ // same DTC, not at end of either list yet, keep looping
+ }
+
+ if (inCopyAllMode) {
+ for (; currentIndex < currentDtcs.size(); ++currentIndex) {
+ newDtcs.add(new FreezeFrameIdentity(currentDtcs.get(currentIndex), currentIndex));
+ }
+ }
+
+ return newDtcs;
+ }
+
+ public JsonWriter generate(JsonWriter jsonWriter, long timestamp)
+ throws IOException, InterruptedException {
+ List<String> currentDtcs = mConnection.getDiagnosticTroubleCodes();
+ List<FreezeFrameIdentity> newDtcs = discoverNewDtcs(currentDtcs);
+ mPreviousDtcs = currentDtcs;
+ for (FreezeFrameIdentity freezeFrame : newDtcs) {
+ jsonWriter.beginObject();
+ jsonWriter.name("type").value(FRAME_TYPE_FREEZE);
+ jsonWriter.name("timestamp").value(timestamp);
+ jsonWriter.name("stringValue").value(freezeFrame.dtc);
+ jsonWriter.name("intValues").beginArray();
+ for (OutputSemanticHandler<Integer> handler : mIntegerCommands) {
+ FreezeFrameCommand<Integer> command =
+ Obd2Command.getFreezeFrameCommand(handler, freezeFrame.id);
+ try {
+ Optional<Integer> result = command.run(mConnection);
+ if (result.isPresent()) {
+ jsonWriter.beginObject();
+ jsonWriter.name("id").value(command.getPid());
+ jsonWriter.name("value").value(result.get());
+ jsonWriter.endObject();
+ }
+ } catch (IOException | InterruptedException e) {
+ Log.w(
+ TAG,
+ String.format(
+ "unable to retrieve OBD2 pid %d due to exception: %s",
+ command.getPid(), e));
+ // skip this entry
+ }
+ }
+ jsonWriter.endArray();
+ jsonWriter.name("floatValues").beginArray();
+ for (OutputSemanticHandler<Float> handler : mFloatCommands) {
+ FreezeFrameCommand<Float> command =
+ Obd2Command.getFreezeFrameCommand(handler, freezeFrame.id);
+ try {
+ Optional<Float> result = command.run(mConnection);
+ if (result.isPresent()) {
+ jsonWriter.beginObject();
+ jsonWriter.name("id").value(command.getPid());
+ jsonWriter.name("value").value(result.get());
+ jsonWriter.endObject();
+ }
+ } catch (IOException | InterruptedException e) {
+ Log.w(
+ TAG,
+ String.format(
+ "unable to retrieve OBD2 pid %d due to exception: %s",
+ command.getPid(), e));
+ // skip this entry
+ }
+ }
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ }
+ return jsonWriter;
+ }
+}
diff --git a/obd2-lib/src/com/android/car/obd2/commands/RPM.java b/obd2-lib/src/com/android/car/obd2/commands/RPM.java
index b277abf..a062e97 100644
--- a/obd2-lib/src/com/android/car/obd2/commands/RPM.java
+++ b/obd2-lib/src/com/android/car/obd2/commands/RPM.java
@@ -30,7 +30,7 @@
public Optional<Integer> consume(IntegerArrayStream data) {
return data.hasAtLeast(
2,
- theData -> Optional.of(theData.consume() * 256 + theData.consume() / 4),
+ theData -> Optional.of((theData.consume() * 256 + theData.consume()) / 4),
theData -> Optional.<Integer>empty());
}
}
diff --git a/service/src/com/android/car/CarLog.java b/service/src/com/android/car/CarLog.java
index e594ec5..d9600d6 100644
--- a/service/src/com/android/car/CarLog.java
+++ b/service/src/com/android/car/CarLog.java
@@ -17,6 +17,8 @@
package com.android.car;
public class CarLog {
+ private static final int MAX_TAG_LEN = 23;
+
public static final String TAG_AM = "CAR.AM";
public static final String TAG_APP_FOCUS = "CAR.APP_FOCUS";
public static final String TAG_AUDIO = "CAR.AUDIO";
@@ -41,4 +43,12 @@
public static final String TAG_SYS = "CAR.SYS";
public static final String TAG_TEST = "CAR.TEST";
public static final String TAG_DIAGNOSTIC = "CAR.DIAGNOSTIC";
+
+ public static String concatTag(String tagPrefix, Class clazz) {
+ String tag = tagPrefix + "." + clazz.getSimpleName();
+ if (tag.length() > MAX_TAG_LEN) {
+ tag = tag.substring(0, MAX_TAG_LEN);
+ }
+ return tag;
+ }
}
diff --git a/service/src/com/android/car/hal/CarPropertyUtils.java b/service/src/com/android/car/hal/CarPropertyUtils.java
index 3ea9aca..6229511 100644
--- a/service/src/com/android/car/hal/CarPropertyUtils.java
+++ b/service/src/com/android/car/hal/CarPropertyUtils.java
@@ -103,7 +103,7 @@
int areaType = getVehicleAreaType(p.prop & VehicleArea.MASK);
Class<?> clazz = getJavaClass(p.prop & VehiclePropertyType.MASK);
- if (clazz == Boolean.class || clazz == byte[].class || clazz == String.class) {
+ if (p.areaConfigs.isEmpty()) {
return CarPropertyConfig
.newBuilder(clazz, propertyId, areaType, /* capacity */ 1)
.addAreas(areas)
@@ -162,6 +162,8 @@
return String.class;
case VehiclePropertyType.BYTES:
return byte[].class;
+ case VehiclePropertyType.COMPLEX:
+ return Object.class;
default:
throw new IllegalArgumentException("Unexpected type: " + toHexString(halType));
}
diff --git a/service/src/com/android/car/hal/SensorHalService.java b/service/src/com/android/car/hal/SensorHalService.java
index 145dcd2..fd9b057 100644
--- a/service/src/com/android/car/hal/SensorHalService.java
+++ b/service/src/com/android/car/hal/SensorHalService.java
@@ -30,14 +30,10 @@
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
import android.util.Log;
-import android.util.SparseArray;
import android.util.SparseIntArray;
-
import com.android.car.CarLog;
import com.android.car.CarSensorEventFactory;
-
import java.io.PrintWriter;
-import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
@@ -45,6 +41,9 @@
* Sensor HAL implementation for physical sensors in car.
*/
public class SensorHalService extends SensorHalServiceBase {
+ private static final String TAG = CarLog.concatTag(CarLog.TAG_SENSOR, SensorHalService.class);
+ private static final boolean DBG_EVENTS = false;
+
/**
* Listener for monitoring sensor event. Only sensor service will implement this.
*/
@@ -56,13 +55,12 @@
void onSensorEvents(List<CarSensorEvent> events);
}
- private static final boolean DBG_EVENTS = false;
- private final LinkedList<CarSensorEvent> mDispatchQ = new LinkedList<>();
-
// Manager property Id to HAL property Id mapping.
private final static ManagerToHalPropIdMap mManagerToHalPropIdMap =
ManagerToHalPropIdMap.create(
CarSensorManager.SENSOR_TYPE_CAR_SPEED, VehicleProperty.PERF_VEHICLE_SPEED,
+ CarSensorManager.SENSOR_TYPE_RPM, VehicleProperty.ENGINE_RPM,
+ CarSensorManager.SENSOR_TYPE_ODOMETER, VehicleProperty.PERF_ODOMETER,
CarSensorManager.SENSOR_TYPE_GEAR, VehicleProperty.GEAR_SELECTION,
CarSensorManager.SENSOR_TYPE_NIGHT, VehicleProperty.NIGHT_MODE,
CarSensorManager.SENSOR_TYPE_PARKING_BRAKE, VehicleProperty.PARKING_BRAKE_ON,
@@ -124,29 +122,17 @@
mEventsToDispatch.add(event);
}
}
- SensorListener sensorListener = null;
+ SensorListener sensorListener;
synchronized (this) {
sensorListener = mSensorListener;
}
+ if (DBG_EVENTS) Log.d(TAG, "handleHalEvents, listener: " + sensorListener);
if (sensorListener != null) {
sensorListener.onSensorEvents(mEventsToDispatch);
}
mEventsToDispatch.clear();
}
- /**
- * Utility to help service to send one event as listener only takes list form.
- * @param listener
- * @param event
- */
- protected void dispatchCarSensorEvent(SensorListener listener, CarSensorEvent event) {
- synchronized (mDispatchQ) {
- mDispatchQ.add(event);
- listener.onSensorEvents(mDispatchQ);
- mDispatchQ.clear();
- }
- }
-
@Nullable
private Integer mapHalEnumValueToMgr(int propId, int halValue) {
int mgrValue = halValue;
@@ -163,6 +149,7 @@
return mgrValue == -1 ? null : mgrValue;
}
+ @Nullable
private CarSensorEvent createCarSensorEvent(VehiclePropValue v) {
int property = v.prop;
int sensorType = mManagerToHalPropIdMap.getManagerPropId(property);
@@ -172,35 +159,27 @@
int dataType = property & VehiclePropertyType.MASK;
+ CarSensorEvent event = null;
switch (dataType) {
case VehiclePropertyType.BOOLEAN:
- if (DBG_EVENTS) {
- Log.i(CarLog.TAG_SENSOR, "boolean event, property:" +
- toHexString(property) + " value:" + v.value.int32Values.get(0));
- }
- return CarSensorEventFactory.createBooleanEvent(sensorType, v.timestamp,
+ event = CarSensorEventFactory.createBooleanEvent(sensorType, v.timestamp,
v.value.int32Values.get(0) == 1);
+ break;
case VehiclePropertyType.INT32:
- if (DBG_EVENTS) {
- Log.i(CarLog.TAG_SENSOR, "int event, property:" +
- toHexString(property) + " value:" + v.value.int32Values.get(0));
- }
Integer mgrVal = mapHalEnumValueToMgr(property, v.value.int32Values.get(0));
- return mgrVal == null ? null
+ event = mgrVal == null ? null
: CarSensorEventFactory.createIntEvent(sensorType, v.timestamp, mgrVal);
+ break;
case VehiclePropertyType.FLOAT: {
- if (DBG_EVENTS) {
- Log.i(CarLog.TAG_SENSOR, "float event, property:" +
- toHexString(property) + " value:" + v.value.floatValues.get(0));
- }
- return CarSensorEventFactory.createFloatEvent(sensorType, v.timestamp,
+ event = CarSensorEventFactory.createFloatEvent(sensorType, v.timestamp,
v.value.floatValues.get(0));
+ break;
}
default:
- Log.w(CarLog.TAG_SENSOR, "createCarSensorEvent: unsupported type: 0x"
- + toHexString(dataType));
+ Log.w(TAG, "createCarSensorEvent: unsupported type: 0x" + toHexString(dataType));
}
- return null;
+ if (DBG_EVENTS) Log.i(TAG, "Sensor event created: " + event);
+ return event;
}
@Nullable
diff --git a/service/src/com/android/car/hal/SensorHalServiceBase.java b/service/src/com/android/car/hal/SensorHalServiceBase.java
index 92d2540..0417690 100644
--- a/service/src/com/android/car/hal/SensorHalServiceBase.java
+++ b/service/src/com/android/car/hal/SensorHalServiceBase.java
@@ -22,9 +22,9 @@
import android.car.hardware.CarSensorEvent;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-
import android.util.Log;
import android.util.SparseArray;
+import com.android.car.CarLog;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
@@ -37,7 +37,9 @@
* the {@link #requestSensorStart(int, int)} call.
*/
public abstract class SensorHalServiceBase extends HalServiceBase implements SensorBase {
- private static final String TAG = "SensorHalServiceBase";
+ private static final String TAG = CarLog.concatTag(CarLog.TAG_SENSOR,
+ SensorHalServiceBase.class);
+ protected static final boolean DBG = false;
private boolean mIsReady = false;
@@ -49,13 +51,21 @@
mHal = hal;
}
+
@Override
public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
Collection<VehiclePropConfig> allProperties) {
+ if (DBG) Log.d(TAG, "takeSupportedProperties");
LinkedList<VehiclePropConfig> supportedProperties = new LinkedList<>();
for (VehiclePropConfig halProperty : allProperties) {
int sensor = getTokenForProperty(halProperty);
- if (sensor != SENSOR_TYPE_INVALID) {
+ boolean mapped = sensor != SENSOR_TYPE_INVALID;
+ if (DBG) {
+ Log.d(TAG, "takeSupportedProperties, hal property "
+ + " 0x" + toHexString(halProperty.prop) +
+ (mapped ? (" mapped to " + sensor) : " ignored"));
+ }
+ if (mapped) {
supportedProperties.add(halProperty);
mSensorToPropConfig.append(sensor, halProperty);
}
@@ -97,8 +107,10 @@
@Override
public synchronized boolean requestSensorStart(int sensorType, int rate) {
+ if (DBG) Log.d(TAG, "requestSensorStart, sensorType: " + sensorType + ", rate: " + rate);
VehiclePropConfig config = mSensorToPropConfig.get(sensorType);
if (config == null) {
+ Log.e(TAG, "requesting to start sensor " + sensorType + ", but VHAL config not found");
return false;
}
//TODO calculate sampling rate properly, bug: 32095903
@@ -108,6 +120,7 @@
@Override
public synchronized void requestSensorStop(int sensorType) {
+ if (DBG) Log.d(TAG, "requestSensorStop, sensorType: " + sensorType);
VehiclePropConfig config = mSensorToPropConfig.get(sensorType);
if (config == null) {
return;
@@ -122,8 +135,7 @@
config = mSensorToPropConfig.get(sensorType);
}
if (config == null) {
- Log.e(TAG, "sensor type not available 0x" +
- toHexString(sensorType));
+ Log.e(TAG, "sensor type not available 0x" + toHexString(sensorType));
return null;
}
try {
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index 4fe8e2f..86237ad 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -42,6 +42,8 @@
import android.util.Log;
import android.util.SparseArray;
+import com.google.android.collect.Lists;
+
import com.android.car.CarLog;
import com.android.car.internal.FeatureConfiguration;
import com.android.internal.annotations.VisibleForTesting;
@@ -490,10 +492,9 @@
for (VehiclePropValue v : propValues) {
HalServiceBase service = mPropertyHandlers.get(v.prop);
if(service == null) {
- if (DBG) {
- Log.d(CarLog.TAG_HAL, "HalService is null for " + v.prop);
- }
- return;
+ Log.e(CarLog.TAG_HAL, "HalService not found for prop: 0x"
+ + toHexString(v.prop));
+ continue;
}
service.getDispatchList().add(v);
mServicesToDispatch.add(service);
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java
index ccbaa6d..4fb72a1 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java
@@ -67,37 +67,31 @@
private void assertTypeAndZone(CarPropertyConfig property) {
switch (property.getPropertyId()) {
case CarHvacManager.ID_MIRROR_DEFROSTER_ON: // non-zoned bool
- assertEquals(Boolean.class, property.getPropertyType());
- assertTrue(property.isGlobalProperty());
+ checkTypeAndGlobal(Boolean.class, true, property);
break;
case CarHvacManager.ID_STEERING_WHEEL_TEMP: // non-zoned int
case CarHvacManager.ID_TEMPERATURE_UNITS:
- assertEquals(Integer.class, property.getPropertyType());
- assertTrue(property.isGlobalProperty());
+ checkTypeAndGlobal(Integer.class, true, property);
checkIntMinMax(property);
break;
case CarHvacManager.ID_OUTSIDE_AIR_TEMP:
- assertEquals(Float.class, property.getPropertyType());
- assertTrue(property.isGlobalProperty());
- checkFloatMinMax(property);
+ checkTypeAndGlobal(Float.class, true, property);
break;
case CarHvacManager.ID_ZONED_TEMP_SETPOINT: // zoned float
case CarHvacManager.ID_ZONED_TEMP_ACTUAL:
- assertEquals(Float.class, property.getPropertyType());
- assertFalse(property.isGlobalProperty());
+ checkTypeAndGlobal(Float.class, false, property);
checkFloatMinMax(property);
break;
case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: // zoned int
case CarHvacManager.ID_ZONED_FAN_SPEED_RPM:
case CarHvacManager.ID_ZONED_FAN_POSITION_AVAILABLE:
- case CarHvacManager.ID_ZONED_FAN_POSITION:
case CarHvacManager.ID_ZONED_SEAT_TEMP:
- assertEquals("Wrong type, expecting Int type for id:" + property.getPropertyId(),
- Integer.class, property.getPropertyType());
- assertFalse("Wrong zone, should not be global for id: " + property.getPropertyId() +
- ", area type:" + property.getAreaType(), property.isGlobalProperty());
+ checkTypeAndGlobal(Integer.class, false, property);
checkIntMinMax(property);
break;
+ case CarHvacManager.ID_ZONED_FAN_POSITION:
+ checkTypeAndGlobal(Integer.class, false, property);
+ break;
case CarHvacManager.ID_ZONED_AC_ON: // zoned boolean
case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON:
case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON:
@@ -106,12 +100,19 @@
case CarHvacManager.ID_ZONED_MAX_DEFROST_ON:
case CarHvacManager.ID_ZONED_HVAC_POWER_ON:
case CarHvacManager.ID_WINDOW_DEFROSTER_ON:
- assertEquals(Boolean.class, property.getPropertyType());
- assertFalse(property.isGlobalProperty());
+ checkTypeAndGlobal(Boolean.class, false, property);
break;
}
}
+ private void checkTypeAndGlobal(Class clazz, boolean global, CarPropertyConfig<Integer> property) {
+ assertEquals("Wrong type, expecting " + clazz + " type for id:" + property.getPropertyId(),
+ clazz, property.getPropertyType());
+ assertEquals("Wrong zone, should " + (global ? "" : "not ") + "be global for id: " +
+ property.getPropertyId() + ", area type:" + property.getAreaType(),
+ global, property.isGlobalProperty());
+ }
+
private void checkIntMinMax(CarPropertyConfig<Integer> property) {
Log.i(TAG, "checkIntMinMax property:" + property);
if (!property.isGlobalProperty()) {
diff --git a/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java b/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
index 583c36a..e292ed5 100644
--- a/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
@@ -618,6 +618,15 @@
CarDiagnosticEvent event1 = listener1.getLastEvent();
CarDiagnosticEvent event2 = listener2.getLastEvent();
+
+ assertTrue(event1.equals(event1));
+ assertTrue(event2.equals(event2));
+ assertTrue(event1.equals(event2));
+ assertTrue(event2.equals(event1));
+
+ assertTrue(event1.hashCode() == event1.hashCode());
+ assertTrue(event1.hashCode() == event2.hashCode());
+
assertEquals(
5000,
event1.getSystemIntegerSensor(Obd2IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START)
@@ -641,6 +650,8 @@
event2 = listener2.getLastEvent();
assertTrue(event1.isEarlierThan(event2));
+ assertFalse(event1.equals(event2));
+ assertFalse(event2.equals(event1));
assertEquals(
5000,
diff --git a/tests/obd2_app/src/com/google/android/car/obd2app/Obd2CollectionTask.java b/tests/obd2_app/src/com/google/android/car/obd2app/Obd2CollectionTask.java
index 31c3db2..b38cf30 100644
--- a/tests/obd2_app/src/com/google/android/car/obd2app/Obd2CollectionTask.java
+++ b/tests/obd2_app/src/com/google/android/car/obd2app/Obd2CollectionTask.java
@@ -22,11 +22,10 @@
import android.os.SystemClock;
import android.util.JsonWriter;
import android.util.Log;
-
import com.android.car.obd2.Obd2Connection;
+import com.android.car.obd2.Obd2FreezeFrameGenerator;
import com.android.car.obd2.Obd2LiveFrameGenerator;
import com.android.car.obd2.connections.BluetoothConnection;
-
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -37,6 +36,7 @@
public class Obd2CollectionTask extends TimerTask {
private final Obd2Connection mConnection;
private final Obd2LiveFrameGenerator mLiveFrameGenerator;
+ private final Obd2FreezeFrameGenerator mFreezeFrameGenerator;
private final StatusNotification mStatusNotification;
private final JsonWriter mJsonWriter;
@@ -79,6 +79,7 @@
try {
synchronized (mJsonWriter) {
mLiveFrameGenerator.generate(mJsonWriter);
+ mFreezeFrameGenerator.generate(mJsonWriter);
mJsonWriter.flush();
}
mStatusNotification.notifyDataCapture();
@@ -88,7 +89,7 @@
}
Obd2CollectionTask(Context context, StatusNotification statusNotification, String deviceAddress)
- throws IOException, InterruptedException {
+ throws IOException, InterruptedException {
if (!isExternalStorageWriteable())
throw new IOException("Cannot write data to external storage");
mStatusNotification = statusNotification;
@@ -99,10 +100,11 @@
}
mConnection = new Obd2Connection(bluetoothConnection);
mLiveFrameGenerator = new Obd2LiveFrameGenerator(mConnection);
+ mFreezeFrameGenerator = new Obd2FreezeFrameGenerator(mConnection);
mJsonWriter =
- new JsonWriter(
- new OutputStreamWriter(
- new FileOutputStream(getFilenameForStorage(context))));
+ new JsonWriter(
+ new OutputStreamWriter(
+ new FileOutputStream(getFilenameForStorage(context))));
mJsonWriter.beginArray();
}
diff --git a/tests/obd2_test/src/com/android/car/obd2/test/IntegerArrayStreamTest.java b/tests/obd2_test/src/com/android/car/obd2/test/IntegerArrayStreamTest.java
index 3c3b1e6..e9bf98b 100644
--- a/tests/obd2_test/src/com/android/car/obd2/test/IntegerArrayStreamTest.java
+++ b/tests/obd2_test/src/com/android/car/obd2/test/IntegerArrayStreamTest.java
@@ -59,4 +59,14 @@
assertFalse(stream.expect(4, 6));
assertEquals(5, stream.peek());
}
+
+ @Test
+ public void testIsEmpty() {
+ IntegerArrayStream stream = new IntegerArrayStream(DATA_SET);
+ assertFalse(stream.isEmpty());
+ stream.expect(1, 2, 3, 4, 5);
+ assertFalse(stream.isEmpty());
+ stream.consume();
+ assertTrue(stream.isEmpty());
+ }
}
diff --git a/tests/obd2_test/src/com/android/car/obd2/test/Obd2CommandTest.java b/tests/obd2_test/src/com/android/car/obd2/test/Obd2CommandTest.java
index b342cbc..f4ac13d 100644
--- a/tests/obd2_test/src/com/android/car/obd2/test/Obd2CommandTest.java
+++ b/tests/obd2_test/src/com/android/car/obd2/test/Obd2CommandTest.java
@@ -106,7 +106,7 @@
String[] commandToSend = new String[] {String.format("02%02X 01\r", pid)};
String[] responseToGet =
- new String[] {String.format("02 %02X 01 %s", pid, responseBytes), OBD2_PROMPT};
+ new String[] {String.format("42 %02X 01 %s", pid, responseBytes), OBD2_PROMPT};
MockObd2UnderlyingTransport transport =
new MockObd2UnderlyingTransport(
@@ -134,7 +134,7 @@
String[] commandToSend = new String[] {String.format("02%02X 01\r", pid)};
String[] responseToGet =
- new String[] {String.format("02 %02X 01 %s", pid, responseBytes), OBD2_PROMPT};
+ new String[] {String.format("42 %02X 01 %s", pid, responseBytes), OBD2_PROMPT};
MockObd2UnderlyingTransport transport =
new MockObd2UnderlyingTransport(
@@ -213,7 +213,7 @@
@Test
public void testRpm() {
- checkCommand(0x0C, "12 0F", 4611);
+ checkCommand(0x0C, "12 0F", 1155);
}
@Test
diff --git a/tests/obd2_test/src/com/android/car/obd2/test/Obd2FreezeFrameGeneratorTest.java b/tests/obd2_test/src/com/android/car/obd2/test/Obd2FreezeFrameGeneratorTest.java
new file mode 100644
index 0000000..20919a1
--- /dev/null
+++ b/tests/obd2_test/src/com/android/car/obd2/test/Obd2FreezeFrameGeneratorTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 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.obd2.test;
+
+import static android.hardware.automotive.vehicle.V2_1.VehicleProperty.OBD2_FREEZE_FRAME;
+import static com.android.car.obd2.test.Utils.concatIntArrays;
+import static com.android.car.obd2.test.Utils.stringsToIntArray;
+import static org.junit.Assert.*;
+
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import com.android.car.obd2.Obd2Connection;
+import com.android.car.obd2.Obd2FreezeFrameGenerator;
+import com.android.car.vehiclehal.DiagnosticJsonReader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import org.junit.Test;
+
+public class Obd2FreezeFrameGeneratorTest {
+ private static final String[] EXPECTED_INIT_COMMANDS =
+ new String[] {
+ "ATD\r", "ATZ\r", "AT E0\r", "AT L0\r", "AT S0\r", "AT H0\r", "AT SP 0\r"
+ };
+
+ private static final String OBD2_PROMPT = ">";
+
+ private static final String[] EXPECTED_INIT_RESPONSES =
+ new String[] {
+ OBD2_PROMPT,
+ OBD2_PROMPT,
+ OBD2_PROMPT,
+ OBD2_PROMPT,
+ OBD2_PROMPT,
+ OBD2_PROMPT,
+ OBD2_PROMPT
+ };
+
+ private static final String[] EXPECTED_DISCOVERY_COMMANDS =
+ new String[] {"0100\r", "0120\r", "0140\r", "0160\r"};
+
+ private static final String[] EXPECTED_DISCOVERY_RESPONSES =
+ new String[] {"00 00 00 18 00 00", OBD2_PROMPT, OBD2_PROMPT, OBD2_PROMPT, OBD2_PROMPT};
+
+ private static final String[] EXPECTED_MODE3_COMMANDS = new String[] {"03\r"};
+
+ private static final String[] EXPECTED_MODE3_RESPONSES =
+ new String[] {
+ "0300E0:4306010002001:030043008200C12:0000000000000043010101", OBD2_PROMPT
+ };
+
+ private static final String[] EXPECTED_FRAME_COMMANDS =
+ new String[] {"020C 00\r", "020D 00\r", "020C 01\r", "020D 01\r"};
+
+ private static final String[] EXPECTED_FRAME_RESPONSES =
+ new String[] {
+ "42 0C 00 12 0F",
+ OBD2_PROMPT,
+ "42 0D 00 82",
+ OBD2_PROMPT,
+ "42 0C 01 12 0F",
+ OBD2_PROMPT,
+ "42 0D 01 83",
+ OBD2_PROMPT
+ };
+
+ @Test
+ public void testObd2FreezeFrameGeneration() throws Exception {
+ MockObd2UnderlyingTransport transport =
+ new MockObd2UnderlyingTransport(
+ concatIntArrays(
+ stringsToIntArray(EXPECTED_INIT_COMMANDS),
+ stringsToIntArray(EXPECTED_DISCOVERY_COMMANDS),
+ stringsToIntArray(EXPECTED_MODE3_COMMANDS),
+ stringsToIntArray(EXPECTED_FRAME_COMMANDS)),
+ concatIntArrays(
+ stringsToIntArray(EXPECTED_INIT_RESPONSES),
+ stringsToIntArray(EXPECTED_DISCOVERY_RESPONSES),
+ stringsToIntArray(EXPECTED_MODE3_RESPONSES),
+ stringsToIntArray(EXPECTED_FRAME_RESPONSES)));
+ Obd2Connection obd2Connection = new Obd2Connection(transport);
+ Obd2FreezeFrameGenerator obd2Generator = new Obd2FreezeFrameGenerator(obd2Connection);
+ StringWriter stringWriter = new StringWriter(1024);
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ jsonWriter.beginArray();
+ obd2Generator.generate(jsonWriter);
+ jsonWriter.endArray();
+ JsonReader jsonReader = new JsonReader(new StringReader(stringWriter.toString()));
+ DiagnosticJsonReader diagnosticJsonReader = new DiagnosticJsonReader();
+ jsonReader.beginArray();
+ VehiclePropValue vehiclePropValue = diagnosticJsonReader.build(jsonReader);
+ assertEquals(OBD2_FREEZE_FRAME, vehiclePropValue.prop);
+ assertEquals(1155, (long) vehiclePropValue.value.int32Values.get(0xC));
+ assertEquals(130, (long) vehiclePropValue.value.int32Values.get(0xD));
+ vehiclePropValue = diagnosticJsonReader.build(jsonReader);
+ assertEquals(OBD2_FREEZE_FRAME, vehiclePropValue.prop);
+ assertEquals(1155, (long) vehiclePropValue.value.int32Values.get(0xC));
+ assertEquals(131, (long) vehiclePropValue.value.int32Values.get(0xD));
+ }
+}
diff --git a/tests/obd2_test/src/com/android/car/obd2/test/Obd2LiveFrameGeneratorTest.java b/tests/obd2_test/src/com/android/car/obd2/test/Obd2LiveFrameGeneratorTest.java
index e2022c1..ba3dbb8 100644
--- a/tests/obd2_test/src/com/android/car/obd2/test/Obd2LiveFrameGeneratorTest.java
+++ b/tests/obd2_test/src/com/android/car/obd2/test/Obd2LiveFrameGeneratorTest.java
@@ -54,7 +54,7 @@
new String[] {"0100\r", "0120\r", "0140\r", "0160\r"};
private static final String[] EXPECTED_DISCOVERY_RESPONSES =
- new String[] {"00 00 00 0C 00 00", OBD2_PROMPT, OBD2_PROMPT, OBD2_PROMPT, OBD2_PROMPT};
+ new String[] {"00 00 00 18 00 00", OBD2_PROMPT, OBD2_PROMPT, OBD2_PROMPT, OBD2_PROMPT};
private static final String[] EXPECTED_FRAME_COMMANDS = new String[] {"010C\r", "010D\r"};
@@ -82,7 +82,7 @@
DiagnosticJsonReader diagnosticJsonReader = new DiagnosticJsonReader();
VehiclePropValue vehiclePropValue = diagnosticJsonReader.build(jsonReader);
assertEquals(OBD2_LIVE_FRAME, vehiclePropValue.prop);
- assertEquals(4611, (long) vehiclePropValue.value.int32Values.get(0xC));
+ assertEquals(1155, (long) vehiclePropValue.value.int32Values.get(0xC));
assertEquals(130, (long) vehiclePropValue.value.int32Values.get(0xD));
}
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
new file mode 100644
index 0000000..c76cc4a
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017 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.vehiclehal.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.car.Car;
+import android.car.hardware.CarSensorManager;
+import android.car.hardware.CarSensorManager.OnSensorChangedListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.hardware.automotive.vehicle.V2_0.IVehicle;
+import android.hardware.automotive.vehicle.V2_0.StatusCode;
+import android.hardware.automotive.vehicle.V2_0.VehicleArea;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.google.android.collect.Lists;
+
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This test suite will make e2e test and measure some performance characteristics. The main idea
+ * is to send command to Vehicle HAL to generate some events with certain time interval and capture
+ * these events through car public API, e.g. CarSensorManager.
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class E2ePerformanceTest {
+ private static String TAG = Utils.concatTag(E2ePerformanceTest.class);
+
+ private IVehicle mVehicle;
+ private final CarConnectionListener mConnectionListener = new CarConnectionListener();
+ private Context mContext;
+ private Car mCar;
+
+ private static Handler sEventHandler;
+ private static final HandlerThread sHandlerThread = new HandlerThread(TAG);
+
+ private static final int DEFAULT_WAIT_TIMEOUT_MS = 1000;
+
+ private static final int GENERATE_FAKE_DATA_CONTROLLING_PROPERTY = 0x0666
+ | VehiclePropertyGroup.VENDOR
+ | VehicleArea.GLOBAL
+ | VehiclePropertyType.COMPLEX;
+
+ private static final int CMD_START = 1;
+ private static final int CMD_STOP = 0;
+
+ private HalEventsGenerator mEventsGenerator;
+
+ @BeforeClass
+ public static void setupEventHandler() {
+ sHandlerThread.start();
+ sEventHandler = new Handler(sHandlerThread.getLooper());
+ }
+
+ @Before
+ public void connectToVehicleHal() throws Exception {
+ mVehicle = Utils.getVehicle();
+
+ mVehicle.getPropConfigs(Lists.newArrayList(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY),
+ (status, propConfigs) -> assumeTrue(status == StatusCode.OK));
+
+ mEventsGenerator = new HalEventsGenerator(mVehicle);
+ }
+
+ @Before
+ public void connectToCarService() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ mCar = Car.createCar(mContext, mConnectionListener, sEventHandler);
+ assertNotNull(mCar);
+ mCar.connect();
+ mConnectionListener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS);
+ }
+
+ @After
+ public void disconnect() throws Exception {
+ if (mVehicle != null) {
+ mEventsGenerator.stop();
+ mVehicle = null;
+ mEventsGenerator = null;
+ }
+ if (mCar != null) {
+ mCar.disconnect();
+ mCar = null;
+ }
+ }
+
+ @Test
+ public void singleOnChangeProperty() throws Exception {
+ final int PROP = CarSensorManager.SENSOR_TYPE_ODOMETER;
+ // Expecting to receive at least 10 events within 150ms.
+ final int EXPECTED_EVENTS = 10;
+ final int EXPECTED_TIME_DURATION_MS = 150;
+ final float INITIAL_VALUE = 1000;
+ final float INCREMENT = 1.0f;
+
+ CarSensorManager mgr = (CarSensorManager) mCar.getCarManager(Car.SENSOR_SERVICE);
+ assertNotNull(mgr);
+ assertTrue(mgr.isSensorSupported(CarSensorManager.SENSOR_TYPE_ODOMETER));
+
+ mEventsGenerator
+ .setIntervalMs(10)
+ .setInitialValue(INITIAL_VALUE)
+ .setIncrement(INCREMENT)
+ .setDispersion(100)
+ .start(VehicleProperty.PERF_ODOMETER);
+
+ CountDownLatch latch = new CountDownLatch(EXPECTED_EVENTS);
+ OnSensorChangedListener listener = event -> latch.countDown();
+
+ mgr.registerListener(listener, PROP, CarSensorManager.SENSOR_RATE_FASTEST);
+ try {
+ assertTrue(latch.await(EXPECTED_TIME_DURATION_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ mgr.unregisterListener(listener);
+ }
+ }
+
+ private static class CarConnectionListener implements ServiceConnection {
+ private final Semaphore mConnectionWait = new Semaphore(0);
+
+ void waitForConnection(long timeoutMs) throws InterruptedException {
+ mConnectionWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mConnectionWait.release();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) { }
+ }
+
+ static class HalEventsGenerator {
+ private final IVehicle mVehicle;
+
+ private long mIntervalMs;
+ private float mInitialValue;
+ private float mDispersion;
+ private float mIncrement;
+
+ HalEventsGenerator(IVehicle vehicle) {
+ mVehicle = vehicle;
+ reset();
+ }
+
+ HalEventsGenerator reset() {
+ mIntervalMs = 1000;
+ mInitialValue = 1000;
+ mDispersion = 0;
+ mInitialValue = 0;
+ return this;
+ }
+
+ HalEventsGenerator setIntervalMs(long intervalMs) {
+ mIntervalMs = intervalMs;
+ return this;
+ }
+
+ HalEventsGenerator setInitialValue(float initialValue) {
+ mInitialValue = initialValue;
+ return this;
+ }
+
+ HalEventsGenerator setDispersion(float dispersion) {
+ mDispersion = dispersion;
+ return this;
+ }
+
+ HalEventsGenerator setIncrement(float increment) {
+ mIncrement = increment;
+ return this;
+ }
+
+ void start(int propId) throws RemoteException {
+ VehiclePropValue request =
+ VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
+ .addIntValue(CMD_START, propId)
+ .setInt64Value(mIntervalMs * 1000_000)
+ .addFloatValue(mInitialValue, mDispersion, mIncrement)
+ .build();
+ assertEquals(StatusCode.OK, mVehicle.set(request));
+ }
+
+ void stop() throws RemoteException {
+ stop(0);
+ }
+
+ void stop(int propId) throws RemoteException {
+ VehiclePropValue request =
+ VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
+ .addIntValue(CMD_STOP, propId)
+ .build();
+ assertEquals(StatusCode.OK, mVehicle.set(request));
+ }
+ }
+}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2FreezeFrameTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2FreezeFrameTest.java
index 19047f2..23b9dbe 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2FreezeFrameTest.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2FreezeFrameTest.java
@@ -16,64 +16,45 @@
package com.android.car.vehiclehal.test;
-import static com.android.car.vehiclehal.test.Utils.dumpVehiclePropValue;
import static com.android.car.vehiclehal.test.Utils.isVhalPropertyAvailable;
import static com.android.car.vehiclehal.test.Utils.readVhalProperty;
-import static com.android.car.vehiclehal.test.Utils.tryWithDeadline;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
-import android.annotation.Nullable;
+import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.StatusCode;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_1.IVehicle;
import android.hardware.automotive.vehicle.V2_1.VehicleProperty;
import android.os.RemoteException;
import android.util.Log;
+
import com.android.car.vehiclehal.VehiclePropValueBuilder;
-import java.util.Objects;
+
import org.junit.Before;
import org.junit.Test;
/** Test retrieving the OBD2_FREEZE_FRAME property from VHAL */
public class Obd2FreezeFrameTest {
- private static final String TAG = Obd2FreezeFrameTest.class.getSimpleName();
- private static final long WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS = 10_000;
+ private static final String TAG = Utils.concatTag(Obd2FreezeFrameTest.class);
private IVehicle mVehicle = null;
@Before
public void setUp() throws Exception {
- mVehicle = Objects.requireNonNull(getVehicle(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS));
- }
-
- @Nullable
- private IVehicle getVehicle(long waitMilliseconds) {
- return tryWithDeadline(
- waitMilliseconds,
- () -> {
- try {
- return IVehicle.getService();
- } catch (RemoteException e) {
- Log.w(TAG, "attempt to get IVehicle service " +
- " caused RemoteException: ", e);
- return null;
- }
- });
+ mVehicle = Utils.getVehicle();
+ assumeTrue("Freeze frame not available, test-case ignored.", isFreezeFrameAvailable());
}
@Test
public void testFreezeFrame() throws RemoteException {
- if (!isFreezeFrameAvailable()) {
- Log.i(TAG, "freeze frame not available; returning - our job here is done");
- return;
- }
readVhalProperty(
mVehicle,
VehicleProperty.OBD2_FREEZE_FRAME_INFO,
(Integer status, VehiclePropValue value) -> {
assertEquals(StatusCode.OK, status.intValue());
assertNotNull("OBD2_FREEZE_FRAME_INFO is supported; should not be null", value);
- Log.i(TAG, "dump of OBD2_FREEZE_FRAME_INFO:\n" + dumpVehiclePropValue(value));
+ Log.i(TAG, "dump of OBD2_FREEZE_FRAME_INFO:\n" + value);
for(long timestamp: value.value.int64Values) {
Log.i(TAG, "timestamp: " + timestamp);
readVhalProperty(
@@ -83,8 +64,9 @@
.build(),
(Integer frameStatus, VehiclePropValue freezeFrame) -> {
if (StatusCode.OK == frameStatus.intValue()) {
- assertNotNull("OBD2_FREEZE_FRAME read OK; should not be null", freezeFrame);
- Log.i(TAG, "dump of OBD2_FREEZE_FRAME:\n" + dumpVehiclePropValue(freezeFrame));
+ assertNotNull("OBD2_FREEZE_FRAME read OK; should not be null",
+ freezeFrame);
+ Log.i(TAG, "dump of OBD2_FREEZE_FRAME:\n" + freezeFrame);
assertEquals(freezeFrame.timestamp, timestamp);
}
return true;
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2LiveFrameTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2LiveFrameTest.java
index 1f17358..8e14db3 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2LiveFrameTest.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Obd2LiveFrameTest.java
@@ -16,63 +16,43 @@
package com.android.car.vehiclehal.test;
-import static com.android.car.vehiclehal.test.Utils.dumpVehiclePropValue;
import static com.android.car.vehiclehal.test.Utils.isVhalPropertyAvailable;
import static com.android.car.vehiclehal.test.Utils.readVhalProperty;
-import static com.android.car.vehiclehal.test.Utils.tryWithDeadline;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
-import android.annotation.Nullable;
+import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.StatusCode;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_1.IVehicle;
import android.hardware.automotive.vehicle.V2_1.VehicleProperty;
import android.os.RemoteException;
import android.util.Log;
-import java.util.Objects;
+
import org.junit.Before;
import org.junit.Test;
/** Test retrieving the OBD2_LIVE_FRAME property from VHAL */
public class Obd2LiveFrameTest {
- private static final String TAG = Obd2LiveFrameTest.class.getSimpleName();
- private static final long WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS = 10_000;
+ private static final String TAG = Utils.concatTag(Obd2LiveFrameTest.class);
private IVehicle mVehicle = null;
@Before
public void setUp() throws Exception {
- mVehicle = Objects.requireNonNull(getVehicle(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS));
- }
-
- @Nullable
- private IVehicle getVehicle(long waitMilliseconds) {
- return tryWithDeadline(
- waitMilliseconds,
- () -> {
- try {
- return IVehicle.getService();
- } catch (RemoteException e) {
- Log.w(TAG, "attempt to get IVehicle service " +
- " caused RemoteException: ", e);
- return null;
- }
- });
+ mVehicle = Utils.getVehicle();
+ assumeTrue("Live frame not available, test-case ignored.", isLiveFrameAvailable());
}
@Test
public void testLiveFrame() throws RemoteException {
- if (!isLiveFrameAvailable()) {
- Log.i(TAG, "live frame not available; returning - our job here is done");
- return;
- }
readVhalProperty(
mVehicle,
VehicleProperty.OBD2_LIVE_FRAME,
(Integer status, VehiclePropValue value) -> {
assertEquals(StatusCode.OK, status.intValue());
assertNotNull("OBD2_LIVE_FRAME is supported; should not be null", value);
- Log.i(TAG, "dump of OBD2_LIVE_FRAME:\n" + dumpVehiclePropValue(value));
+ Log.i(TAG, "dump of OBD2_LIVE_FRAME:\n" + value);
return true;
});
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java
index 67c5c2d..5221907 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java
@@ -16,65 +16,25 @@
package com.android.car.vehiclehal.test;
-import static android.os.SystemClock.elapsedRealtime;
-
import android.annotation.Nullable;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.os.RemoteException;
import android.util.Log;
+
import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
+import java.util.NoSuchElementException;
import java.util.Objects;
final class Utils {
private Utils() {}
- private static final String TAG = Utils.class.getSimpleName();
+ private static final String TAG = concatTag(Utils.class);
- @Nullable
- static <T> T tryWithDeadline(long waitMilliseconds, java.util.function.Supplier<T> f) {
- f = Objects.requireNonNull(f);
- T object = f.get();
- long start = elapsedRealtime();
- while (object == null && (start + waitMilliseconds) > elapsedRealtime()) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- throw new RuntimeException("Sleep was interrupted", e);
- }
-
- object = f.get();
- }
- return object;
- }
-
- static String dumpVehiclePropValue(VehiclePropValue vpv) {
- vpv = Objects.requireNonNull(vpv);
- return "prop = "
- + vpv.prop
- + '\n'
- + "areaId = "
- + vpv.areaId
- + '\n'
- + "timestamp = "
- + vpv.timestamp
- + '\n'
- + "int32Values = "
- + vpv.value.int32Values
- + '\n'
- + "floatValues = "
- + vpv.value.floatValues
- + '\n'
- + "int64Values ="
- + vpv.value.int64Values
- + '\n'
- + "bytes = "
- + vpv.value.bytes
- + '\n'
- + "string = "
- + vpv.value.stringValue
- + '\n';
+ static String concatTag(Class clazz) {
+ return "VehicleHalTest." + clazz.getSimpleName();
}
static boolean isVhalPropertyAvailable(IVehicle vehicle, int prop) throws RemoteException {
@@ -99,8 +59,7 @@
}
});
} catch (RemoteException e) {
- Log.w(TAG, "attempt to read VHAL property " +
- dumpVehiclePropValue(request) + " caused RemoteException: ", e);
+ Log.w(TAG, "attempt to read VHAL property " + request + " caused RemoteException: ", e);
}
return vpv[0];
}
@@ -121,4 +80,17 @@
VehiclePropValueBuilder.newBuilder(propertyId).setAreaId(areaId).build();
return readVhalProperty(vehicle, request, f);
}
+
+ @Nullable
+ static IVehicle getVehicle() throws RemoteException {
+ IVehicle service;
+ try {
+ service = android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
+ } catch (NoSuchElementException ex) {
+ Log.d(TAG, "Couldn't connect to vehicle@2.1, connecting to vehicle@2.0...");
+ service = IVehicle.getService();
+ }
+ Log.d(TAG, "Connected to IVehicle service: " + service);
+ return service;
+ }
}