Remove LOCAL_CLANG am: 7a3f3ef53e am: 1426ca0155 am: 97f6422cd3
am: 633e098d12

Change-Id: Idb9e2c2acae2649c49911329b45801cf647c73b0
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index 6f32dd7..568d611 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -32,11 +32,13 @@
     field public static final java.lang.String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
     field public static final deprecated 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_STORAGE_MONITORING = "android.car.permission.STORAGE_MONITORING";
     field public static final java.lang.String PERMISSION_VEHICLE_DYNAMICS_STATE = "android.car.permission.VEHICLE_DYNAMICS_STATE";
     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 STORAGE_MONITORING_SERVICE = "storage_monitoring";
     field public static final java.lang.String TEST_SERVICE = "car-service-test";
     field public static final java.lang.String VENDOR_EXTENSION_SERVICE = "vendor_extension";
     field public static final int VERSION = 3; // 0x3
@@ -485,6 +487,7 @@
     method public boolean isFreezeFrameNotificationSupported() throws android.car.CarNotConnectedException;
     method public boolean isGetFreezeFrameSupported() throws android.car.CarNotConnectedException;
     method public boolean isLiveFrameSupported() throws android.car.CarNotConnectedException;
+    method public boolean isSelectiveClearFreezeFramesSupported() throws android.car.CarNotConnectedException;
     method public void onCarDisconnected();
     method public boolean registerListener(android.car.diagnostic.CarDiagnosticManager.OnDiagnosticEventListener, int, int) throws android.car.CarNotConnectedException, java.lang.IllegalArgumentException;
     method public void unregisterListener(android.car.diagnostic.CarDiagnosticManager.OnDiagnosticEventListener);
@@ -998,6 +1001,45 @@
 
 }
 
+package android.car.storagemonitoring {
+
+  public final class CarStorageMonitoringManager {
+    method public int getPreEolIndicatorStatus() throws android.car.CarNotConnectedException;
+    method public android.car.storagemonitoring.WearEstimate getWearEstimate() throws android.car.CarNotConnectedException;
+    field public static final int PRE_EOL_INFO_NORMAL = 1; // 0x1
+    field public static final int PRE_EOL_INFO_UNKNOWN = 0; // 0x0
+    field public static final int PRE_EOL_INFO_URGENT = 3; // 0x3
+    field public static final int PRE_EOL_INFO_WARNING = 2; // 0x2
+  }
+
+  public class WearEstimate implements android.os.Parcelable {
+    ctor public WearEstimate(int, int);
+    ctor public WearEstimate(android.os.Parcel);
+    ctor public WearEstimate(android.util.JsonReader) throws java.io.IOException;
+    method public int describeContents();
+    method public void writeToJson(android.util.JsonWriter) throws java.io.IOException;
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.car.storagemonitoring.WearEstimate> CREATOR;
+    field public static final int UNKNOWN = -1; // 0xffffffff
+    field public final int typeA;
+    field public final int typeB;
+  }
+
+  public class WearEstimateChange implements android.os.Parcelable {
+    ctor public WearEstimateChange(android.car.storagemonitoring.WearEstimate, android.car.storagemonitoring.WearEstimate, long, Instant, boolean);
+    ctor public WearEstimateChange(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.storagemonitoring.WearEstimateChange> CREATOR;
+    field public final Instant dateAtChange;
+    field public final boolean isAcceptableDegradation;
+    field public final android.car.storagemonitoring.WearEstimate newEstimate;
+    field public final android.car.storagemonitoring.WearEstimate oldEstimate;
+    field public final long uptimeAtChange;
+  }
+
+}
+
 package android.car.test {
 
   public class CarTestManagerBinderWrapper {
@@ -1008,3 +1050,112 @@
 
 }
 
+package android.car.vms {
+
+  public final class VmsAssociatedLayer implements android.os.Parcelable {
+    ctor public VmsAssociatedLayer(android.car.vms.VmsLayer, java.util.Set<java.lang.Integer>);
+    method public int describeContents();
+    method public java.util.Set<java.lang.Integer> getPublisherIds();
+    method public android.car.vms.VmsLayer getVmsLayer();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.car.vms.VmsAssociatedLayer> CREATOR;
+  }
+
+  public final class VmsLayer implements android.os.Parcelable {
+    ctor public VmsLayer(int, int, int);
+    method public int describeContents();
+    method public int getSubtype();
+    method public int getType();
+    method public int getVersion();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.car.vms.VmsLayer> CREATOR;
+  }
+
+  public final class VmsLayerDependency implements android.os.Parcelable {
+    ctor public VmsLayerDependency(android.car.vms.VmsLayer, java.util.Set<android.car.vms.VmsLayer>);
+    ctor public VmsLayerDependency(android.car.vms.VmsLayer);
+    method public int describeContents();
+    method public java.util.Set<android.car.vms.VmsLayer> getDependencies();
+    method public android.car.vms.VmsLayer getLayer();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.car.vms.VmsLayerDependency> CREATOR;
+  }
+
+  public final class VmsLayersOffering implements android.os.Parcelable {
+    ctor public VmsLayersOffering(java.util.Set<android.car.vms.VmsLayerDependency>, int);
+    method public int describeContents();
+    method public java.util.Set<android.car.vms.VmsLayerDependency> getDependencies();
+    method public int getPublisherId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.car.vms.VmsLayersOffering> CREATOR;
+  }
+
+  public final class VmsOperationRecorder {
+    ctor public VmsOperationRecorder(android.car.vms.VmsOperationRecorder.Writer);
+    method public void addHalSubscription(int, android.car.vms.VmsLayer);
+    method public void addPromiscuousSubscription(int);
+    method public void addSubscription(int, android.car.vms.VmsLayer);
+    method public static android.car.vms.VmsOperationRecorder get();
+    method public void getPublisherId(int);
+    method public void removeHalSubscription(int, android.car.vms.VmsLayer);
+    method public void removePromiscuousSubscription(int);
+    method public void removeSubscription(int, android.car.vms.VmsLayer);
+    method public void setHalPublisherLayersOffering(android.car.vms.VmsLayersOffering);
+    method public void setLayersOffering(android.car.vms.VmsLayersOffering);
+    method public void setPublisherLayersOffering(android.car.vms.VmsLayersOffering);
+    method public void startMonitoring();
+    method public void stopMonitoring();
+    method public void subscribe(android.car.vms.VmsLayer);
+    method public void subscribe(android.car.vms.VmsLayer, int);
+    method public void unsubscribe(android.car.vms.VmsLayer);
+    method public void unsubscribe(android.car.vms.VmsLayer, int);
+  }
+
+  public static class VmsOperationRecorder.Writer {
+    ctor public VmsOperationRecorder.Writer();
+    method public boolean isEnabled();
+    method public void write(java.lang.String);
+  }
+
+  public abstract class VmsPublisherClientService extends android.app.Service {
+    ctor public VmsPublisherClientService();
+    method public final int getPublisherId(byte[]);
+    method public final android.car.vms.VmsSubscriptionState getSubscriptions();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public final boolean onUnbind(android.content.Intent);
+    method protected abstract void onVmsPublisherServiceReady();
+    method public abstract void onVmsSubscriptionChange(android.car.vms.VmsSubscriptionState);
+    method public final void publish(android.car.vms.VmsLayer, int, byte[]);
+    method public final void setLayersOffering(android.car.vms.VmsLayersOffering);
+  }
+
+  public final class VmsSubscriberManager {
+    ctor public VmsSubscriberManager(android.os.IBinder, android.os.Handler);
+    method public byte[] getPublisherInfo(int) throws android.car.CarNotConnectedException, java.lang.IllegalStateException;
+    method public void registerClientCallback(android.car.vms.VmsSubscriberManager.VmsSubscriberClientCallback) throws android.car.CarNotConnectedException;
+    method public void startMonitoring() throws android.car.CarNotConnectedException;
+    method public void stopMonitoring();
+    method public void subscribe(android.car.vms.VmsLayer) throws android.car.CarNotConnectedException;
+    method public void subscribe(android.car.vms.VmsLayer, int) throws android.car.CarNotConnectedException;
+    method public void unregisterClientCallback() throws android.car.CarNotConnectedException;
+    method public void unsubscribe(android.car.vms.VmsLayer);
+    method public void unsubscribe(android.car.vms.VmsLayer, int);
+  }
+
+  public static abstract interface VmsSubscriberManager.VmsSubscriberClientCallback {
+    method public abstract void onLayersAvailabilityChanged(java.util.List<android.car.vms.VmsLayer>);
+    method public abstract void onVmsMessageReceived(android.car.vms.VmsLayer, byte[]);
+  }
+
+  public final class VmsSubscriptionState implements android.os.Parcelable {
+    ctor public VmsSubscriptionState(int, java.util.Set<android.car.vms.VmsLayer>, java.util.Set<android.car.vms.VmsAssociatedLayer>);
+    method public int describeContents();
+    method public java.util.Set<android.car.vms.VmsAssociatedLayer> getAssociatedLayers();
+    method public java.util.Set<android.car.vms.VmsLayer> getLayers();
+    method public int getSequenceNumber();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.car.vms.VmsSubscriptionState> CREATOR;
+  }
+
+}
+
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index c0b83f7..6101797 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -31,6 +31,7 @@
 import android.car.media.CarAudioManager;
 import android.car.navigation.CarNavigationStatusManager;
 import android.car.CarBluetoothManager;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
 import android.car.test.CarTestManagerBinderWrapper;
 import android.car.vms.VmsSubscriberManager;
 import android.content.ComponentName;
@@ -141,6 +142,12 @@
     public static final String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service";
 
     /**
+     * @hide
+     */
+    @SystemApi
+    public static final String STORAGE_MONITORING_SERVICE = "storage_monitoring";
+
+    /**
      * Service for testing. This is system app only feature.
      * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}.
      * @hide
@@ -293,6 +300,14 @@
     @SystemApi
     public static final String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.DIAGNOSTIC_CLEAR";
 
+    /**
+     * Permissions necessary to clear diagnostic information.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String PERMISSION_STORAGE_MONITORING = "android.car.permission.STORAGE_MONITORING";
+
     /** Type of car connection: platform runs directly in car. */
     public static final int CONNECTION_TYPE_EMBEDDED = 5;
 
@@ -655,12 +670,12 @@
                 manager = new CarTestManagerBinderWrapper(binder);
                 break;
             case VMS_SUBSCRIBER_SERVICE:
-                if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-                    manager = new VmsSubscriberManager(binder, mEventHandler);
-                }
+                manager = new VmsSubscriberManager(binder, mEventHandler);
                 break;
             case BLUETOOTH_SERVICE:
                 manager = new CarBluetoothManager(binder, mContext);
+            case STORAGE_MONITORING_SERVICE:
+                manager = new CarStorageMonitoringManager(binder);
         }
         return manager;
     }
diff --git a/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java b/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java
index 84cdd3e..88980bf 100644
--- a/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java
+++ b/car-lib/src/android/car/diagnostic/CarDiagnosticManager.java
@@ -349,8 +349,13 @@
     }
 
     /**
-     * Returns true if this vehicle supports clearing freeze frame timestamps.
+     * Returns true if this vehicle supports clearing all freeze frames.
      * This is only meaningful if freeze frame data is also supported.
+     *
+     * A return value of true for this method indicates that it is supported to call
+     * carDiagnosticManager.clearFreezeFrames()
+     * to delete all freeze frames stored in vehicle memory.
+     *
      * @return
      * @throws CarNotConnectedException
      */
@@ -365,6 +370,28 @@
         return false;
     }
 
+    /**
+     * Returns true if this vehicle supports clearing specific freeze frames by timestamp.
+     * This is only meaningful if freeze frame data is also supported.
+     *
+     * A return value of true for this method indicates that it is supported to call
+     * carDiagnosticManager.clearFreezeFrames(timestamp1, timestamp2, ...)
+     * to delete the freeze frames stored for the provided input timestamps, provided any exist.
+     *
+     * @return
+     * @throws CarNotConnectedException
+     */
+    public boolean isSelectiveClearFreezeFramesSupported() throws CarNotConnectedException {
+        try {
+            return mService.isSelectiveClearFreezeFramesSupported();
+        } catch (IllegalStateException e) {
+            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
+        } catch (RemoteException e) {
+            throw new CarNotConnectedException();
+        }
+        return false;
+    }
+
     private static class CarDiagnosticEventListenerToService
             extends Stub {
         private final WeakReference<CarDiagnosticManager> mManager;
diff --git a/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl b/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl
index 3d1808f..57443d8 100644
--- a/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl
+++ b/car-lib/src/android/car/diagnostic/ICarDiagnostic.aidl
@@ -74,4 +74,10 @@
      * Returns whether the underlying HAL supports clearing freeze frames.
      */
      boolean isClearFreezeFramesSupported() = 10;
+
+    /**
+     * Returns whether the underlying HAL supports clearing specific freeze frames specified
+     * by means of their timestamps.
+     */
+     boolean isSelectiveClearFreezeFramesSupported() = 11;
 }
diff --git a/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java b/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
new file mode 100644
index 0000000..aa2ad84
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
@@ -0,0 +1,94 @@
+/*
+ * 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 android.car.storagemonitoring;
+
+import android.annotation.SystemApi;
+import android.car.CarApiUtil;
+import android.car.CarManagerBase;
+import android.car.CarNotConnectedException;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * API for retrieving information and metrics about the flash storage.
+ *
+ * @hide
+ */
+@SystemApi
+public final class CarStorageMonitoringManager implements CarManagerBase {
+    private final ICarStorageMonitoring mService;
+
+    public static final int PRE_EOL_INFO_UNKNOWN = 0;
+    public static final int PRE_EOL_INFO_NORMAL = 1;
+    public static final int PRE_EOL_INFO_WARNING = 2;
+    public static final int PRE_EOL_INFO_URGENT = 3;
+
+    /** @hide */
+    public CarStorageMonitoringManager(IBinder service) {
+        mService = ICarStorageMonitoring.Stub.asInterface(service);
+    }
+
+    /** @hide */
+    @Override
+    public void onCarDisconnected() {
+    }
+
+    // ICarStorageMonitoring forwards
+
+    /**
+     * This method returns the value of the "pre EOL" indicator for the flash storage
+     * as retrieved during the current boot cycle.
+     *
+     * It will return either PRE_EOL_INFO_UNKNOWN if the value can't be determined,
+     * or one of PRE_EOL_INFO_{NORMAL|WARNING|URGENT} depending on the device state.
+     * @return
+     * @throws CarNotConnectedException
+     */
+    public int getPreEolIndicatorStatus() throws CarNotConnectedException {
+        try {
+            return mService.getPreEolIndicatorStatus();
+        } catch (IllegalStateException e) {
+            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
+        } catch (RemoteException e) {
+            throw new CarNotConnectedException();
+        }
+        return PRE_EOL_INFO_UNKNOWN;
+    }
+
+    /**
+     * This method returns the value of the wear estimate indicators for the flash storage
+     * as retrieved during the current boot cycle.
+     *
+     * The indicators are guaranteed to be a lower-bound on the actual wear of the storage.
+     * Current technology in common automotive usage offers estimates in 10% increments.
+     *
+     * If either or both indicators are not available, they will be reported as UNKNOWN.
+     * @return
+     * @throws CarNotConnectedException
+     */
+    public WearEstimate getWearEstimate() throws CarNotConnectedException {
+        try {
+            return mService.getWearEstimate();
+        } catch (IllegalStateException e) {
+            CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
+        } catch (RemoteException e) {
+            throw new CarNotConnectedException();
+        }
+        return new WearEstimate(WearEstimate.UNKNOWN, WearEstimate.UNKNOWN);
+    }
+
+}
+
diff --git a/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl b/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl
new file mode 100644
index 0000000..61910c5
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 android.car.storagemonitoring;
+
+import android.car.storagemonitoring.WearEstimate;
+
+/** @hide */
+interface ICarStorageMonitoring {
+  /**
+   * Returns the value of the PRE_EOL register.
+   */
+  int getPreEolIndicatorStatus() = 1;
+
+  /**
+   * Returns the current wear estimate indicators.
+   */
+  WearEstimate getWearEstimate() = 2;
+}
diff --git a/car-lib/src/android/car/storagemonitoring/WearEstimate.aidl b/car-lib/src/android/car/storagemonitoring/WearEstimate.aidl
new file mode 100644
index 0000000..c7ea505
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimate.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.car.storagemonitoring;
+
+parcelable WearEstimate;
diff --git a/car-lib/src/android/car/storagemonitoring/WearEstimate.java b/car-lib/src/android/car/storagemonitoring/WearEstimate.java
new file mode 100644
index 0000000..d7abc2b
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimate.java
@@ -0,0 +1,142 @@
+/*
+ * 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 android.car.storagemonitoring;
+
+import android.annotation.IntRange;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.JsonReader;
+import android.util.JsonToken;
+import android.util.JsonWriter;
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Wear-out information for flash storage.
+ *
+ * Contains a lower-bound estimate of the wear of "type A" (SLC) and "type B" (MLC) storage.
+ *
+ * Current technology offers wear data in increments of 10% (i.e. from 0 == new device up to
+ * 100 == worn-out device). It is possible for a storage device to only support one type of memory
+ * cell, in which case it is expected that the storage type not supported will have UNKNOWN wear.
+ *
+ * @hide
+ */
+@SystemApi
+public class WearEstimate implements Parcelable {
+    public static final int UNKNOWN = -1;
+
+    public static final Parcelable.Creator<WearEstimate> CREATOR =
+        new Parcelable.Creator<WearEstimate>() {
+            public WearEstimate createFromParcel(Parcel in) {
+                return new WearEstimate(in);
+            }
+
+            public WearEstimate[] newArray(int size) {
+                return new WearEstimate[size];
+            }
+        };
+
+    /**
+     * Wear estimate data for "type A" storage.
+     */
+    @IntRange(from=-1, to=100)
+    public final int typeA;
+
+    /**
+     * Wear estimate data for "type B" storage.
+     */
+    @IntRange(from=-1, to=100)
+    public final int typeB;
+
+    private static final int validateWearValue(int value) {
+        if (value == UNKNOWN) return value;
+        if ((value >= 0) && (value <= 100)) return value;
+        throw new IllegalArgumentException(value + " is not a valid wear estimate");
+    }
+
+    public WearEstimate(int typeA, int typeB) {
+        this.typeA = validateWearValue(typeA);
+        this.typeB = validateWearValue(typeB);
+    }
+
+    public WearEstimate(Parcel in) {
+        typeA = validateWearValue(in.readInt());
+        typeB = validateWearValue(in.readInt());
+    }
+
+    public WearEstimate(JsonReader in) throws IOException {
+        int typeA = UNKNOWN;
+        int typeB = UNKNOWN;
+        in.beginObject();
+        while (in.hasNext()) {
+            switch (in.nextName()) {
+                case "wearEstimateTypeA":
+                    typeA = validateWearValue(in.nextInt());
+                    break;
+                case "wearEstimateTypeB":
+                    typeB = validateWearValue(in.nextInt());
+                    break;
+            }
+        }
+        in.endObject();
+        this.typeA = typeA;
+        this.typeB = typeB;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(typeA);
+        dest.writeInt(typeB);
+    }
+
+    public void writeToJson(JsonWriter jsonWriter) throws IOException {
+        jsonWriter.beginObject();
+        jsonWriter.name("wearEstimateTypeA").value(typeA);
+        jsonWriter.name("wearEstimateTypeB").value(typeB);
+        jsonWriter.endObject();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof WearEstimate) {
+            WearEstimate wo = (WearEstimate)other;
+            return wo.typeA == typeA && wo.typeB == typeB;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(typeA, typeB);
+    }
+
+    private static final String wearValueToString(int value) {
+        if (value == UNKNOWN) return "unknown";
+        return value + "%";
+    }
+
+    @Override
+    public String toString() {
+        return "type A: " + wearValueToString(typeA) + ", type B: " + wearValueToString(typeB);
+    }
+}
diff --git a/car-lib/src/android/car/storagemonitoring/WearEstimateChange.aidl b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.aidl
new file mode 100644
index 0000000..49adfe5
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.car.storagemonitoring;
+
+parcelable WearEstimateChange;
diff --git a/car-lib/src/android/car/storagemonitoring/WearEstimateChange.java b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.java
new file mode 100644
index 0000000..5c80a31
--- /dev/null
+++ b/car-lib/src/android/car/storagemonitoring/WearEstimateChange.java
@@ -0,0 +1,143 @@
+/*
+ * 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 android.car.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.time.Instant;
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Change in wear-out information.
+ *
+ * Contains information about the first cycle during which the system detected a change
+ * in wear-out information of the flash storage.
+ *
+ * @hide
+ */
+@SystemApi
+public class WearEstimateChange implements Parcelable {
+    public static final Parcelable.Creator<WearEstimateChange> CREATOR =
+        new Parcelable.Creator<WearEstimateChange>() {
+            public WearEstimateChange createFromParcel(Parcel in) {
+                return new WearEstimateChange(in);
+            }
+
+            public WearEstimateChange[] newArray(int size) {
+                return new WearEstimateChange[size];
+            }
+        };
+
+    /**
+     * The previous wear estimate.
+     */
+    public final @NonNull WearEstimate oldEstimate;
+
+    /**
+     * The new wear estimate.
+     */
+    public final @NonNull WearEstimate newEstimate;
+
+    /**
+     * Total CarService uptime when this change was detected.
+     */
+    public final long uptimeAtChange;
+
+    /**
+     * Wall-clock time when this change was detected.
+     */
+    public final @NonNull Instant dateAtChange;
+
+    /**
+     * Whether this change was within the vendor range for acceptable flash degradation.
+     */
+    public final boolean isAcceptableDegradation;
+
+    public WearEstimateChange(WearEstimate oldEstimate,
+                              WearEstimate newEstimate,
+                              long uptimeAtChange,
+                              Instant dateAtChange,
+                              boolean isAcceptableDegradation) {
+        if (uptimeAtChange < 0) {
+            throw new IllegalArgumentException("uptimeAtChange must be >= 0");
+        }
+        this.oldEstimate = requireNonNull(oldEstimate);
+        this.newEstimate = requireNonNull(newEstimate);
+        this.uptimeAtChange = uptimeAtChange;
+        this.dateAtChange = requireNonNull(dateAtChange);
+        this.isAcceptableDegradation = isAcceptableDegradation;
+    }
+
+    public WearEstimateChange(Parcel in) {
+        oldEstimate = in.readParcelable(WearEstimate.class.getClassLoader());
+        newEstimate = in.readParcelable(WearEstimate.class.getClassLoader());
+        uptimeAtChange = in.readLong();
+        dateAtChange = Instant.ofEpochMilli(in.readLong());
+        isAcceptableDegradation = in.readInt() == 1;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(oldEstimate, flags);
+        dest.writeParcelable(newEstimate, flags);
+        dest.writeLong(uptimeAtChange);
+        dest.writeLong(dateAtChange.toEpochMilli());
+        dest.writeInt(isAcceptableDegradation ? 1 : 0);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof WearEstimateChange) {
+            WearEstimateChange wo = (WearEstimateChange)other;
+            return wo.isAcceptableDegradation == isAcceptableDegradation &&
+                wo.uptimeAtChange == uptimeAtChange &&
+                wo.dateAtChange.equals(dateAtChange) &&
+                wo.oldEstimate.equals(oldEstimate) &&
+                wo.newEstimate.equals(newEstimate);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(oldEstimate,
+                            newEstimate,
+                            uptimeAtChange,
+                            dateAtChange,
+                            isAcceptableDegradation);
+    }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "wear change{old level=%s, new level=%s, uptime=%d, date=%s, acceptable=%s}",
+                oldEstimate,
+                newEstimate,
+                uptimeAtChange,
+                dateAtChange,
+                isAcceptableDegradation ? "yes" : "no");
+    }
+
+}
diff --git a/car-lib/src/android/car/vms/VmsAssociatedLayer.java b/car-lib/src/android/car/vms/VmsAssociatedLayer.java
index 023fd9c..55ea541 100644
--- a/car-lib/src/android/car/vms/VmsAssociatedLayer.java
+++ b/car-lib/src/android/car/vms/VmsAssociatedLayer.java
@@ -16,7 +16,6 @@
 
 package android.car.vms;
 
-import android.car.annotation.FutureFeature;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,7 +26,6 @@
  *
  * @hide
  */
-@FutureFeature
 public final class VmsAssociatedLayer implements Parcelable {
 
     // The VmsLayer.
diff --git a/car-lib/src/android/car/vms/VmsLayer.java b/car-lib/src/android/car/vms/VmsLayer.java
index 9125796..b921230 100644
--- a/car-lib/src/android/car/vms/VmsLayer.java
+++ b/car-lib/src/android/car/vms/VmsLayer.java
@@ -16,7 +16,7 @@
 
 package android.car.vms;
 
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,7 +27,7 @@
  *
  * @hide
  */
-@FutureFeature
+@SystemApi
 public final class VmsLayer implements Parcelable {
 
     // The layer Type.
diff --git a/car-lib/src/android/car/vms/VmsLayerDependency.java b/car-lib/src/android/car/vms/VmsLayerDependency.java
index 3b82775..869fc84 100644
--- a/car-lib/src/android/car/vms/VmsLayerDependency.java
+++ b/car-lib/src/android/car/vms/VmsLayerDependency.java
@@ -16,7 +16,7 @@
 
 package android.car.vms;
 
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import java.util.ArrayList;
@@ -31,7 +31,7 @@
  *
  * @hide
  */
-@FutureFeature
+@SystemApi
 public final class VmsLayerDependency implements Parcelable {
     private final VmsLayer mLayer;
     private final Set<VmsLayer> mDependency;
diff --git a/car-lib/src/android/car/vms/VmsLayersOffering.java b/car-lib/src/android/car/vms/VmsLayersOffering.java
index 6abffc6..fc83696 100644
--- a/car-lib/src/android/car/vms/VmsLayersOffering.java
+++ b/car-lib/src/android/car/vms/VmsLayersOffering.java
@@ -16,7 +16,7 @@
 
 package android.car.vms;
 
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import java.util.ArrayList;
@@ -30,7 +30,7 @@
  *
  * @hide
  */
-@FutureFeature
+@SystemApi
 public final class VmsLayersOffering implements Parcelable {
 
     private final Set<VmsLayerDependency> mDependencies;
diff --git a/car-lib/src/android/car/vms/VmsOperationRecorder.java b/car-lib/src/android/car/vms/VmsOperationRecorder.java
index c873dce..bfb6055 100644
--- a/car-lib/src/android/car/vms/VmsOperationRecorder.java
+++ b/car-lib/src/android/car/vms/VmsOperationRecorder.java
@@ -1,6 +1,6 @@
 package android.car.vms;
 
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -24,7 +24,7 @@
  *
  * @hide
  */
-@FutureFeature
+@SystemApi
 public final class VmsOperationRecorder {
     private static final String TAG = "VmsOperationRecorder";
     private static final VmsOperationRecorder INSTANCE = new VmsOperationRecorder(new Writer());
diff --git a/car-lib/src/android/car/vms/VmsPublisherClientService.java b/car-lib/src/android/car/vms/VmsPublisherClientService.java
index 33ca1f3..024fc14 100644
--- a/car-lib/src/android/car/vms/VmsPublisherClientService.java
+++ b/car-lib/src/android/car/vms/VmsPublisherClientService.java
@@ -17,8 +17,8 @@
 package android.car.vms;
 
 
+import android.annotation.SystemApi;
 import android.app.Service;
-import android.car.annotation.FutureFeature;
 import android.content.Intent;
 import android.os.Handler;
 import android.os.IBinder;
@@ -46,7 +46,7 @@
  *
  * @hide
  */
-@FutureFeature
+@SystemApi
 public abstract class VmsPublisherClientService extends Service {
     private static final boolean DBG = true;
     private static final String TAG = "VmsPublisherClient";
diff --git a/car-lib/src/android/car/vms/VmsSubscriberManager.java b/car-lib/src/android/car/vms/VmsSubscriberManager.java
index 6f6377c..97d4d86 100644
--- a/car-lib/src/android/car/vms/VmsSubscriberManager.java
+++ b/car-lib/src/android/car/vms/VmsSubscriberManager.java
@@ -16,10 +16,10 @@
 
 package android.car.vms;
 
+import android.annotation.SystemApi;
 import android.car.Car;
 import android.car.CarManagerBase;
 import android.car.CarNotConnectedException;
-import android.car.annotation.FutureFeature;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -40,7 +40,7 @@
  *
  * @hide
  */
-@FutureFeature
+@SystemApi
 public final class VmsSubscriberManager implements CarManagerBase {
     private static final boolean DBG = true;
     private static final String TAG = "VmsSubscriberManager";
diff --git a/car-lib/src/android/car/vms/VmsSubscriptionState.java b/car-lib/src/android/car/vms/VmsSubscriptionState.java
index ea433f7..1aba30c 100644
--- a/car-lib/src/android/car/vms/VmsSubscriptionState.java
+++ b/car-lib/src/android/car/vms/VmsSubscriptionState.java
@@ -16,7 +16,6 @@
 
 package android.car.vms;
 
-import android.car.annotation.FutureFeature;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,7 +31,6 @@
  *
  * @hide
  */
-@FutureFeature
 public final class VmsSubscriptionState implements Parcelable {
     private final int mSequenceNumber;
     private final Set<VmsLayer> mLayers;
diff --git a/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java b/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java
index 55da870..462f320 100644
--- a/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java
+++ b/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java
@@ -25,5 +25,4 @@
     public static final boolean DEFAULT = false;
     /** product configuration in CarInfoManager */
     public static final boolean ENABLE_PRODUCT_CONFIGURATION_INFO = DEFAULT;
-    public static final boolean ENABLE_VEHICLE_MAP_SERVICE = DEFAULT;
 }
diff --git a/car-support-lib/proguard-extra-keeps.flags b/car-support-lib/proguard-extra-keeps.flags
index 5e67c6e..72ea927 100644
--- a/car-support-lib/proguard-extra-keeps.flags
+++ b/car-support-lib/proguard-extra-keeps.flags
@@ -17,3 +17,7 @@
     public static ... createCluster(...);
     public static ... createCustomImageCluster(...);
 }
+
+-keep class android.support.car.CarManagerBase {
+  *;
+}
diff --git a/car-support-lib/src/android/support/car/Car.java b/car-support-lib/src/android/support/car/Car.java
index a374d87..e0e3a0d 100644
--- a/car-support-lib/src/android/support/car/Car.java
+++ b/car-support-lib/src/android/support/car/Car.java
@@ -237,6 +237,7 @@
                         if (mConnectionState == STATE_DISCONNECTED) {
                             return;
                         }
+                        tearDownCarManagers();
                         mConnectionState = STATE_DISCONNECTED;
                     }
                     mCarConnectionCallback.onDisconnected(Car.this);
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index e39fb9e..05073e3 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -154,6 +154,11 @@
                 android:label="@string/car_permission_car_cluster_control"
                 android:description="@string/car_permission_desc_car_cluster_control" />
 
+    <permission android:name="android.car.permission.STORAGE_MONITORING"
+        android:protectionLevel="system|signature"
+        android:label="@string/car_permission_label_storage_monitoring"
+        android:description="@string/car_permission_desc_storage_monitoring" />
+
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
     <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 61cef59..68996d1 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -60,7 +60,7 @@
 
     <string name="instrumentClusterRendererService">android.car.cluster.sample/.SampleClusterServiceImpl</string>
 
-    <!--  Whether to enable Avtivity blocking for safety. When Activity blocking is enabled,
+    <!--  Whether to enable Activity blocking for safety. When Activity blocking is enabled,
           only whitelisted safe Activities will be allowed while car is not parked. -->
     <bool name="enableActivityBlockingForSafety">true</bool>
     <!--  Activity to be presented when un-safe activity is launched. Take a look at the javadoc of the
@@ -81,4 +81,13 @@
     <string-array translatable="false" name="vmsSafePermissions">
         <item>"android.permission.ACCESS_FINE_LOCATION"</item>
     </string-array>
+
+    <!-- Hours of uptime (excluding sleep) after which a 1% increase in the wear of the flash
+         storage in the head-unit is considered as acceptable level of wear. -->
+    <integer name="acceptableHoursPerOnePercentFlashWear">70</integer>
+
+    <!-- How often (in hours of uptime excluding sleep) CarService will flush to disk information
+         about the total running time of the head-unit. A shutdown or reboot of the head-unit
+          will always cause a flush of the uptime information, regardless of this setting. -->
+    <integer name="uptimeHoursIntervalBetweenUptimeDataWrite">5</integer>
 </resources>
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index 6cfff9a..37503ab 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -125,4 +125,9 @@
     <string name="car_permission_label_vms_subscriber">VMS subscriber</string>
     <!-- Permission text: apps can receive VMS messages from the car [CHAR LIMIT=NONE] -->
     <string name="car_permission_desc_vms_subscriber">Subscribe to vms messages</string>
+
+    <!-- Permission text: apps can monitor flash storage usage [CHAR LIMIT=NONE] -->
+    <string name="car_permission_label_storage_monitoring">Flash storage monitoring</string>
+    <!-- Permission text: apps can monitor flash storage usage [CHAR LIMIT=NONE] -->
+    <string name="car_permission_desc_storage_monitoring">Monitor flash storage usage</string>
 </resources>
diff --git a/service/src/com/android/car/CarAudioService.java b/service/src/com/android/car/CarAudioService.java
index f56b105..ab9d271 100644
--- a/service/src/com/android/car/CarAudioService.java
+++ b/service/src/com/android/car/CarAudioService.java
@@ -198,28 +198,32 @@
 
     @Override
     public void init() {
-        AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
-        builder.setLooper(Looper.getMainLooper());
-        boolean isFocusSupported = mAudioHal.isFocusSupported();
-        if (isFocusSupported) {
-            builder.setAudioPolicyFocusListener(mSystemFocusListener);
-            FocusState currentState = FocusState.create(mAudioHal.getCurrentFocusState());
-            int r = mAudioManager.requestAudioFocus(mBottomAudioFocusListener, mAttributeBottom,
-                    AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_FLAG_DELAY_OK);
-            synchronized (mLock) {
-                mCurrentFocusState = currentState;
-                mCurrentAudioContexts = 0;
-            }
-        }
         int audioHwVariant = mAudioHal.getHwVariant();
         AudioRoutingPolicy audioRoutingPolicy = AudioRoutingPolicy.create(mContext, audioHwVariant);
-        if (mUseDynamicRouting) {
-            setupDynamicRouting(audioRoutingPolicy, builder);
-        }
+
         AudioPolicy audioPolicy = null;
+        boolean isFocusSupported = mAudioHal.isFocusSupported();
+
+        // Do we need to install a custom audio policy?
         if (isFocusSupported || mUseDynamicRouting) {
+            AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
+            builder.setLooper(Looper.getMainLooper());
+            if (isFocusSupported) {
+                builder.setAudioPolicyFocusListener(mSystemFocusListener);
+                FocusState currentState = FocusState.create(mAudioHal.getCurrentFocusState());
+                int r = mAudioManager.requestAudioFocus(mBottomAudioFocusListener, mAttributeBottom,
+                        AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_FLAG_DELAY_OK);
+                synchronized (mLock) {
+                    mCurrentFocusState = currentState;
+                    mCurrentAudioContexts = 0;
+                }
+            }
+            if (mUseDynamicRouting) {
+                setupDynamicRouting(audioRoutingPolicy, builder);
+            }
             audioPolicy = builder.build();
         }
+
         mAudioHal.setFocusListener(this);
         mAudioHal.setAudioRoutingPolicy(audioRoutingPolicy);
         mAudioHal.setOnParameterChangeListener(this);
diff --git a/service/src/com/android/car/CarDiagnosticService.java b/service/src/com/android/car/CarDiagnosticService.java
index 809439c..3bd9979 100644
--- a/service/src/com/android/car/CarDiagnosticService.java
+++ b/service/src/com/android/car/CarDiagnosticService.java
@@ -411,6 +411,13 @@
             diagnosticCapabilities.isFreezeFrameSupported();
     }
 
+    public boolean isSelectiveClearFreezeFramesSupported() {
+        DiagnosticCapabilities diagnosticCapabilities =
+            getDiagnosticHal().getDiagnosticCapabilities();
+        return isClearFreezeFramesSupported() &&
+                diagnosticCapabilities.isSelectiveClearFreezeFramesSupported();
+    }
+
     // ICarDiagnostic implementations
 
     @Override
@@ -441,14 +448,18 @@
     @Override
     public boolean clearFreezeFrames(long... timestamps) {
         mDiagnosticClearPermission.assertGranted();
-        if (mDiagnosticHal.getDiagnosticCapabilities().isFreezeFrameClearSupported()) {
-            mFreezeFrameDiagnosticRecords.lock();
-            mDiagnosticHal.clearFreezeFrames(timestamps);
-            mFreezeFrameDiagnosticRecords.clearEvents();
-            mFreezeFrameDiagnosticRecords.unlock();
-            return true;
+        if (!isClearFreezeFramesSupported())
+            return false;
+        if (timestamps != null && timestamps.length != 0) {
+            if (!isSelectiveClearFreezeFramesSupported()) {
+                return false;
+            }
         }
-        return false;
+        mFreezeFrameDiagnosticRecords.lock();
+        mDiagnosticHal.clearFreezeFrames(timestamps);
+        mFreezeFrameDiagnosticRecords.clearEvents();
+        mFreezeFrameDiagnosticRecords.unlock();
+        return true;
     }
 
     /**
diff --git a/service/src/com/android/car/CarLog.java b/service/src/com/android/car/CarLog.java
index d9600d6..6ca570f 100644
--- a/service/src/com/android/car/CarLog.java
+++ b/service/src/com/android/car/CarLog.java
@@ -43,6 +43,7 @@
     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 final String TAG_STORAGE = "CAR.STORAGE";
 
     public static String concatTag(String tagPrefix, Class clazz) {
         String tag = tagPrefix + "." + clazz.getSimpleName();
diff --git a/service/src/com/android/car/CarService.java b/service/src/com/android/car/CarService.java
index 87e891e..6026fce 100644
--- a/service/src/com/android/car/CarService.java
+++ b/service/src/com/android/car/CarService.java
@@ -95,6 +95,9 @@
         super.onCreate();
     }
 
+    // onDestroy is best-effort and might not get called on shutdown/reboot. As such it is not
+    // suitable for permanently saving state or other need-to-happen operation. If you have a
+    // cleanup task that you want to make sure happens on shutdown/reboot, see OnShutdownReboot.
     @Override
     public void onDestroy() {
         Log.i(CarLog.TAG_SERVICE, "Service onDestroy");
diff --git a/service/src/com/android/car/CarStorageMonitoringService.java b/service/src/com/android/car/CarStorageMonitoringService.java
new file mode 100644
index 0000000..82a57af
--- /dev/null
+++ b/service/src/com/android/car/CarStorageMonitoringService.java
@@ -0,0 +1,127 @@
+/*
+ * 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;
+
+import android.car.Car;
+import android.car.storagemonitoring.ICarStorageMonitoring;
+import android.car.storagemonitoring.WearEstimate;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+import com.android.car.internal.CarPermission;
+import com.android.car.storagemonitoring.WearInformation;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import java.io.File;
+import java.io.PrintWriter;
+import java.time.Duration;
+import java.util.Optional;
+
+public class CarStorageMonitoringService extends ICarStorageMonitoring.Stub
+        implements CarServiceBase {
+
+    private static final String UPTIME_TRACKER_FILENAME = "service_uptime";
+    private static final String WEAR_INFO_FILENAME = "wear_info";
+
+    private final WearInformationProvider[] mWearInformationProviders;
+    private final Context mContext;
+    private final File mUptimeTrackerFile;
+    private final File mWearInfoFile;
+    private final OnShutdownReboot mOnShutdownReboot;
+
+    private final CarPermission mStorageMonitoringPermission;
+
+    private UptimeTracker mUptimeTracker;
+    private Optional<WearInformation> mWearInformation = Optional.empty();
+
+    public CarStorageMonitoringService(Context context, SystemInterface systemInterface) {
+        mContext = context;
+        mUptimeTrackerFile = new File(systemInterface.getFilesDir(), UPTIME_TRACKER_FILENAME);
+        mWearInfoFile = new File(systemInterface.getFilesDir(), WEAR_INFO_FILENAME);
+        mOnShutdownReboot = new OnShutdownReboot(mContext);
+        mWearInformationProviders = systemInterface.getFlashWearInformationProviders();
+        mStorageMonitoringPermission =
+                new CarPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
+    }
+
+    /**
+     * The overlay vends this data in hours/1% increase, but the current implementation
+     * works in terms of 10% increases. This method computes the number of milliseconds
+     * that make up an acceptable rate of 10% increases.
+     */
+    static long getAcceptableFlashWearRate() {
+        return 10 * Duration.ofHours(R.integer.acceptableHoursPerOnePercentFlashWear).toMillis();
+    }
+
+    /**
+     * We define the proper interval between uptime snapshots to be 1% of
+     * the value of uptimeHoursForAcceptableWearIncrease in the overlay.
+     */
+    private static long getUptimeSnapshotIntervalMs() {
+        return Duration.ofHours(R.integer.uptimeHoursIntervalBetweenUptimeDataWrite).toMillis();
+    }
+
+    private Optional<WearInformation> loadWearInformation() {
+        for (WearInformationProvider provider : mWearInformationProviders) {
+            WearInformation wearInfo = provider.load();
+            if (wearInfo != null) {
+                return Optional.of(wearInfo);
+            }
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public void init() {
+        Log.i(CarLog.TAG_STORAGE, "starting up CarStorageMonitoringService");
+        mUptimeTracker = new UptimeTracker(mUptimeTrackerFile, getUptimeSnapshotIntervalMs());
+        mWearInformation = loadWearInformation();
+        mOnShutdownReboot.addAction((Context ctx, Intent intent) -> release());
+    }
+
+    @Override
+    public void release() {
+        Log.i(CarLog.TAG_STORAGE, "tearing down CarStorageMonitoringService");
+        mUptimeTracker.onDestroy();
+        mOnShutdownReboot.clearActions();
+    }
+
+    @Override
+    public void dump(PrintWriter writer) {
+        writer.println("*CarStorageMonitoringService*");
+        writer.println("last wear information retrieved: " +
+            mWearInformation.map(WearInformation::toString).orElse("missing"));
+    }
+
+    // ICarStorageMonitoring implementation
+
+    @Override
+    public int getPreEolIndicatorStatus() {
+        mStorageMonitoringPermission.assertGranted();
+
+        return mWearInformation.map(wi -> wi.preEolInfo)
+                .orElse(WearInformation.UNKNOWN_PRE_EOL_INFO);
+    }
+
+    @Override
+    public WearEstimate getWearEstimate() {
+        mStorageMonitoringPermission.assertGranted();
+
+        return mWearInformation.map(wi ->
+                new WearEstimate(wi.lifetimeEstimateA,wi.lifetimeEstimateB)).orElse(
+                    new WearEstimate(WearEstimate.UNKNOWN, WearEstimate.UNKNOWN));
+    }
+}
diff --git a/service/src/com/android/car/CarVolumeControllerFactory.java b/service/src/com/android/car/CarVolumeControllerFactory.java
index c83ef93..7dc3929 100644
--- a/service/src/com/android/car/CarVolumeControllerFactory.java
+++ b/service/src/com/android/car/CarVolumeControllerFactory.java
@@ -23,6 +23,7 @@
 import android.media.IVolumeController;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteCallbackList;
@@ -90,8 +91,21 @@
      * support volume controls.
      */
     public static final class SimpleCarVolumeController extends CarVolumeController {
+        private static final String TAG = CarLog.TAG_AUDIO + ".SVolCtrl";
+        private static final int MSG_DISPLAY_SAFE_VOL_WARNING = 0;
+        private static final int MSG_VOL_CHANGED = 1;
+        private static final int MSG_MASTER_MUTE_CHANGED = 2;
+        private static final int MSG_SET_LAYOUT_DIRECTION = 3;
+        private static final int MSG_DISMISS = 4;
+        private static final int MSG_SET_ALLY_MODE = 5;
+
         private final AudioManager mAudioManager;
         private final Context mContext;
+        private RemoteCallbackList<IVolumeController> mVolumeCallbacks = new RemoteCallbackList<>();
+        @GuardedBy("this")
+        private IVolumeController mVolumeCallbackProxy;
+        private HandlerThread mVolumeThread;
+        private Handler mHandler;
 
         public SimpleCarVolumeController(Context context) {
             mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -100,16 +114,27 @@
 
         @Override
         void init() {
+            synchronized (this) {
+                mVolumeThread = new HandlerThread(TAG);
+                mVolumeThread.start();
+                mHandler = new VolumeHandler(mVolumeThread.getLooper());
+            }
         }
 
         @Override
         void release() {
+            synchronized (this) {
+                if (mVolumeThread != null) {
+                    mVolumeThread.quit();
+                }
+            }
+            mVolumeCallbacks.kill();
         }
 
         @Override
         public void setStreamVolume(int stream, int index, int flags) {
             if (DBG) {
-                Log.d(CarLog.TAG_AUDIO, "setStreamVolume " + stream + " " + index + " " + flags);
+                Log.d(TAG, "setStreamVolume " + stream + " " + index + " " + flags);
             }
             mAudioManager.setStreamVolume(stream, index, flags);
         }
@@ -121,7 +146,13 @@
 
         @Override
         public void setVolumeController(IVolumeController controller) {
-            mAudioManager.setVolumeController(controller);
+            synchronized (this) {
+                if (mVolumeCallbackProxy == null) {
+                    mVolumeCallbackProxy = new VolumeControllerProxy();
+                    mAudioManager.setVolumeController(mVolumeCallbackProxy);
+                }
+            }
+            mVolumeCallbacks.register(controller);
         }
 
         @Override
@@ -149,6 +180,146 @@
             // nothing else to dump
         }
 
+        private class VolumeHandler extends Handler {
+
+            public VolumeHandler(Looper looper) {
+                super(looper);
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_DISPLAY_SAFE_VOL_WARNING:
+                        int count = mVolumeCallbacks.beginBroadcast();
+                        try {
+                            for (int i = 0; i < count; i++) {
+                                try {
+                                    mVolumeCallbacks.getBroadcastItem(i)
+                                            .displaySafeVolumeWarning(msg.arg1);
+                                } catch (RemoteException ignored) {}
+                            }
+                        } finally {
+                            mVolumeCallbacks.finishBroadcast();
+                        }
+                        break;
+                    case MSG_VOL_CHANGED:
+                        count = mVolumeCallbacks.beginBroadcast();
+                        try {
+                            for (int i = 0; i < count; i++) {
+                                try {
+                                    mVolumeCallbacks.getBroadcastItem(i)
+                                            .volumeChanged(msg.arg1, msg.arg2);
+                                } catch (RemoteException ignored) {}
+                            }
+                        } finally {
+                            mVolumeCallbacks.finishBroadcast();
+                        }
+                        break;
+                    case MSG_MASTER_MUTE_CHANGED:
+                        count = mVolumeCallbacks.beginBroadcast();
+                        try {
+                            for (int i = 0; i < count; i++) {
+                                try {
+                                    mVolumeCallbacks.getBroadcastItem(i)
+                                            .masterMuteChanged(msg.arg1);
+                                } catch (RemoteException ignored) {}
+                            }
+                        } finally {
+                            mVolumeCallbacks.finishBroadcast();
+                        }
+                        break;
+                    case MSG_SET_LAYOUT_DIRECTION:
+                        count = mVolumeCallbacks.beginBroadcast();
+                        try {
+                            for (int i = 0; i < count; i++) {
+                                try {
+                                    mVolumeCallbacks.getBroadcastItem(i)
+                                            .setLayoutDirection(msg.arg1);
+                                } catch (RemoteException ignored) {}
+                            }
+                        } finally {
+                            mVolumeCallbacks.finishBroadcast();
+                        }
+                        break;
+                    case MSG_DISMISS:
+                        count = mVolumeCallbacks.beginBroadcast();
+                        try {
+                            for (int i = 0; i < count; i++) {
+                                try {
+                                    mVolumeCallbacks.getBroadcastItem(i)
+                                            .dismiss();
+                                } catch (RemoteException ignored) {}
+                            }
+                        } finally {
+                            mVolumeCallbacks.finishBroadcast();
+                        }
+                        break;
+                    case MSG_SET_ALLY_MODE:
+                        count = mVolumeCallbacks.beginBroadcast();
+                        try {
+                            for (int i = 0; i < count; i++) {
+                                try {
+                                    mVolumeCallbacks.getBroadcastItem(i)
+                                            .setA11yMode(msg.arg1);
+                                } catch (RemoteException ignored) {}
+                            }
+                        } finally {
+                            mVolumeCallbacks.finishBroadcast();
+                        }
+                        break;
+                }
+            }
+        }
+
+        private class VolumeControllerProxy extends IVolumeController.Stub {
+            @Override
+            public void displaySafeVolumeWarning(int flags) throws RemoteException {
+                synchronized (this) {
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPLAY_SAFE_VOL_WARNING,
+                            flags, 0 /*unused*/));
+                }
+            }
+
+            @Override
+            public void volumeChanged(int streamType, int flags) throws RemoteException {
+                synchronized (this) {
+                    mHandler.sendMessage(
+                            mHandler.obtainMessage(MSG_VOL_CHANGED, streamType, flags));
+                }
+            }
+
+            @Override
+            public void masterMuteChanged(int flags) throws RemoteException {
+                synchronized (this) {
+                    mHandler.sendMessage(
+                            mHandler.obtainMessage(MSG_VOL_CHANGED, flags, 0 /*unused*/));
+                }
+            }
+
+            @Override
+            public void setLayoutDirection(int layoutDirection) throws RemoteException {
+                synchronized (this) {
+                    mHandler.sendMessage(
+                            mHandler.obtainMessage(MSG_VOL_CHANGED, layoutDirection, 0 /*unused*/));
+                }
+            }
+
+            @Override
+            public void dismiss() throws RemoteException {
+                synchronized (this) {
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_DISMISS));
+                }
+            }
+
+            @Override
+            public void setA11yMode(int mode) throws RemoteException {
+                synchronized (this) {
+                    mHandler.sendMessage(
+                            mHandler.obtainMessage(MSG_SET_ALLY_MODE, mode, 0 /*unused*/));
+                }
+            }
+        }
+
         private void handleVolumeKeyDefault(KeyEvent event) {
             if (event.getAction() != KeyEvent.ACTION_DOWN
                     || interceptVolKeyBeforeDispatching(mContext)) {
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index bd42454..c308d81 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -71,7 +71,8 @@
     private final CarVendorExtensionService mCarVendorExtensionService;
     private final CarBluetoothService mCarBluetoothService;
     private final PerUserCarServiceHelper mPerUserCarServiceHelper;
-    private CarDiagnosticService mCarDiagnosticService;
+    private final CarDiagnosticService mCarDiagnosticService;
+    private final CarStorageMonitoringService mCarStorageMonitoringService;
     @FutureFeature
     private VmsSubscriberService mVmsSubscriberService;
     @FutureFeature
@@ -121,11 +122,11 @@
         mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
         mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService,
                 mCarSensorService, mPerUserCarServiceHelper);
-        if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-            mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
-            mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
-        }
+        mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
+        mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
         mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
+        mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,
+                systemInterface);
 
         // Be careful with order. Service depending on other service should be inited later.
         List<CarServiceBase> allServices = new ArrayList<>(Arrays.asList(
@@ -148,16 +149,15 @@
                 mCarVendorExtensionService,
                 mCarBluetoothService,
                 mCarDiagnosticService,
-                mPerUserCarServiceHelper
+                mPerUserCarServiceHelper,
+                mCarStorageMonitoringService,
+                mVmsSubscriberService,
+                mVmsPublisherService
         ));
-        if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-            allServices.add(mVmsSubscriberService);
-            allServices.add(mVmsPublisherService);
-        }
         mAllServices = allServices.toArray(new CarServiceBase[0]);
     }
 
-    public void init() {
+    void init() {
         traceBegin("VehicleHal.init");
         mHal.init();
         traceEnd();
@@ -168,7 +168,7 @@
         traceEnd();
     }
 
-    public void release() {
+    void release() {
         // release done in opposite order from init
         for (int i = mAllServices.length - 1; i >= 0; i--) {
             mAllServices[i].release();
@@ -176,7 +176,7 @@
         mHal.release();
     }
 
-    public void vehicleHalReconnected(IVehicle vehicle) {
+    void vehicleHalReconnected(IVehicle vehicle) {
         mHal.vehicleHalReconnected(vehicle);
         for (CarServiceBase service : mAllServices) {
             service.vehicleHalReconnected();
@@ -234,11 +234,8 @@
                 assertVendorExtensionPermission(mContext);
                 return mCarVendorExtensionService;
             case Car.VMS_SUBSCRIBER_SERVICE:
-                FeatureUtil.assertFeature(FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE);
-                if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-                    assertVmsSubscriberPermission(mContext);
-                    return mVmsSubscriberService;
-                }
+                assertVmsSubscriberPermission(mContext);
+                return mVmsSubscriberService;
             case Car.TEST_SERVICE: {
                 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
                 synchronized (this) {
@@ -250,6 +247,9 @@
             }
             case Car.BLUETOOTH_SERVICE:
                 return mCarBluetoothService;
+            case Car.STORAGE_MONITORING_SERVICE:
+                assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
+                return mCarStorageMonitoringService;
             default:
                 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
                 return null;
diff --git a/service/src/com/android/car/OnShutdownReboot.java b/service/src/com/android/car/OnShutdownReboot.java
new file mode 100644
index 0000000..701fabf
--- /dev/null
+++ b/service/src/com/android/car/OnShutdownReboot.java
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.BiConsumer;
+
+/**
+ * This class allows one to register actions they want executed when the vehicle is being shutdown
+ * or rebooted.
+ *
+ * To use this class instantiate it as part of your long-lived service, and then add actions to it.
+ * Actions receive the Context and Intent that go with the shutdown/reboot action, which allows the
+ * action to differentiate the two cases, should it need to do so.
+ *
+ * The actions will run on the UI thread.
+ */
+class OnShutdownReboot {
+    private final Object mLock = new Object();
+
+    private final Context mContext;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            for (BiConsumer<Context, Intent> action : mActions) {
+                action.accept(context, intent);
+            }
+        }
+    };
+
+    private final CopyOnWriteArrayList<BiConsumer<Context, Intent>> mActions =
+            new CopyOnWriteArrayList<>();
+
+    OnShutdownReboot(Context context) {
+        mContext = context;
+        IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
+        IntentFilter rebootFilter = new IntentFilter(Intent.ACTION_REBOOT);
+        mContext.registerReceiver(mReceiver, shutdownFilter);
+        mContext.registerReceiver(mReceiver, rebootFilter);
+    }
+
+    void addAction(BiConsumer<Context, Intent> action) {
+        mActions.add(action);
+    }
+
+    void clearActions() {
+        mActions.clear();
+    }
+}
diff --git a/service/src/com/android/car/SystemInterface.java b/service/src/com/android/car/SystemInterface.java
index 6311d80..d991d87 100644
--- a/service/src/com/android/car/SystemInterface.java
+++ b/service/src/com/android/car/SystemInterface.java
@@ -23,11 +23,18 @@
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.Display;
+import com.android.car.storagemonitoring.EMmcWearInformationProvider;
+import com.android.car.storagemonitoring.UfsWearInformationProvider;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import java.io.File;
 
 /**
  * Interface to abstract all system interaction.
  */
 public abstract class SystemInterface {
+    public static final boolean INCLUDE_DEEP_SLEEP_TIME = true;
+    public static final boolean EXCLUDE_DEEP_SLEEP_TIME = false;
+
     public abstract void setDisplayState(boolean on);
     public abstract void releaseAllWakeLocks();
     public abstract void shutdown();
@@ -38,7 +45,17 @@
     public abstract void stopDisplayStateMonitoring();
     public abstract boolean isSystemSupportingDeepSleep();
     public abstract boolean isWakeupCausedByTimer();
+    public abstract WearInformationProvider[] getFlashWearInformationProviders();
+    public abstract File getFilesDir();
 
+    public final long getUptime() {
+        return getUptime(EXCLUDE_DEEP_SLEEP_TIME);
+    }
+    public long getUptime(boolean includeDeepSleepTime) {
+        return includeDeepSleepTime ?
+            SystemClock.elapsedRealtime() :
+            SystemClock.uptimeMillis();
+    }
 
     public static SystemInterface getDefault(Context context) {
         return new SystemInterfaceImpl(context);
@@ -50,6 +67,8 @@
         private final WakeLock mFullWakeLock;
         private final WakeLock mPartialWakeLock;
         private final DisplayStateListener mDisplayListener;
+        private final WearInformationProvider[] mWearInformationProviders;
+        private final File mFilesDir;
         private CarPowerManagementService mService;
         private boolean mDisplayStateSet;
 
@@ -61,6 +80,11 @@
             mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                     CarLog.TAG_POWER);
             mDisplayListener = new DisplayStateListener();
+            mWearInformationProviders = new WearInformationProvider[] {
+                    new EMmcWearInformationProvider(),
+                    new UfsWearInformationProvider()
+                };
+            mFilesDir = context.getFilesDir();
         }
 
         @Override
@@ -156,6 +180,16 @@
             return false;
         }
 
+        @Override
+        public WearInformationProvider[] getFlashWearInformationProviders() {
+            return mWearInformationProviders;
+        }
+
+        @Override
+        public File getFilesDir() {
+            return mFilesDir;
+        }
+
         private void handleMainDisplayChanged() {
             boolean isOn = isMainDisplayOn();
             CarPowerManagementService service;
diff --git a/service/src/com/android/car/UptimeTracker.java b/service/src/com/android/car/UptimeTracker.java
new file mode 100644
index 0000000..a4f1d7c
--- /dev/null
+++ b/service/src/com/android/car/UptimeTracker.java
@@ -0,0 +1,214 @@
+/*
+ * 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;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import android.os.SystemClock;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * A class that can keep track of how long its instances are alive for.
+ *
+ * It can be used as a helper object to track the lifetime of system components, e.g.
+ *
+ * class InterestingService {
+ *     private UptimeTracker mTracker;
+ *
+ *     public void onCreate() {
+ *         mTracker = new UptimeTracker(
+ *             "/storage/emulated/0/Android/data/interestingservice.uptime", 1 hour);
+ *         mTracker.onCreate();
+ *     }
+ *
+ *     public void onDestroy() {
+ *         mTracker.onDestroy();
+ *     }
+ * }
+ *
+ * Now it's possible to know how long InterestingService has been alive in the system by querying
+ * mTracker.getTotalUptime(). Because this data is stored to disk, the uptime is maintained across
+ * process and system reboot boundaries. It is possible to configure periodic snapshot points to
+ * ensure that crashes do not cause more than a certain amount of uptime to go untracked.
+ */
+public class UptimeTracker {
+    @VisibleForTesting
+    interface TimingProvider {
+        long getCurrentRealtime();
+        void schedule(Runnable r, long delay);
+        void cancelAll();
+    }
+
+    // note: this implementation does not account for time spent in "suspend" mode
+    private static final class DefaultTimingProvider implements TimingProvider {
+        private ScheduledExecutorService mExecutor = newSingleThreadScheduledExecutor();
+
+        @Override
+        public long getCurrentRealtime() {
+            return SystemClock.uptimeMillis();
+        }
+
+        @Override
+        public void schedule(Runnable r, long delay) {
+            mExecutor.scheduleWithFixedDelay(r, delay, delay, MILLISECONDS);
+        }
+
+        @Override
+        public void cancelAll() {
+            mExecutor.shutdownNow();
+        }
+    }
+
+    /**
+     * In order to prevent excessive wear-out of the storage, do not allow snapshots to happen
+     * more frequently than this value
+     */
+    public static final long MINIMUM_SNAPSHOT_INTERVAL_MS = 60 * 60 * 1000;
+
+    /**
+     * The default snapshot interval if none is given
+     */
+    private static long DEFAULT_SNAPSHOT_INTERVAL_MS = 5 * 60 * 60 * 1000; // 5 hours
+
+    private final Object mLock = new Object();
+
+    /**
+     * The file that uptime metrics are stored to
+     */
+    private File mUptimeFile;
+
+    /**
+     * The uptime value retrieved from mUptimeFile
+     */
+    private Optional<Long> mHistoricalUptime;
+
+    /**
+     * Last value of elapsedRealTime read from the system
+     */
+    private long mLastRealTimeSnapshot;
+
+    /**
+     * The source of real-time and scheduling
+     */
+    private TimingProvider mTimingProvider;
+
+    public UptimeTracker(File file) {
+        this(file, DEFAULT_SNAPSHOT_INTERVAL_MS);
+    }
+
+    public UptimeTracker(File file, long snapshotInterval) {
+        this(file, snapshotInterval, new DefaultTimingProvider());
+    }
+
+    // By default, SystemClock::elapsedRealtime is used as the source of the uptime clock
+    // and a ScheduledExecutorService provides snapshot synchronization. For testing purposes
+    // this constructor allows using a controlled source of time information and scheduling.
+    @VisibleForTesting
+    UptimeTracker(File file,
+            long snapshotInterval,
+            TimingProvider timingProvider) {
+        snapshotInterval = Math.max(snapshotInterval, MINIMUM_SNAPSHOT_INTERVAL_MS);
+        mUptimeFile = Objects.requireNonNull(file);
+        mTimingProvider = timingProvider;
+        mLastRealTimeSnapshot = mTimingProvider.getCurrentRealtime();
+        mHistoricalUptime = Optional.empty();
+
+        mTimingProvider.schedule(this::flushSnapshot, snapshotInterval);
+    }
+
+    void onDestroy() {
+        synchronized (mLock) {
+            if (mTimingProvider != null) {
+                mTimingProvider.cancelAll();
+            }
+            flushSnapshot();
+            mTimingProvider = null;
+            mUptimeFile = null;
+        }
+    }
+
+    /**
+     * Return the total amount of uptime that has been observed, in milliseconds.
+     *
+     * This is the sum of the uptime stored on disk + the uptime seen since the last snapshot.
+     */
+    long getTotalUptime() {
+        synchronized (mLock) {
+            if (mTimingProvider == null) {
+                return 0;
+            }
+            return getHistoricalUptimeLocked() + (
+                    mTimingProvider.getCurrentRealtime() - mLastRealTimeSnapshot);
+        }
+    }
+
+    private long getHistoricalUptimeLocked() {
+        if (!mHistoricalUptime.isPresent() && mUptimeFile != null) {
+            try {
+                JsonReader reader = new JsonReader(new FileReader(mUptimeFile));
+                reader.beginObject();
+                if (!reader.nextName().equals("uptime")) {
+                    throw new IllegalArgumentException(
+                        mUptimeFile + " is not in a valid format");
+                } else {
+                    mHistoricalUptime = Optional.of(reader.nextLong());
+                }
+                reader.endObject();
+                reader.close();
+            } catch (IllegalArgumentException | IOException e) {
+                Log.w(CarLog.TAG_SERVICE, "unable to read historical uptime data", e);
+                mHistoricalUptime = Optional.empty();
+            }
+        }
+        return mHistoricalUptime.orElse(0L);
+    }
+
+    private void flushSnapshot() {
+        synchronized (mLock) {
+            if (mUptimeFile == null) {
+                return;
+            }
+            try {
+                long newUptime = getTotalUptime();
+                mHistoricalUptime = Optional.of(newUptime);
+                mLastRealTimeSnapshot = mTimingProvider.getCurrentRealtime();
+
+                JsonWriter writer = new JsonWriter(new FileWriter(mUptimeFile));
+                writer.beginObject();
+                writer.name("uptime");
+                writer.value(newUptime);
+                writer.endObject();
+                writer.close();
+            } catch (IOException e) {
+                Log.w(CarLog.TAG_SERVICE, "unable to write historical uptime data", e);
+            }
+        }
+    }
+}
diff --git a/service/src/com/android/car/VmsLayersAvailability.java b/service/src/com/android/car/VmsLayersAvailability.java
index 93b917c..4c730c1 100644
--- a/service/src/com/android/car/VmsLayersAvailability.java
+++ b/service/src/com/android/car/VmsLayersAvailability.java
@@ -16,7 +16,6 @@
 
 package com.android.car;
 
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsAssociatedLayer;
 import android.car.vms.VmsLayer;
 import android.car.vms.VmsLayerDependency;
@@ -40,9 +39,10 @@
  * Each VMS publisher sets its layers offering which are a list of layers the publisher claims
  * it might publish. VmsLayersAvailability calculates from all the offering what are the
  * available layers.
+ *
+ * @hide
  */
 
-@FutureFeature
 public class VmsLayersAvailability {
 
     private static final boolean DBG = true;
diff --git a/service/src/com/android/car/VmsPublisherService.java b/service/src/com/android/car/VmsPublisherService.java
index 8a293e5..2d2acf6 100644
--- a/service/src/com/android/car/VmsPublisherService.java
+++ b/service/src/com/android/car/VmsPublisherService.java
@@ -16,7 +16,7 @@
 
 package com.android.car;
 
-import android.car.annotation.FutureFeature;
+import android.annotation.SystemApi;
 import android.car.vms.IVmsSubscriberClient;
 import android.car.vms.IVmsPublisherClient;
 import android.car.vms.IVmsPublisherService;
@@ -48,11 +48,13 @@
 import java.util.Set;
 
 /**
- * + Receives HAL updates by implementing VmsHalService.VmsHalListener.
- * + Binds to publishers and configures them to use this service.
- * + Notifies publishers of subscription changes.
+ * Receives HAL updates by implementing VmsHalService.VmsHalListener.
+ * Binds to publishers and configures them to use this service.
+ * Notifies publishers of subscription changes.
+ *
+ * @hide
  */
-@FutureFeature
+@SystemApi
 public class VmsPublisherService extends IVmsPublisherService.Stub
         implements CarServiceBase, VmsHalService.VmsHalPublisherListener {
     private static final boolean DBG = true;
diff --git a/service/src/com/android/car/VmsPublishersInfo.java b/service/src/com/android/car/VmsPublishersInfo.java
index 04ee82f..0f73e5c 100644
--- a/service/src/com/android/car/VmsPublishersInfo.java
+++ b/service/src/com/android/car/VmsPublishersInfo.java
@@ -16,8 +16,6 @@
 
 package com.android.car;
 
-
-import android.car.annotation.FutureFeature;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.List;
@@ -26,7 +24,6 @@
 import com.android.internal.annotations.GuardedBy;
 import android.util.Log;
 
-@FutureFeature
 public class VmsPublishersInfo {
     private static final String TAG = "VmsPublishersInfo";
     private static final boolean DBG = true;
diff --git a/service/src/com/android/car/VmsRouting.java b/service/src/com/android/car/VmsRouting.java
index 2e66781..fa29a27 100644
--- a/service/src/com/android/car/VmsRouting.java
+++ b/service/src/com/android/car/VmsRouting.java
@@ -16,7 +16,6 @@
 
 package com.android.car;
 
-import android.car.annotation.FutureFeature;
 import android.car.vms.IVmsSubscriberClient;
 import android.car.vms.VmsAssociatedLayer;
 import android.car.vms.VmsLayer;
@@ -39,7 +38,7 @@
  * + Subscriptions to all data messages.
  * + HAL subscriptions to layer + version.
  */
-@FutureFeature
+
 public class VmsRouting {
     private final Object mLock = new Object();
     // A map of Layer + Version to subscribers.
diff --git a/service/src/com/android/car/VmsSubscriberService.java b/service/src/com/android/car/VmsSubscriberService.java
index 94f0844..5031fb4 100644
--- a/service/src/com/android/car/VmsSubscriberService.java
+++ b/service/src/com/android/car/VmsSubscriberService.java
@@ -16,8 +16,8 @@
 
 package com.android.car;
 
+import android.annotation.SystemApi;
 import android.car.Car;
-import android.car.annotation.FutureFeature;
 import android.car.vms.IVmsSubscriberClient;
 import android.car.vms.IVmsSubscriberService;
 import android.car.vms.VmsAssociatedLayer;
@@ -43,7 +43,7 @@
  * + Receives HAL updates by implementing VmsHalService.VmsHalListener.
  * + Offers subscriber/publisher services by implementing IVmsService.Stub.
  */
-@FutureFeature
+@SystemApi
 public class VmsSubscriberService extends IVmsSubscriberService.Stub
         implements CarServiceBase, VmsHalService.VmsHalSubscriberListener {
     private static final boolean DBG = true;
diff --git a/service/src/com/android/car/hal/DiagnosticHalService.java b/service/src/com/android/car/hal/DiagnosticHalService.java
index 4ff0ada..bcbae7a 100644
--- a/service/src/com/android/car/hal/DiagnosticHalService.java
+++ b/service/src/com/android/car/hal/DiagnosticHalService.java
@@ -42,6 +42,8 @@
  * higher-level semantic information
  */
 public class DiagnosticHalService extends SensorHalServiceBase {
+    static final int OBD2_SELECTIVE_FRAME_CLEAR = 1;
+
     public static class DiagnosticCapabilities {
         private final CopyOnWriteArraySet<Integer> mProperties = new CopyOnWriteArraySet<>();
 
@@ -69,6 +71,10 @@
             return isSupported(VehicleProperty.OBD2_FREEZE_FRAME_CLEAR);
         }
 
+        public boolean isSelectiveClearFreezeFramesSupported() {
+            return isSupported(OBD2_SELECTIVE_FRAME_CLEAR);
+        }
+
         void clear() {
             mProperties.clear();
         }
@@ -102,6 +108,17 @@
                 return propConfig.prop;
             case VehicleProperty.OBD2_FREEZE_FRAME_CLEAR:
                 mDiagnosticCapabilities.setSupported(propConfig.prop);
+                Log.i(CarLog.TAG_DIAGNOSTIC, String.format(
+                        "configArray for OBD2_FREEZE_FRAME_CLEAR is %s", propConfig.configArray));
+                if (propConfig.configArray.size() < 1) {
+                    Log.e(CarLog.TAG_DIAGNOSTIC, String.format(
+                            "property 0x%x does not specify whether it supports selective " +
+                            "clearing of freeze frames. assuming it does not.", propConfig.prop));
+                } else {
+                    if (propConfig.configArray.get(0) == 1) {
+                        mDiagnosticCapabilities.setSupported(OBD2_SELECTIVE_FRAME_CLEAR);
+                    }
+                }
                 return propConfig.prop;
             default:
                 return SENSOR_TYPE_INVALID;
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index 21f8f51..3c54bfc 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -108,9 +108,7 @@
         mHvacHal = new HvacHalService(this);
         mInputHal = new InputHalService(this);
         mVendorExtensionHal = new VendorExtensionHalService(this);
-        if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-            mVmsHal = new VmsHalService(this);
-        }
+        mVmsHal = new VmsHalService(this);
         mDiagnosticHal = new DiagnosticHalService(this);
         mAllServices.addAll(Arrays.asList(mPowerHal,
                 mSensorHal,
@@ -121,10 +119,8 @@
                 mHvacHal,
                 mInputHal,
                 mVendorExtensionHal,
-                mDiagnosticHal));
-        if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-            mAllServices.add(mVmsHal);
-        }
+                mDiagnosticHal,
+                mVmsHal));
 
         mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
     }
@@ -132,7 +128,7 @@
     /** Dummy version only for testing */
     @VisibleForTesting
     public VehicleHal(PowerHalService powerHal, SensorHalService sensorHal, InfoHalService infoHal,
-            AudioHalService audioHal, CabinHalService cabinHal,
+            AudioHalService audioHal, CabinHalService cabinHal, DiagnosticHalService diagnosticHal,
             RadioHalService radioHal, HvacHalService hvacHal, HalClient halClient) {
         mHandlerThread = null;
         mPowerHal = powerHal;
@@ -140,38 +136,14 @@
         mInfoHal = infoHal;
         mAudioHal = audioHal;
         mCabinHal = cabinHal;
+        mDiagnosticHal = diagnosticHal;
         mRadioHal = radioHal;
         mHvacHal = hvacHal;
         mInputHal = null;
         mVendorExtensionHal = null;
-        mDiagnosticHal = null;
-
-        if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-            mVmsHal = null;
-        }
-
+        mVmsHal = null;
         mHalClient = halClient;
-    }
-
-    /** Dummy version only for testing */
-    @VisibleForTesting
-    public VehicleHal(PowerHalService powerHal, SensorHalService sensorHal, InfoHalService infoHal,
-            AudioHalService audioHal, CabinHalService cabinHal, DiagnosticHalService diagnosticHal,
-            RadioHalService radioHal, HvacHalService hvacHal, HalClient halClient) {
-            mHandlerThread = null;
-            mPowerHal = powerHal;
-            mSensorHal = sensorHal;
-            mInfoHal = infoHal;
-            mAudioHal = audioHal;
-            mCabinHal = cabinHal;
-            mDiagnosticHal = diagnosticHal;
-            mRadioHal = radioHal;
-            mHvacHal = hvacHal;
-            mInputHal = null;
-            mVendorExtensionHal = null;
-            mVmsHal = null;
-            mHalClient = halClient;
-            mDiagnosticHal = diagnosticHal;
+        mDiagnosticHal = diagnosticHal;
     }
 
     public void vehicleHalReconnected(IVehicle vehicle) {
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
index d20a453..36da390 100644
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ b/service/src/com/android/car/hal/VmsHalService.java
@@ -18,8 +18,8 @@
 import static com.android.car.CarServiceUtils.toByteArray;
 import static java.lang.Integer.toHexString;
 
+import android.annotation.SystemApi;
 import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
 import android.car.vms.IVmsSubscriberClient;
 import android.car.vms.VmsLayer;
 import android.car.vms.VmsAssociatedLayer;
@@ -61,7 +61,7 @@
  * This is a glue layer between the VehicleHal and the VmsService. It sends VMS properties back and
  * forth.
  */
-@FutureFeature
+@SystemApi
 public class VmsHalService extends HalServiceBase {
 
     private static final boolean DBG = true;
diff --git a/service/src/com/android/car/storagemonitoring/EMmcWearInformationProvider.java b/service/src/com/android/car/storagemonitoring/EMmcWearInformationProvider.java
new file mode 100644
index 0000000..3940578
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/EMmcWearInformationProvider.java
@@ -0,0 +1,106 @@
+/*
+ * 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.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+import com.android.car.CarLog;
+import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+/**
+ * Loads wear information from the eMMC sysfs entry points.
+ * sysfs exposes eMMC lifetime data in /sys/bus/mmc/devices/mmc0:0001/{pre_eol_info|life_time}
+ * The first file contains the value of the PRE_EOL_INFO register as an hexadecimal string
+ * The second file contains the values of the LIFE_TIME_EST A and B registers as two hexadecimal
+ * strings separated by a space.
+ */
+public class EMmcWearInformationProvider implements WearInformationProvider {
+    private static File DEFAULT_LIFE_TIME_FILE =
+        new File("/sys/bus/mmc/devices/mmc0:0001/life_time");
+
+    private static File DEFAULT_PRE_EOL_FILE =
+        new File("/sys/bus/mmc/devices/mmc0:0001/pre_eol_info");
+
+    private File mLifetimeFile;
+    private File mPreEolFile;
+
+    public EMmcWearInformationProvider() {
+        this(DEFAULT_LIFE_TIME_FILE, DEFAULT_PRE_EOL_FILE);
+    }
+
+    @VisibleForTesting
+    EMmcWearInformationProvider(@NonNull File lifetimeFile, @NonNull File preEolFile) {
+        mLifetimeFile = lifetimeFile;
+        mPreEolFile = preEolFile;
+    }
+
+    private String readLineFromFile(File f) {
+        if (!f.exists() || !f.isFile()) {
+            Log.i(CarLog.TAG_STORAGE, f + " does not exist or is not a file");
+            return null;
+        }
+
+        try {
+            BufferedReader reader = new BufferedReader(new FileReader(f));
+            String data = reader.readLine();
+            reader.close();
+            return data;
+        } catch (IOException e) {
+            Log.w(CarLog.TAG_STORAGE, f + " cannot be read from", e);
+            return null;
+        }
+    }
+
+    @Nullable
+    @Override
+    public WearInformation load() {
+        String lifetimeData = readLineFromFile(mLifetimeFile);
+        String eolData = readLineFromFile(mPreEolFile);
+
+        if ((lifetimeData == null) || (eolData == null)) {
+            return null;
+        }
+
+        String[] lifetimes = lifetimeData.split(" ");
+        if (lifetimes.length != 2) {
+            Log.w(CarLog.TAG_STORAGE, "lifetime data not in expected format: " + lifetimeData);
+            return null;
+        }
+
+        int lifetimeA;
+        int lifetimeB;
+        int eol;
+
+        try {
+            lifetimeA = Integer.decode(lifetimes[0]);
+            lifetimeB = Integer.decode(lifetimes[1]);
+            eol = Integer.decode("0x" + eolData);
+        } catch (NumberFormatException e) {
+            Log.w(CarLog.TAG_STORAGE,
+                    "lifetime data not in expected format: " + lifetimeData, e);
+            return null;
+        }
+
+        return new WearInformation(convertLifetime(lifetimeA),
+                convertLifetime(lifetimeB),
+                adjustEol(eol));
+    }
+}
diff --git a/service/src/com/android/car/storagemonitoring/UfsWearInformationProvider.java b/service/src/com/android/car/storagemonitoring/UfsWearInformationProvider.java
new file mode 100644
index 0000000..fa7ba8b
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/UfsWearInformationProvider.java
@@ -0,0 +1,112 @@
+/*
+ * 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.storagemonitoring;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.Log;
+import com.android.car.CarLog;
+import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import java.util.Scanner;
+import java.util.regex.MatchResult;
+import java.util.regex.Pattern;
+
+/**
+ * Loads wear information from the UFS sysfs entry points.
+ * sysfs exposes UFS lifetime data in /sys/devices/soc/624000.ufshc/health
+ * The first line of the file contains the UFS version
+ * Subsequent lines contains individual information points in the format:
+ * Health Descriptor[Byte offset 0x%d]: %31s = 0x%hx
+ * Of these we care about the key values bPreEOLInfo and bDeviceLifeTimeEstA bDeviceLifeTimeEstB
+ */
+public class UfsWearInformationProvider implements WearInformationProvider {
+    private static File DEFAULT_FILE =
+        new File("/sys/devices/soc/624000.ufshc/health");
+
+    private File mFile;
+
+    public UfsWearInformationProvider() {
+        this(DEFAULT_FILE);
+    }
+
+    @VisibleForTesting
+    public UfsWearInformationProvider(@NonNull File file) {
+        mFile = file;
+    }
+
+    @Nullable
+    @Override
+    public WearInformation load() {
+        List<String> lifetimeData;
+        try {
+            lifetimeData = java.nio.file.Files.readAllLines(mFile.toPath());
+        } catch (IOException e) {
+            Log.w(CarLog.TAG_STORAGE, "error reading " + mFile, e);
+            return null;
+        }
+        if (lifetimeData == null || lifetimeData.size() < 4) {
+            return null;
+        }
+
+        Pattern infoPattern = Pattern.compile(
+                "Health Descriptor\\[Byte offset 0x\\d+\\]: (\\w+) = 0x([0-9a-fA-F]+)");
+
+        Optional<Integer> lifetimeA = Optional.empty();
+        Optional<Integer> lifetimeB = Optional.empty();
+        Optional<Integer> eol = Optional.empty();
+
+        for(String lifetimeInfo : lifetimeData) {
+            Scanner scanner = new Scanner(lifetimeInfo);
+            if (null == scanner.findInLine(infoPattern)) {
+                continue;
+            }
+            MatchResult match = scanner.match();
+            if (match.groupCount() != 2) {
+                continue;
+            }
+            String name = match.group(1);
+            String value = "0x" + match.group(2);
+            try {
+                switch (name) {
+                    case "bPreEOLInfo":
+                        eol = Optional.of(Integer.decode(value));
+                        break;
+                    case "bDeviceLifeTimeEstA":
+                        lifetimeA = Optional.of(Integer.decode(value));
+                        break;
+                    case "bDeviceLifeTimeEstB":
+                        lifetimeB = Optional.of(Integer.decode(value));
+                        break;
+                }
+            } catch (NumberFormatException e) {
+                Log.w(CarLog.TAG_STORAGE,
+                    "trying to decode key " + name + " value " + value + " didn't parse properly", e);
+            }
+        }
+
+        if (!lifetimeA.isPresent() || !lifetimeB.isPresent() || !eol.isPresent()) {
+            return null;
+        }
+
+        return new WearInformation(convertLifetime(lifetimeA.get()),
+            convertLifetime(lifetimeB.get()),
+            adjustEol(eol.get()));
+    }
+}
diff --git a/service/src/com/android/car/storagemonitoring/WearInformation.java b/service/src/com/android/car/storagemonitoring/WearInformation.java
new file mode 100644
index 0000000..2f885d4
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/WearInformation.java
@@ -0,0 +1,83 @@
+/*
+ * 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.storagemonitoring;
+
+import static java.util.Objects.hash;
+
+public final class WearInformation {
+    public static final int UNKNOWN_LIFETIME_ESTIMATE = -1;
+
+    public static final int UNKNOWN_PRE_EOL_INFO = 0;
+    public static final int PRE_EOL_INFO_NORMAL = 1;
+    public static final int PRE_EOL_INFO_WARNING = 2;
+    public static final int PRE_EOL_INFO_URGENT = 3;
+
+    private static final String UNKNOWN = "unknown";
+    private static final String[] PRE_EOL_STRINGS = new String[] {
+        UNKNOWN, "normal", "warning", "urgent"
+    };
+
+    /**
+     * A lower bound on the lifetime estimate for "type A" memory cells, expressed as a percentage.
+     */
+    public final int lifetimeEstimateA;
+
+    /**
+     * A lower bound on the lifetime estimate for "type B" memory cells, expressed as a percentage.
+     */
+    public final int lifetimeEstimateB;
+
+    /**
+     * An estimate of the lifetime based on reserved block consumption.
+     */
+    public final int preEolInfo;
+
+    public WearInformation(int lifetimeA, int lifetimeB, int preEol) {
+        lifetimeEstimateA = lifetimeA;
+        lifetimeEstimateB = lifetimeB;
+        preEolInfo = preEol;
+    }
+
+    @Override
+    public int hashCode() {
+        return hash(lifetimeEstimateA, lifetimeEstimateB, preEolInfo);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof WearInformation) {
+            WearInformation wi = (WearInformation)other;
+            return (wi.lifetimeEstimateA == lifetimeEstimateA) &&
+                (wi.lifetimeEstimateB == lifetimeEstimateB) &&
+                (wi.preEolInfo == preEolInfo);
+        } else {
+            return false;
+        }
+    }
+
+    private String lifetimeToString(int lifetime) {
+        if (lifetime == UNKNOWN_LIFETIME_ESTIMATE) return UNKNOWN;
+
+        return lifetime + "%";
+    }
+
+    @Override
+    public String toString() {
+        return "lifetime estimate A: " + lifetimeToString(lifetimeEstimateA) + '\n' +
+            "lifetime estimate B: " + lifetimeToString(lifetimeEstimateB) + '\n' +
+            "pre EOL info: " + PRE_EOL_STRINGS[preEolInfo] + '\n';
+    }
+}
diff --git a/service/src/com/android/car/storagemonitoring/WearInformationProvider.java b/service/src/com/android/car/storagemonitoring/WearInformationProvider.java
new file mode 100644
index 0000000..65574d7
--- /dev/null
+++ b/service/src/com/android/car/storagemonitoring/WearInformationProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.storagemonitoring;
+
+import android.annotation.Nullable;
+
+public interface WearInformationProvider {
+    @Nullable
+    WearInformation load();
+
+    default int convertLifetime(int lifetime) {
+        if ((lifetime <= 0) || (lifetime > 11)) return WearInformation.UNKNOWN_LIFETIME_ESTIMATE;
+        return 10 * (lifetime - 1);
+    }
+
+    default int adjustEol(int eol) {
+        if ((eol <= 0) || (eol > 3)) return WearInformation.UNKNOWN_PRE_EOL_INFO;
+        return eol;
+    }
+
+}
diff --git a/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml b/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
index 2a96898..db09cba 100644
--- a/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
+++ b/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
@@ -33,6 +33,7 @@
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"/>
     <uses-permission android:name="android.car.permission.VEHICLE_DYNAMICS_STATE"/>
     <uses-permission android:name="android.car.permission.CAR_DISPLAY_IN_CLUSTER"/>
+    <uses-permission android:name="android.car.permission.STORAGE_MONITORING" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.MANAGE_USB" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/storagewear.xml b/tests/EmbeddedKitchenSinkApp/res/layout/storagewear.xml
new file mode 100644
index 0000000..bfb57c3
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/storagewear.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+    <!-- 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.
+    -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="50dp"
+        android:orientation="vertical"
+        android:layout_weight="1" />
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_weight="1" >
+            <TextView
+                android:id="@+id/storage_wear_info"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Storage Wear Information"
+                android:textSize="24dp"
+                android:textColor="#ff0000"
+                android:minLines="5"/>
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
index e68c3fa..c1dd824 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
@@ -49,6 +49,7 @@
 import com.google.android.car.kitchensink.radio.RadioTestFragment;
 import com.google.android.car.kitchensink.sensor.SensorsTestFragment;
 import com.google.android.car.kitchensink.setting.CarServiceSettingsActivity;
+import com.google.android.car.kitchensink.storagelifetime.StorageLifetimeFragment;
 import com.google.android.car.kitchensink.touch.TouchTestFragment;
 import com.google.android.car.kitchensink.volume.VolumeTestFragment;
 import java.util.ArrayList;
@@ -147,6 +148,7 @@
             add("orientation test", OrientationTestFragment.class);
             add("bluetooth headset",BluetoothHeadsetFragment.class);
             add("bluetooth messaging test", MapMceTestFragment.class);
+            add("storage lifetime", StorageLifetimeFragment.class);
             add("car service settings", () -> {
                 Intent intent = new Intent(KitchenSinkActivity.this,
                     CarServiceSettingsActivity.class);
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
new file mode 100644
index 0000000..b5165a8
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
@@ -0,0 +1,83 @@
+/*
+ * 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.google.android.car.kitchensink.storagelifetime;
+
+import android.annotation.Nullable;
+import android.car.Car;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import com.google.android.car.kitchensink.KitchenSinkActivity;
+import com.google.android.car.kitchensink.R;
+
+public class StorageLifetimeFragment extends Fragment {
+    private static final String TAG = "CAR.STORAGELIFETIME.KS";
+
+    private KitchenSinkActivity mActivity;
+    private TextView mStorageWearInfo;
+    private CarStorageMonitoringManager mStorageManager;
+
+    // TODO(egranata): put this somewhere more useful than KitchenSink
+    private static String preEolToString(int preEol) {
+        switch (preEol) {
+            case 1: return "normal";
+            case 2: return "warning";
+            case 3: return "urgent";
+            default:
+                return "unknown";
+        }
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(
+            LayoutInflater inflater,
+            @Nullable ViewGroup container,
+            @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.storagewear, container, false);
+        mActivity = (KitchenSinkActivity) getHost();
+        mStorageWearInfo = (TextView) view.findViewById(R.id.storage_wear_info);
+        return view;
+    }
+
+    private void reloadInfo() {
+        try {
+            mStorageManager =
+                (CarStorageMonitoringManager) mActivity.getCar().getCarManager(
+                        Car.STORAGE_MONITORING_SERVICE);
+
+            mStorageWearInfo.setText("Wear estimate: " +
+                mStorageManager.getWearEstimate() + "\nPre EOL indicator: " +
+                preEolToString(mStorageManager.getPreEolIndicatorStatus()));
+        } catch (android.car.CarNotConnectedException|
+                 android.support.car.CarNotConnectedException e) {
+            Log.e(TAG, "Car not connected or not supported", e);
+        }
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        reloadInfo();
+    }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java
index 0d65500..874bc64 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/volume/VolumeTestFragment.java
@@ -18,11 +18,14 @@
 import android.car.Car;
 import android.car.CarNotConnectedException;
 import android.car.media.CarAudioManager;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.ServiceConnection;
 import android.media.AudioManager;
 import android.media.IVolumeController;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
 import android.support.annotation.Nullable;
@@ -36,10 +39,9 @@
 import android.widget.Button;
 import android.widget.ListView;
 
-import com.google.android.car.kitchensink.CarEmulator;
 import com.google.android.car.kitchensink.R;
 
-public class VolumeTestFragment extends Fragment{
+public class VolumeTestFragment extends Fragment {
     private static final String TAG = "CarVolumeTest";
     private static final int MSG_VOLUME_CHANGED = 0;
     private static final int MSG_REQUEST_FOCUS = 1;
@@ -52,7 +54,6 @@
 
     private CarAudioManager mCarAudioManager;
     private Car mCar;
-    private CarEmulator mCarEmulator;
 
     private Button mVolumeUp;
     private Button mVolumeDown;
@@ -140,6 +141,26 @@
             default: return "Unknown";
         }
     }
+    private final ServiceConnection mCarConnectionCallback =
+            new ServiceConnection() {
+                @Override
+                public void onServiceConnected(ComponentName name, IBinder binder) {
+                    Log.d(TAG, "Connected to Car Service");
+                    try {
+                        mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
+                        initVolumeInfo();
+                        mCarAudioManager.setVolumeController(mVolumeController);
+
+                    } catch (CarNotConnectedException e) {
+                        Log.e(TAG, "Car is not connected!", e);
+                    }
+                }
+
+                @Override
+                public void onServiceDisconnected(ComponentName name) {
+                    Log.d(TAG, "Disconnect from Car Service");
+                }
+            };
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -160,33 +181,8 @@
             }
         });
 
-        mCarEmulator = CarEmulator.create(getContext());
-        mCar = mCarEmulator.getCar();
-        try {
-            mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
-            initVolumeInfo();
-            mCarAudioManager.setVolumeController(mVolumeController);
-        } catch (CarNotConnectedException e) {
-            throw new RuntimeException(e); // Should never occur in car emulator.
-        }
-
-        mVolumeUp = (Button) v.findViewById(R.id.volume_up);
-        mVolumeDown = (Button) v.findViewById(R.id.volume_down);
-
-        mVolumeUp.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                mCarEmulator.injectKey(KeyEvent.KEYCODE_VOLUME_UP);
-            }
-        });
-
-        mVolumeDown.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                mCarEmulator.injectKey(KeyEvent.KEYCODE_VOLUME_DOWN);
-            }
-        });
-
+        mCar = Car.createCar(getActivity(), mCarConnectionCallback);
+        mCar.connect();
         return v;
     }
 
@@ -214,7 +210,8 @@
             return;
         }
         try {
-            mCarAudioManager.setStreamVolume(logicalStream, volume, 0);
+            mCarAudioManager.setStreamVolume(logicalStream, volume,
+                    AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND);
         } catch (CarNotConnectedException e) {
             Log.e(TAG, "car not connected", e);
         }
diff --git a/tests/carservice_test/Android.mk b/tests/carservice_test/Android.mk
index 4be5354..9203cbd 100644
--- a/tests/carservice_test/Android.mk
+++ b/tests/carservice_test/Android.mk
@@ -41,7 +41,8 @@
                                vehicle-hal-support-lib \
                                car-systemtest \
                                android-support-test \
-                               android.hardware.automotive.vehicle-V2.0-java-static
+                               android.hardware.automotive.vehicle-V2.0-java \
+                               com.android.car.test.utils
 
 LOCAL_JAVA_LIBRARIES := android.car android.test.runner
 
diff --git a/tests/carservice_test/AndroidManifest.xml b/tests/carservice_test/AndroidManifest.xml
index 6f7ba34..ee4917b 100644
--- a/tests/carservice_test/AndroidManifest.xml
+++ b/tests/carservice_test/AndroidManifest.xml
@@ -24,28 +24,30 @@
     <uses-permission android:name="android.car.permission.CONTROL_APP_BLOCKING" />
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.car.permission.STORAGE_MONITORING" />
     <instrumentation android:name="android.test.InstrumentationTestRunner"
             android:targetPackage="com.android.car.test"
             android:label="Tests for Car APIs"/>
 
     <application android:label="CarServiceTest">
         <uses-library android:name="android.test.runner" />
-        <service android:name="com.android.car.test.TestAppBlockingPolicyService"
+        <service android:name="com.android.car.TestAppBlockingPolicyService"
             android:permission="android.car.permission.CONTROL_APP_BLOCKING">
             <intent-filter>
                 <action android:name="android.car.content.pm.CarAppBlockingPolicyService"/>
             </intent-filter>
         </service>
-        <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityA" />
-        <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityB"
+        <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$ActivityA" />
+        <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$ActivityB"
             android:taskAffinity="com.android.car.carservicetest.activity"/>
-        <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityC"
+        <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$ActivityC"
             android:process="com.android.car.carservicetest.activityC"/>
-        <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$BlockingActivity"
+        <activity android:name="com.android.car.SystemActivityMonitoringServiceTest$BlockingActivity"
             android:taskAffinity="com.android.car.carservicetest.block"/>
-        <service android:name=".SimpleVmsPublisherClientService"
+        <service android:name="com.android.car.SimpleVmsPublisherClientService"
                  android:exported="true"
         />
-        <service android:name=".VmsPublisherClientMockService" android:exported="true" />
+        <service android:name="com.android.car.VmsPublisherClientMockService"
+                 android:exported="true" />
     </application>
 </manifest>
diff --git a/tests/carservice_test/src/com/android/car/test/AppFocusTest.java b/tests/carservice_test/src/com/android/car/AppFocusTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/AppFocusTest.java
rename to tests/carservice_test/src/com/android/car/AppFocusTest.java
index b63383e..d9bce26 100644
--- a/tests/carservice_test/src/com/android/car/test/AppFocusTest.java
+++ b/tests/carservice_test/src/com/android/car/AppFocusTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.CarAppFocusManager;
diff --git a/tests/carservice_test/src/com/android/car/test/AudioRoutingPolicyTest.java b/tests/carservice_test/src/com/android/car/AudioRoutingPolicyTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/AudioRoutingPolicyTest.java
rename to tests/carservice_test/src/com/android/car/AudioRoutingPolicyTest.java
index 7f4aeac..357da1d 100644
--- a/tests/carservice_test/src/com/android/car/test/AudioRoutingPolicyTest.java
+++ b/tests/carservice_test/src/com/android/car/AudioRoutingPolicyTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
 import android.hardware.automotive.vehicle.V2_0.VehicleAudioRoutingPolicyIndex;
diff --git a/tests/carservice_test/src/com/android/car/test/AudioTestUtils.java b/tests/carservice_test/src/com/android/car/AudioTestUtils.java
similarity index 98%
rename from tests/carservice_test/src/com/android/car/test/AudioTestUtils.java
rename to tests/carservice_test/src/com/android/car/AudioTestUtils.java
index 8c3de7c..459daa2 100644
--- a/tests/carservice_test/src/com/android/car/test/AudioTestUtils.java
+++ b/tests/carservice_test/src/com/android/car/AudioTestUtils.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.media.AudioAttributes;
 import android.media.AudioFocusRequest;
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioExtFocusTest.java b/tests/carservice_test/src/com/android/car/CarAudioExtFocusTest.java
similarity index 97%
rename from tests/carservice_test/src/com/android/car/test/CarAudioExtFocusTest.java
rename to tests/carservice_test/src/com/android/car/CarAudioExtFocusTest.java
index 71e0d04..46e1df6 100644
--- a/tests/carservice_test/src/com/android/car/test/CarAudioExtFocusTest.java
+++ b/tests/carservice_test/src/com/android/car/CarAudioExtFocusTest.java
@@ -13,10 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
+import static com.android.car.AudioTestUtils.doRequestFocus;
 import static java.lang.Integer.toHexString;
 
 import android.car.Car;
@@ -227,7 +227,7 @@
     public void testMediaNavFocus() throws Exception {
         //music start
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -249,7 +249,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
@@ -293,7 +293,7 @@
     public void testMediaExternalMediaNavFocus() throws Exception {
         // android music
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -323,7 +323,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
@@ -369,7 +369,7 @@
         assertNotNull(carAudioManager);
         AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
                 CarAudioManager.CAR_AUDIO_USAGE_RADIO);
-        int res = doRequestFocus(mAudioManager, listenerRadio,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerRadio,
                 radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -389,7 +389,7 @@
         AudioFocusListener listenerNav = new AudioFocusListener();
         AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource(
                 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
-        res = doRequestFocus(mAudioManager, listenerNav,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav,
                 extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -438,7 +438,7 @@
     public void testMediaExternalNav() throws Exception {
         // android music
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -458,7 +458,7 @@
         AudioFocusListener listenerNav = new AudioFocusListener();
         AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource(
                 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
-        res = doRequestFocus(mAudioManager, listenerNav,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav,
                 extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -514,7 +514,7 @@
         AudioFocusListener listenerIntNav = new AudioFocusListener();
         AudioAttributes intNavAttributes = mCarAudioManager.getAudioAttributesForCarUsage(
                 CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE);
-        int res = doRequestFocus(mAudioManager, listenerIntNav, intNavAttributes,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerIntNav, intNavAttributes,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -534,7 +534,7 @@
         AudioFocusListener listenerExtNav = new AudioFocusListener();
         AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource(
                 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE);
-        res = doRequestFocus(mAudioManager, listenerExtNav,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerExtNav,
                 extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -582,7 +582,7 @@
     public void testMediaExternalRadioNavMediaFocus() throws Exception {
         // android music
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -605,7 +605,7 @@
         assertNotNull(carAudioManager);
         AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
                 CarAudioManager.CAR_AUDIO_USAGE_RADIO);
-        res = doRequestFocus(mAudioManager, listenerRadio,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerRadio,
                 radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -627,7 +627,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
@@ -763,7 +763,7 @@
         assertNotNull(carAudioManager);
         AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(mediaUsage);
         Log.i(TAG, "request media Focus");
-        int res = doRequestFocus(mAudioManager, listenerMedia,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMedia,
                 radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -807,7 +807,7 @@
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
         Log.i(TAG, "request nav Focus");
-        res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioFocusSystemSoundTest.java b/tests/carservice_test/src/com/android/car/CarAudioFocusSystemSoundTest.java
similarity index 97%
rename from tests/carservice_test/src/com/android/car/test/CarAudioFocusSystemSoundTest.java
rename to tests/carservice_test/src/com/android/car/CarAudioFocusSystemSoundTest.java
index afafb28..5e0d2e7 100644
--- a/tests/carservice_test/src/com/android/car/test/CarAudioFocusSystemSoundTest.java
+++ b/tests/carservice_test/src/com/android/car/CarAudioFocusSystemSoundTest.java
@@ -13,11 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
 import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_STREAM_STATE;
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
+import static com.android.car.AudioTestUtils.doRequestFocus;
 
 import com.google.android.collect.Lists;
 
@@ -137,7 +137,7 @@
         assertNotNull(carAudioManager);
         AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
                 CarAudioManager.CAR_AUDIO_USAGE_RADIO);
-        int res = doRequestFocus(mAudioManager, listenerRadio,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerRadio,
                 radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -191,7 +191,7 @@
     public void testMusicSystemSound() throws Exception {
         // music start
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -247,7 +247,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        int res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioFocusTest.java b/tests/carservice_test/src/com/android/car/CarAudioFocusTest.java
similarity index 96%
rename from tests/carservice_test/src/com/android/car/test/CarAudioFocusTest.java
rename to tests/carservice_test/src/com/android/car/CarAudioFocusTest.java
index 6f5da5f..982924f 100644
--- a/tests/carservice_test/src/com/android/car/test/CarAudioFocusTest.java
+++ b/tests/carservice_test/src/com/android/car/CarAudioFocusTest.java
@@ -13,10 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
 
 import android.car.Car;
 import android.car.media.CarAudioManager;
@@ -136,7 +135,7 @@
     public void testMediaNavFocus() throws Exception {
         //music start
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -156,7 +155,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN, request[0]);
@@ -194,7 +193,7 @@
     public void testMediaExternalMediaNavFocus() throws Exception {
         // android music
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -222,7 +221,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
@@ -259,7 +258,7 @@
     public void testMediaExternalRadioNavMediaFocus() throws Exception {
         // android music
         AudioFocusListener listenerMusic = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -280,7 +279,7 @@
         assertNotNull(carAudioManager);
         AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(
                 CarAudioManager.CAR_AUDIO_USAGE_RADIO);
-        res = doRequestFocus(mAudioManager, listenerRadio,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerRadio,
                 radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -300,7 +299,7 @@
                 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
-        res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN,
@@ -361,7 +360,7 @@
             int context)
             throws Exception {
         AudioFocusListener lister = new AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, lister,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, lister,
                 streamType,
                 androidFocus);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -427,7 +426,7 @@
         assertNotNull(carAudioManager);
         AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(mediaUsage);
         Log.i(TAG, "request media Focus");
-        int res = doRequestFocus(mAudioManager, listenerMedia,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMedia,
                 radioAttributes, AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
         int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -462,7 +461,7 @@
                 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
                 build();
         Log.i(TAG, "request nav Focus");
-        res = doRequestFocus(mAudioManager, listenerNav, navAttrib,
+        res = AudioTestUtils.doRequestFocus(mAudioManager, listenerNav, navAttrib,
                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
         request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
         assertEquals(VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK,
diff --git a/tests/carservice_test/src/com/android/car/test/CarAudioManagerTest.java b/tests/carservice_test/src/com/android/car/CarAudioManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarAudioManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarAudioManagerTest.java
index 07646d4..a66cc60 100644
--- a/tests/carservice_test/src/com/android/car/test/CarAudioManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarAudioManagerTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.media.CarAudioManager;
diff --git a/tests/carservice_test/src/com/android/car/test/CarCabinManagerTest.java b/tests/carservice_test/src/com/android/car/CarCabinManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarCabinManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarCabinManagerTest.java
index cef163e..58b784b 100644
--- a/tests/carservice_test/src/com/android/car/test/CarCabinManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarCabinManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.hardware.CarPropertyValue;
diff --git a/tests/carservice_test/src/com/android/car/test/CarDiagnosticConstantsTest.java b/tests/carservice_test/src/com/android/car/CarDiagnosticConstantsTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarDiagnosticConstantsTest.java
rename to tests/carservice_test/src/com/android/car/CarDiagnosticConstantsTest.java
index 2ed2658..33be912 100644
--- a/tests/carservice_test/src/com/android/car/test/CarDiagnosticConstantsTest.java
+++ b/tests/carservice_test/src/com/android/car/CarDiagnosticConstantsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
diff --git a/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java b/tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java
similarity index 98%
rename from tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java
index b77a844..eb7ef57 100644
--- a/tests/carservice_test/src/com/android/car/test/CarDiagnosticManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import static java.lang.Integer.toHexString;
 
@@ -43,6 +43,7 @@
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
@@ -190,6 +191,7 @@
     @Override
     protected synchronized void configureMockedHal() {
         java.util.Collection<Integer> numVendorSensors = Arrays.asList(0, 0);
+        java.util.Collection<Integer> selectiveClear = Collections.singletonList(1);
         addProperty(VehicleProperty.OBD2_LIVE_FRAME, mLiveFrameEventBuilder.build())
                 .setConfigArray(numVendorSensors);
         addProperty(
@@ -199,7 +201,8 @@
                 .setConfigArray(numVendorSensors);
         addProperty(
                 VehicleProperty.OBD2_FREEZE_FRAME_CLEAR,
-                mFreezeFrameProperties.mFreezeFrameClearHandler);
+                mFreezeFrameProperties.mFreezeFrameClearHandler)
+                .setConfigArray(selectiveClear);
     }
 
     @Override
@@ -732,6 +735,7 @@
         assertTrue(mCarDiagnosticManager.isFreezeFrameNotificationSupported());
         assertTrue(mCarDiagnosticManager.isGetFreezeFrameSupported());
         assertTrue(mCarDiagnosticManager.isClearFreezeFramesSupported());
+        assertTrue(mCarDiagnosticManager.isSelectiveClearFreezeFramesSupported());
     }
 
     class Listener implements CarDiagnosticManager.OnDiagnosticEventListener {
diff --git a/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java b/tests/carservice_test/src/com/android/car/CarHvacManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarHvacManagerTest.java
index 07f879e..9c89694 100644
--- a/tests/carservice_test/src/com/android/car/test/CarHvacManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarHvacManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.hardware.CarPropertyValue;
diff --git a/tests/carservice_test/src/com/android/car/test/CarInfoManagerTest.java b/tests/carservice_test/src/com/android/car/CarInfoManagerTest.java
similarity index 98%
rename from tests/carservice_test/src/com/android/car/test/CarInfoManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarInfoManagerTest.java
index 2cdbbb0..fe32615 100644
--- a/tests/carservice_test/src/com/android/car/test/CarInfoManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarInfoManagerTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.CarInfoManager;
diff --git a/tests/carservice_test/src/com/android/car/test/CarPackageManagerTest.java b/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarPackageManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
index c455bc4..ffbf5a4 100644
--- a/tests/carservice_test/src/com/android/car/test/CarPackageManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.CarNotConnectedException;
diff --git a/tests/carservice_test/src/com/android/car/test/CarPowerManagementTest.java b/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarPowerManagementTest.java
rename to tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
index d5e5bf8..64d9b82 100644
--- a/tests/carservice_test/src/com/android/car/test/CarPowerManagementTest.java
+++ b/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerBootupReason;
 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerSetState;
diff --git a/tests/carservice_test/src/com/android/car/test/CarProjectionManagerTest.java b/tests/carservice_test/src/com/android/car/CarProjectionManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarProjectionManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarProjectionManagerTest.java
index adf288c..773a296 100644
--- a/tests/carservice_test/src/com/android/car/test/CarProjectionManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarProjectionManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.CarProjectionManager;
diff --git a/tests/carservice_test/src/com/android/car/test/CarRadioManagerTest.java b/tests/carservice_test/src/com/android/car/CarRadioManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarRadioManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarRadioManagerTest.java
index 169a370..7288259 100644
--- a/tests/carservice_test/src/com/android/car/test/CarRadioManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarRadioManagerTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.hardware.radio.CarRadioEvent;
diff --git a/tests/carservice_test/src/com/android/car/test/CarSensorManagerTest.java b/tests/carservice_test/src/com/android/car/CarSensorManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarSensorManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarSensorManagerTest.java
index daddfdb..00120a3 100644
--- a/tests/carservice_test/src/com/android/car/test/CarSensorManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarSensorManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.car.Car;
 import android.car.CarNotConnectedException;
diff --git a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
new file mode 100644
index 0000000..cd104f8
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import android.car.Car;
+import android.car.storagemonitoring.CarStorageMonitoringManager;
+import android.car.storagemonitoring.WearEstimate;
+import android.test.suitebuilder.annotation.MediumTest;
+import com.android.car.storagemonitoring.WearInformation;
+
+/** Test the public entry points for the CarStorageMonitoringManager */
+@MediumTest
+public class CarStorageMonitoringTest extends MockedCarTestBase {
+    private static final String TAG = CarStorageMonitoringTest.class.getSimpleName();
+
+    private static final WearInformation DEFAULT_WEAR_INFORMATION =
+        new WearInformation(10, 0, WearInformation.PRE_EOL_INFO_NORMAL);
+
+    private CarStorageMonitoringManager mCarStorageMonitoringManager;
+
+    @Override
+    protected synchronized void configureFakeSystemInterface() {
+        setFlashWearInformation(DEFAULT_WEAR_INFORMATION);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mCarStorageMonitoringManager =
+            (CarStorageMonitoringManager) getCar().getCarManager(Car.STORAGE_MONITORING_SERVICE);
+    }
+
+    public void testReadPreEolInformation() throws Exception {
+        assertEquals(DEFAULT_WEAR_INFORMATION.preEolInfo,
+                mCarStorageMonitoringManager.getPreEolIndicatorStatus());
+    }
+
+    public void testReadWearEstimate() throws Exception {
+        final WearEstimate wearEstimate = mCarStorageMonitoringManager.getWearEstimate();
+
+        assertNotNull(wearEstimate);
+        assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateA, wearEstimate.typeA);
+        assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateB, wearEstimate.typeB);
+    }
+}
diff --git a/tests/carservice_test/src/com/android/car/test/CarVendorExtensionManagerTest.java b/tests/carservice_test/src/com/android/car/CarVendorExtensionManagerTest.java
similarity index 99%
rename from tests/carservice_test/src/com/android/car/test/CarVendorExtensionManagerTest.java
rename to tests/carservice_test/src/com/android/car/CarVendorExtensionManagerTest.java
index fa33e56..29b24e3 100644
--- a/tests/carservice_test/src/com/android/car/test/CarVendorExtensionManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarVendorExtensionManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import static com.android.car.CarServiceUtils.toByteArray;
 
diff --git a/tests/carservice_test/src/com/android/car/test/CarVolumeServiceTest.java b/tests/carservice_test/src/com/android/car/CarVolumeServiceTest.java
similarity index 90%
rename from tests/carservice_test/src/com/android/car/test/CarVolumeServiceTest.java
rename to tests/carservice_test/src/com/android/car/CarVolumeServiceTest.java
index 2e92a59..0d9a607 100644
--- a/tests/carservice_test/src/com/android/car/test/CarVolumeServiceTest.java
+++ b/tests/carservice_test/src/com/android/car/CarVolumeServiceTest.java
@@ -13,9 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
-
-import static com.android.car.test.AudioTestUtils.doRequestFocus;
+package com.android.car;
 
 import android.car.Car;
 import android.car.CarNotConnectedException;
@@ -40,13 +38,12 @@
 import android.util.SparseIntArray;
 import android.view.KeyEvent;
 
-import com.android.car.VolumeUtils;
+import com.google.android.collect.Lists;
+
 import com.android.car.vehiclehal.VehiclePropValueBuilder;
 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
 import com.android.internal.annotations.GuardedBy;
 
-import com.google.android.collect.Lists;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -54,7 +51,6 @@
 public class CarVolumeServiceTest extends MockedCarTestBase {
     private static final String TAG = CarVolumeServiceTest.class.getSimpleName();
 
-    private static final int MIN_VOL = 1;
     private static final int MAX_VOL = 20;
     private static final long TIMEOUT_MS = 3000;
     private static final long POLL_INTERVAL_MS = 50;
@@ -101,7 +97,7 @@
             }
         }
         SingleChannelVolumeHandler handler =
-                startVolumeEmulation(supportedAudioContext, maxs);
+                startVolumeEmulation(true, supportedAudioContext, maxs);
         mCarAudioManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE);
         return handler;
     }
@@ -114,7 +110,7 @@
         // give focus to music, now current context becomes VehicleAudioContextFlag.MUSIC_FLAG
         CarAudioFocusTest.AudioFocusListener listenerMusic =
                 new CarAudioFocusTest.AudioFocusListener();
-        int res = doRequestFocus(mAudioManager, listenerMusic,
+        int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.AUDIOFOCUS_GAIN);
         assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -138,7 +134,7 @@
         }
     }
 
-    public void testVolumeSet() throws Exception {
+    public void testVolumeSet() {
         try {
             setupExternalVolumeEmulation(false);
             int callVol = 10;
@@ -154,8 +150,27 @@
 
             volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, MAX_VOL),
                     createStreamVolPair(AudioManager.STREAM_VOICE_CALL, callVol));
-        } catch (CarNotConnectedException e) {
-            fail("Car not connected");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+    }
+
+    public void testMultipleVolumeControllers() {
+        try {
+            startVolumeEmulation(false, 0, new ArrayList<>());
+            mCarAudioManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE);
+            mCarAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
+            VolumeController volumeController1 = new VolumeController();
+            VolumeController volumeController2 = new VolumeController();
+            mCarAudioManager.setVolumeController(volumeController1);
+            mCarAudioManager.setVolumeController(volumeController2);
+
+            mCarAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
+                    1, AudioManager.FLAG_SHOW_UI);
+            volumeChangeVerificationPoll(AudioManager.STREAM_MUSIC, true, volumeController1);
+            volumeChangeVerificationPoll(AudioManager.STREAM_MUSIC, true, volumeController2);
+        } catch (Exception e) {
+            fail(e.getMessage());
         }
     }
 
@@ -168,7 +183,7 @@
             // first give focus to system sound
             CarAudioFocusTest.AudioFocusListener listenerMusic =
                     new CarAudioFocusTest.AudioFocusListener();
-            int res = doRequestFocus(mAudioManager, listenerMusic,
+            int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                     AudioManager.STREAM_SYSTEM,
                     AudioManager.AUDIOFOCUS_GAIN);
             assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -184,7 +199,7 @@
             AudioAttributes callAttrib = (new AudioAttributes.Builder()).
                     setUsage(AudioAttributes.USAGE_ALARM).
                     build();
-            res = doRequestFocus(mAudioManager, listenerAlarm, callAttrib,
+            res = AudioTestUtils.doRequestFocus(mAudioManager, listenerAlarm, callAttrib,
                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
             assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
             request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
@@ -207,7 +222,7 @@
         }
     }
 
-    public void testVolumeKeys() throws Exception {
+    public void testVolumeKeys() {
         try {
             setupExternalVolumeEmulation(false);
             int musicVol = 10;
@@ -217,7 +232,7 @@
 
             CarAudioFocusTest.AudioFocusListener listenerMusic =
                     new CarAudioFocusTest.AudioFocusListener();
-            int res = doRequestFocus(mAudioManager, listenerMusic,
+            int res = AudioTestUtils.doRequestFocus(mAudioManager, listenerMusic,
                     AudioManager.STREAM_MUSIC,
                     AudioManager.AUDIOFOCUS_GAIN);
             assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res);
@@ -239,7 +254,7 @@
             AudioAttributes callAttrib = (new AudioAttributes.Builder()).
                     setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION).
                     build();
-            doRequestFocus(mAudioManager, listenerCall, callAttrib,
+            AudioTestUtils.doRequestFocus(mAudioManager, listenerCall, callAttrib,
                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
             request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS);
             mAudioFocusPropertyHandler.sendAudioFocusState(
@@ -250,7 +265,7 @@
             callVol++;
             volumeVerificationPoll(createStreamVolPair(AudioManager.STREAM_MUSIC, musicVol),
                     createStreamVolPair(AudioManager.STREAM_VOICE_CALL, callVol));
-        } catch (CarNotConnectedException | InterruptedException e) {
+        } catch (Exception e) {
             fail(e.toString());
         }
     }
@@ -411,8 +426,8 @@
                 }
             };
 
-    private SingleChannelVolumeHandler startVolumeEmulation(int supportedAudioVolumeContext,
-            List<Integer> maxs) {
+    private SingleChannelVolumeHandler startVolumeEmulation(boolean supportExternalVolume,
+            int supportedAudioVolumeContext, List<Integer> maxs) {
         SingleChannelVolumeHandler singleChannelVolumeHandler =
                 new SingleChannelVolumeHandler(maxs);
         int zones = (1<<maxs.size()) - 1;
@@ -425,9 +440,11 @@
                         0  /* reserved */);
         audioVolumeConfigArray.addAll(maxs);
 
-        addProperty(VehicleProperty.AUDIO_VOLUME, singleChannelVolumeHandler)
-                        .setConfigArray(audioVolumeConfigArray)
-                        .setSupportedAreas(zones);
+        if (supportExternalVolume) {
+            addProperty(VehicleProperty.AUDIO_VOLUME, singleChannelVolumeHandler)
+                    .setConfigArray(audioVolumeConfigArray)
+                    .setSupportedAreas(zones);
+        }
 
         addProperty(VehicleProperty.HW_KEY_INPUT, mHWKeyHandler)
                 .setAccess(VehiclePropertyAccess.READ);
diff --git a/tests/carservice_test/src/com/android/car/test/GarageModeTest.java b/tests/carservice_test/src/com/android/car/GarageModeTest.java
similarity index 96%
rename from tests/carservice_test/src/com/android/car/test/GarageModeTest.java
rename to tests/carservice_test/src/com/android/car/GarageModeTest.java
index 19ccb6e..06abdc8 100644
--- a/tests/carservice_test/src/com/android/car/test/GarageModeTest.java
+++ b/tests/carservice_test/src/com/android/car/GarageModeTest.java
@@ -13,17 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.settings.CarSettings;
 import android.content.Context;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.android.car.CarPowerManagementService;
-import com.android.car.DeviceIdleControllerWrapper;
-import com.android.car.GarageModeService;
-
 @MediumTest
 public class GarageModeTest extends AndroidTestCase {
 
diff --git a/tests/carservice_test/src/com/android/car/test/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
similarity index 76%
rename from tests/carservice_test/src/com/android/car/test/MockedCarTestBase.java
rename to tests/carservice_test/src/com/android/car/MockedCarTestBase.java
index a060496..f670832 100644
--- a/tests/carservice_test/src/com/android/car/test/MockedCarTestBase.java
+++ b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.test.CarTestManager;
 import android.car.test.CarTestManagerBinderWrapper;
@@ -28,18 +28,22 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-import com.android.car.CarPowerManagementService;
-import com.android.car.ICarImpl;
-import com.android.car.SystemInterface;
+import com.android.car.MockedCarTestBase.FakeSystemInterface.UptimeProvider;
+import com.android.car.storagemonitoring.WearInformation;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.test.utils.TemporaryDirectory;
 import com.android.car.vehiclehal.test.MockedVehicleHal;
 import com.android.car.vehiclehal.test.MockedVehicleHal.DefaultPropertyHandler;
 import com.android.car.vehiclehal.test.MockedVehicleHal.StaticPropertyHandler;
 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
 import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
@@ -75,9 +79,24 @@
         return mMockedVehicleHal;
     }
 
+    protected synchronized FakeSystemInterface getFakeSystemInterface() {
+        return mFakeSystemInterface;
+    }
+
     protected synchronized void configureMockedHal() {
     }
 
+    protected synchronized void configureFakeSystemInterface() {
+    }
+
+    protected synchronized void setFlashWearInformation(WearInformation wearInformation) {
+        mFakeSystemInterface.mWearInformationProvider.setWearInformation(wearInformation);
+    }
+
+    protected synchronized void setUptimeProvider(UptimeProvider uptimeProvider) {
+        mFakeSystemInterface.mUptimeProvider = uptimeProvider;
+    }
+
     @Override
     protected synchronized void setUp() throws Exception {
         super.setUp();
@@ -88,6 +107,8 @@
         configureMockedHal();
 
         mFakeSystemInterface = new FakeSystemInterface();
+        configureFakeSystemInterface();
+
         Context context = getCarServiceContext();
         mCarImpl = new ICarImpl(context, mMockedVehicleHal, mFakeSystemInterface,
                 null /* error notifier */);
@@ -103,6 +124,8 @@
 
         mCar.disconnect();
         mCarImpl.release();
+
+        mFakeSystemInterface.tearDown();
     }
 
     protected Context getCarServiceContext() throws NameNotFoundException {
@@ -239,10 +262,28 @@
         }
     }
 
-    private static class FakeSystemInterface extends SystemInterface {
+    static class FakeSystemInterface extends SystemInterface {
+        interface UptimeProvider {
+            long getUptime(boolean includeDeepSleepTime);
+        }
 
         private boolean mDisplayOn = true;
         private final Semaphore mDisplayStateWait = new Semaphore(0);
+        private final class FakeWearInformationProvider implements WearInformationProvider {
+            private WearInformation mWearInformation = null;
+            public void setWearInformation(WearInformation wearInformation) {
+                mWearInformation = wearInformation;
+            }
+
+            @Override
+            public WearInformation load() {
+                return mWearInformation;
+            }
+        }
+        private final FakeWearInformationProvider mWearInformationProvider =
+                new FakeWearInformationProvider();
+        private TemporaryDirectory mFilesDir = null;
+        private UptimeProvider mUptimeProvider = null;
 
         @Override
         public synchronized void setDisplayState(boolean on) {
@@ -292,5 +333,41 @@
 
         @Override
         public boolean isWakeupCausedByTimer() { return false; }
+
+        @Override
+        public WearInformationProvider[] getFlashWearInformationProviders() {
+            return new WearInformationProvider[] { mWearInformationProvider };
+        }
+
+        @Override
+        public File getFilesDir() {
+            if (mFilesDir == null) {
+                try {
+                    mFilesDir = new TemporaryDirectory(TAG);
+                } catch (IOException e) {
+                    Log.e(TAG, "failed to create temporary directory", e);
+                    fail("failed to create temporary directory. exception was: " + e);
+                }
+            }
+            return mFilesDir.getDirectory();
+        }
+
+        @Override
+        public long getUptime(boolean includeDeepSleepTime) {
+            if (mUptimeProvider != null) {
+                return mUptimeProvider.getUptime(includeDeepSleepTime);
+            }
+            return super.getUptime(includeDeepSleepTime);
+        }
+
+        void tearDown() {
+            if (mFilesDir != null) {
+                try {
+                    mFilesDir.close();
+                } catch (Exception e) {
+                    Log.w(TAG, "could not remove temporary directory", e);
+                }
+            }
+        }
     }
 }
diff --git a/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java b/tests/carservice_test/src/com/android/car/SimpleVmsPublisherClientService.java
similarity index 93%
rename from tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java
rename to tests/carservice_test/src/com/android/car/SimpleVmsPublisherClientService.java
index c3c15f5..53491b1 100644
--- a/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java
+++ b/tests/carservice_test/src/com/android/car/SimpleVmsPublisherClientService.java
@@ -14,16 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsPublisherClientService;
 import android.car.vms.VmsSubscriptionState;
 
 /**
  * This service is launched during the tests in VmsPublisherClientServiceTest.
  */
-@FutureFeature
 public class SimpleVmsPublisherClientService extends VmsPublisherClientService {
     @Override
     public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
diff --git a/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java b/tests/carservice_test/src/com/android/car/SystemActivityMonitoringServiceTest.java
similarity index 98%
rename from tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java
rename to tests/carservice_test/src/com/android/car/SystemActivityMonitoringServiceTest.java
index 3345605..d95170d 100644
--- a/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java
+++ b/tests/carservice_test/src/com/android/car/SystemActivityMonitoringServiceTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.app.Activity;
 import android.content.ComponentName;
@@ -25,7 +25,6 @@
 import android.os.SystemClock;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.android.car.SystemActivityMonitoringService;
 import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
 import com.android.car.vehiclehal.VehiclePropValueBuilder;
 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
diff --git a/tests/carservice_test/src/com/android/car/test/TestAppBlockingPolicyService.java b/tests/carservice_test/src/com/android/car/TestAppBlockingPolicyService.java
similarity index 98%
rename from tests/carservice_test/src/com/android/car/test/TestAppBlockingPolicyService.java
rename to tests/carservice_test/src/com/android/car/TestAppBlockingPolicyService.java
index dc1ad8a..ec30d0d 100644
--- a/tests/carservice_test/src/com/android/car/test/TestAppBlockingPolicyService.java
+++ b/tests/carservice_test/src/com/android/car/TestAppBlockingPolicyService.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.car.test;
+package com.android.car;
 
 import android.car.content.pm.AppBlockingPackageInfo;
 import android.car.content.pm.CarAppBlockingPolicy;
diff --git a/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java b/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
similarity index 95%
rename from tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java
rename to tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
index cad3086..286c004 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import static org.junit.Assume.assumeTrue;
 
 import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsLayer;
 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
@@ -41,7 +40,6 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-@FutureFeature
 @MediumTest
 public class VmsHalServiceSubscriptionEventTest extends MockedCarTestBase {
     private static final String TAG = "VmsHalServiceTest";
@@ -62,7 +60,6 @@
 
     @Override
     protected void setUp() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.setUp();
         mHal = getMockedVehicleHal();
         mHalHandlerSemaphore = new Semaphore(0);
@@ -70,24 +67,20 @@
 
     @Override
     protected synchronized void tearDown() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.tearDown();
     }
 
     public void testEmptySubscriptions() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         List<VmsLayer> layers = new ArrayList<>();
         subscriptionTestLogic(layers);
     }
 
     public void testOneSubscription() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         List<VmsLayer> layers = Arrays.asList(new VmsLayer(8, 0, 3));
         subscriptionTestLogic(layers);
     }
 
     public void testManySubscriptions() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         List<VmsLayer> layers = Arrays.asList(
                 new VmsLayer(8, 1, 3),
                 new VmsLayer(5, 2, 1),
diff --git a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java b/tests/carservice_test/src/com/android/car/VmsOperationRecorderTest.java
similarity index 73%
rename from tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
rename to tests/carservice_test/src/com/android/car/VmsOperationRecorderTest.java
index a00ec68..f6b3be5 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsOperationRecorderTest.java
@@ -14,16 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.car.vms.VmsLayer;
 import android.car.vms.VmsLayerDependency;
 import android.car.vms.VmsLayersOffering;
 import android.car.vms.VmsOperationRecorder;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
 
 import junit.framework.TestCase;
 
+import org.json.JSONArray;
+import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.util.ArrayList;
@@ -53,6 +56,7 @@
 
     private TestWriter mWriter;
     private VmsOperationRecorder mRecorder;
+    private static final String TAG = "VmsOperationRecorderTest";
 
     private static final VmsLayer layer1 = new VmsLayer(1, 3, 2);
     private static final VmsLayer layer2 = new VmsLayer(2, 4, 3);
@@ -76,7 +80,7 @@
 
     public void testSubscribe() throws Exception {
         mRecorder.subscribe(layer1);
-        assertJsonMsgEquals("{'subscribe':{'layer':{'type':1,'subtype':3,'version':2}}}");
+        assertJsonMsgEquals("{'subscribe':{'layer':{'subtype':3,'type':1,'version':2}}}");
     }
 
     public void testUnsubscribe() throws Exception {
@@ -177,8 +181,65 @@
         // quotes instead, which gets replaced here.
         JSONObject expect = new JSONObject(expectJson.replace("'", "\""));
         JSONObject got = new JSONObject(mWriter.mMsg);
-        // Comparing the JSON strings works and is not flakey only because the JSON library
-        // generates a consistent string representation when object construction is consistent.
-        assertEquals(expect.toString(), got.toString());
+        assertTrue(similar(expect, got));
+    }
+
+    /*
+     * Determine if two JSONObjects are similar.
+     * They must contain the same set of names which must be associated with
+     * similar values.
+     */
+    private boolean similar(JSONObject expect, JSONObject got) {
+        try {
+            if (!expect.keySet().equals(got.keySet())) {
+                return false;
+            }
+
+            for (String key : expect.keySet()) {
+                Object valueExpect = expect.get(key);
+                Object valueGot = got.get(key);
+
+                if (valueExpect == valueGot) {
+                    continue;
+                }
+
+                if (valueExpect == null) {
+                    return false;
+                }
+
+                if (valueExpect instanceof JSONObject) {
+                    return similar((JSONObject) valueExpect, (JSONObject) valueGot);
+                } else if (valueExpect instanceof JSONArray) {
+                    // Equal JSONArray have the same length and one contains the other.
+                    JSONArray expectArray = (JSONArray) valueExpect;
+                    JSONArray gotArray = (JSONArray) valueGot;
+
+                    if (expectArray.length() != gotArray.length()) {
+                        return false;
+                    }
+
+                    for (int i = 0; i < expectArray.length(); i++) {
+                        boolean gotContainsSimilar = false;
+                        for (int j = 0; j < gotArray.length(); j++) {
+                            if (similar((JSONObject) expectArray.get(i),
+                                    (JSONObject) gotArray.get(j))) {
+                                gotContainsSimilar = true;
+                                break;
+                            }
+                        }
+                        if (!gotContainsSimilar) {
+                            return false;
+                        }
+                    }
+                } else if (!valueExpect.equals(valueGot)) {
+                    return false;
+                }
+            }
+
+        } catch (JSONException e) {
+            Log.d(TAG, "Could not compare JSONObjects: " + e);
+            return false;
+        }
+        return true;
     }
 }
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java b/tests/carservice_test/src/com/android/car/VmsPublisherClientMockService.java
similarity index 96%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherClientMockService.java
index 0d5c427..32d224b 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherClientMockService.java
@@ -14,18 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsLayer;
 import android.car.vms.VmsLayerDependency;
 import android.car.vms.VmsLayersOffering;
 import android.car.vms.VmsPublisherClientService;
 import android.car.vms.VmsSubscriptionState;
 import android.util.Log;
-import java.util.ArrayList;
+
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 /**
@@ -43,7 +41,6 @@
  * both potential scenarios, this service publishes the test message in onVmsSubscriptionChange
  * and in onVmsPublisherServiceReady. See comments below.
  */
-@FutureFeature
 public class VmsPublisherClientMockService extends VmsPublisherClientService {
     private static final String TAG = "VmsPublisherClientMockService";
 
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherClientServiceTest.java
similarity index 94%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherClientServiceTest.java
index 053bab7..0a53092 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherClientServiceTest.java
@@ -14,27 +14,25 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.annotation.ArrayRes;
 import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsLayer;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
 import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
-import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
 import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
+import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
 
-import com.android.car.R;
 import com.android.car.vehiclehal.VehiclePropValueBuilder;
 import com.android.car.vehiclehal.test.MockedVehicleHal;
 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
@@ -44,7 +42,6 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-@FutureFeature
 @MediumTest
 public class VmsPublisherClientServiceTest extends MockedCarTestBase {
     private static final String TAG = "VmsPublisherTest";
@@ -85,8 +82,12 @@
             @Override
             public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
                 if (id == R.array.vmsPublisherClients) {
-                    return new String[]{"com.android.car.test/.SimpleVmsPublisherClientService"};
+                    return new String[] {
+                            javaClassToComponent(
+                                    getContext(), SimpleVmsPublisherClientService.class)
+                    };
                 }
+
                 return super.getStringArray(id);
             }
         };
@@ -110,7 +111,6 @@
 
     @Override
     protected void setUp() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         /**
          * First init the semaphore, setUp will start a series of events that will ultimately
          * update the HAL layer and release this semaphore.
@@ -125,10 +125,13 @@
 
     @Override
     protected synchronized void tearDown() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.tearDown();
     }
 
+    static String javaClassToComponent(Context context, Class<?> clazz) {
+        return context.getPackageName() +  "/" + clazz.getName();
+    }
+
     /**
      * The method setUp initializes all the Car services, including the VmsPublisherService.
      * The VmsPublisherService will start and configure its list of clients. This list was
@@ -138,7 +141,6 @@
      * this test.
      */
     public void testPublish() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         //TODO: This test is using minial synchronisation between clients.
         //      If more complexity is added this may result in publisher
         //      publishing before the subscriber subscribed, in which case
@@ -165,7 +167,7 @@
         public synchronized void onPropertySet(VehiclePropValue value) {
             mValue = value;
 
-            // If this is the data message release the semaphone so the test can continue.
+            // If this is the data message release the semaphore so the test can continue.
             ArrayList<Integer> int32Values = value.value.int32Values;
             if (int32Values.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE) ==
                     VmsMessageType.DATA) {
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherPermissionsTest.java
similarity index 95%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherPermissionsTest.java
index 1d14c57..14a2f18 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherPermissionsTest.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import android.annotation.ArrayRes;
 import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.PackageManager;
@@ -31,7 +30,6 @@
 import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.android.car.R;
 import com.android.car.vehiclehal.VehiclePropValueBuilder;
 import com.android.car.vehiclehal.test.MockedVehicleHal;
 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
@@ -40,7 +38,6 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-@FutureFeature
 @MediumTest
 public class VmsPublisherPermissionsTest extends MockedCarTestBase {
     private static final String TAG = "VmsPublisherTest";
@@ -104,7 +101,6 @@
 
     @Override
     protected void setUp() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         /**
          * First init the semaphore, setUp will start a series of events that will ultimately
          * update the HAL layer and release this semaphore.
@@ -119,7 +115,6 @@
 
     @Override
     protected synchronized void tearDown() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.tearDown();
     }
 
@@ -132,7 +127,6 @@
      * this test.
      */
     public void testPermissions() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
         // At this point the client initialization finished. Let's validate the permissions.
         // The VMS service is only allowed to grant ACCESS_FINE_LOCATION but not CAMERA.
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java b/tests/carservice_test/src/com/android/car/VmsPublisherSubscriberTest.java
similarity index 93%
rename from tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
rename to tests/carservice_test/src/com/android/car/VmsPublisherSubscriberTest.java
index 5b387d2..89dcba9 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsPublisherSubscriberTest.java
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
+
+import static com.android.car.VmsPublisherClientServiceTest.javaClassToComponent;
 
 import android.annotation.ArrayRes;
 import android.car.Car;
 import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsAssociatedLayer;
 import android.car.vms.VmsLayer;
 import android.car.vms.VmsSubscriberManager;
@@ -41,7 +42,6 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-@FutureFeature
 @MediumTest
 public class VmsPublisherSubscriberTest extends MockedCarTestBase {
     private static final int LAYER_ID = 88;
@@ -97,8 +97,11 @@
             @Override
             public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
                 if (id == com.android.car.R.array.vmsPublisherClients) {
-                    return new String[]{"com.android.car.test/.VmsPublisherClientMockService"};
+                    return new String[] {
+                            javaClassToComponent(getContext(), VmsPublisherClientMockService.class)
+                    };
                 }
+
                 return super.getStringArray(id);
             }
         };
@@ -113,7 +116,6 @@
 
     @Override
     protected void setUp() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.setUp();
         mSubscriberSemaphore = new Semaphore(0);
         mAvailabilitySemaphore = new Semaphore(0);
@@ -121,7 +123,6 @@
 
     @Override
     protected synchronized void tearDown() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.tearDown();
     }
 
@@ -134,7 +135,6 @@
      * a message, which is validated in this test.
      */
     public void testPublisherToSubscriber() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -153,7 +153,6 @@
      * that the Mock service has gotten its ServiceReady and publisherId.
      */
     public void testPublisherInfo() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         // Subscribe to layer as a way to make sure the mock client completed setting the information.
@@ -173,7 +172,6 @@
      * notification that it is available.
      */
     public void testAvailabilityWithSubscription() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
             Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -181,7 +179,7 @@
         vmsSubscriberManager.subscribe(SUBSCRIBED_LAYER);
 
         assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
-        assertEquals(AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER, clientCallback.getAvailalbeLayers());
+        assertEquals(AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER, clientCallback.getAvailableLayers());
     }
 
     /**
@@ -190,14 +188,13 @@
      * is available.
      */
     public void testAvailabilityWithoutSubscription() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
         vmsSubscriberManager.registerClientCallback(clientCallback);
 
         assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
-        assertEquals(AVAILABLE_ASSOCIATED_LAYERS, clientCallback.getAvailalbeLayers());
+        assertEquals(AVAILABLE_ASSOCIATED_LAYERS, clientCallback.getAvailableLayers());
     }
 
     private class HalHandler implements MockedVehicleHal.VehicleHalPropertyHandler {
@@ -231,7 +228,7 @@
             return mPayload;
         }
 
-        public List<VmsLayer> getAvailalbeLayers() {
+        public List<VmsLayer> getAvailableLayers() {
             return mAvailableLayers;
         }
     }
diff --git a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java b/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
similarity index 96%
rename from tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
rename to tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
index 8e0c91b..954afee 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.car.test;
+package com.android.car;
 
 import static org.junit.Assume.assumeTrue;
 
 import android.car.Car;
 import android.car.VehicleAreaType;
-import android.car.annotation.FutureFeature;
 import android.car.vms.VmsAssociatedLayer;
 import android.car.vms.VmsLayer;
 import android.car.vms.VmsSubscriberManager;
@@ -44,7 +43,6 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-@FutureFeature
 @MediumTest
 public class VmsSubscriberManagerTest extends MockedCarTestBase {
     private static final String TAG = "VmsSubscriberManagerTest";
@@ -102,7 +100,6 @@
 
     @Override
     protected void setUp() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.setUp();
         mSubscriberSemaphore = new Semaphore(0);
         mHalHandlerSemaphore = new Semaphore(0);
@@ -110,13 +107,11 @@
 
     @Override
     protected synchronized void tearDown() throws Exception {
-        if (!VmsTestUtils.canRunTest(TAG)) return;
         super.tearDown();
     }
 
     // Test injecting a value in the HAL and verifying it propagates to a subscriber.
     public void testSubscribe() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -147,7 +142,6 @@
 
     // Test injecting a value in the HAL and verifying it propagates to a subscriber.
     public void testSubscribeToPublisher() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -175,7 +169,6 @@
 
     // Test injecting a value in the HAL and verifying it propagates to a subscriber.
     public void testSubscribeFromPublisher() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -205,7 +198,6 @@
 
     // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
     public void testUnsubscribe() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -233,7 +225,6 @@
 
     // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
     public void testSubscribeFromWrongPublisher() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -260,7 +251,6 @@
 
     // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
     public void testUnsubscribeFromPublisher() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -289,7 +279,6 @@
 
     // Test injecting a value in the HAL and verifying it propagates to a subscriber.
     public void testSubscribeAll() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -319,7 +308,6 @@
 
     // Test injecting a value in the HAL and verifying it propagates to a subscriber.
     public void testSimpleAvailableLayers() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -365,7 +353,6 @@
     // Test injecting a value in the HAL and verifying it propagates to a subscriber after it has
     // subscribed to a layer.
     public void testSimpleAvailableLayersAfterSubscription() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -412,7 +399,6 @@
     // Test injecting a value in the HAL and verifying it does not propagates to a subscriber after
     // it has unregistered its callback.
     public void testSimpleAvailableLayersAfterUnregister() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -455,7 +441,6 @@
     // Test injecting a value in the HAL and verifying it does not propagates to a subscriber after
     // it has unregistered its callback.
     public void testSomething() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
@@ -472,7 +457,6 @@
 
     // Test injecting a value in the HAL and verifying it propagates to a subscriber.
     public void testComplexAvailableLayers() throws Exception {
-        assumeTrue(VmsTestUtils.canRunTest(TAG));
         VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
                 Car.VMS_SUBSCRIBER_SERVICE);
         TestClientCallback clientCallback = new TestClientCallback();
diff --git a/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java b/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java
deleted file mode 100644
index 2f3af52..0000000
--- a/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.car.test;
-
-import android.car.annotation.FutureFeature;
-import android.util.Log;
-
-import com.android.car.internal.FeatureConfiguration;
-
-@FutureFeature
-public class VmsTestUtils {
-    public static boolean canRunTest(String tag) {
-        if (!FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
-            Log.i(tag, "Skipping test because ENABLE_VEHICLE_MAP_SERVICE = false");
-        }
-        return FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE;
-    }
-}
diff --git a/tests/carservice_unit_test/Android.mk b/tests/carservice_unit_test/Android.mk
index 1ec2008..1cf134c 100644
--- a/tests/carservice_unit_test/Android.mk
+++ b/tests/carservice_unit_test/Android.mk
@@ -34,6 +34,10 @@
 LOCAL_INSTRUMENTATION_FOR := CarService
 
 LOCAL_JAVA_LIBRARIES := android.car android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test android-support-test mockito-target-minus-junit4
+LOCAL_STATIC_JAVA_LIBRARIES := junit \
+                               legacy-android-test \
+                               android-support-test \
+                               mockito-target-minus-junit4 \
+                               com.android.car.test.utils
 
 include $(BUILD_PACKAGE)
diff --git a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
index 78f13e3..e09d54d 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.car;
 
+import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -25,6 +26,10 @@
 import com.android.car.hal.PowerHalService;
 import com.android.car.hal.PowerHalService.PowerState;
 
+import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.test.utils.TemporaryDirectory;
+import java.io.File;
+import java.io.IOException;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
@@ -54,6 +59,9 @@
         if (mService != null) {
             mService.release();
         }
+        if (mSystemInterface != null) {
+            mSystemInterface.tearDown();
+        }
     }
 
     public void testBootComplete() throws Exception {
@@ -266,6 +274,7 @@
         private final Semaphore mShutdownWait = new Semaphore(0);
         private final Semaphore mSleepWait = new Semaphore(0);
         private final Semaphore mSleepExitWait = new Semaphore(0);
+        private TemporaryDirectory mFilesDir;
         private int mWakeupTime;
         private boolean mWakeupCausedByTimer = false;
 
@@ -340,6 +349,34 @@
             return mWakeupCausedByTimer;
         }
 
+        @Override
+        public WearInformationProvider[] getFlashWearInformationProviders() {
+            return new WearInformationProvider[] {};
+        }
+
+        @Override
+        public File getFilesDir() {
+            if (mFilesDir == null) {
+                try {
+                    mFilesDir = new TemporaryDirectory(TAG);
+                } catch (IOException e) {
+                    Log.e(TAG, "failed to create temporary directory", e);
+                    fail("failed to create temporary directory. exception was: " + e);
+                }
+            }
+            return mFilesDir.getDirectory();
+        }
+
+        void tearDown() {
+            if (mFilesDir != null) {
+                try {
+                    mFilesDir.close();
+                } catch (Exception e) {
+                    Log.w(TAG, "could not remove temporary directory", e);
+                }
+            }
+        }
+
         public synchronized void setWakeupCausedByTimer(boolean set) {
             mWakeupCausedByTimer = set;
         }
diff --git a/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java b/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
new file mode 100644
index 0000000..a5f12dd
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import com.android.car.test.utils.TemporaryFile;
+
+import junit.framework.TestCase;
+
+@MediumTest
+public class UptimeTrackerTest extends TestCase {
+    static final String TAG = UptimeTrackerTest.class.getSimpleName();
+
+    static final class TestTimingProvider implements UptimeTracker.TimingProvider {
+        private long mCurrentTime = 0;
+        private Runnable mRunnable = null;
+
+        TestTimingProvider incrementTime(long by) {
+            mCurrentTime += by;
+            return this;
+        }
+
+        TestTimingProvider tick() {
+            if (mRunnable != null) {
+                mRunnable.run();
+            }
+            return this;
+        }
+
+        @Override
+        public long getCurrentRealtime() {
+            return mCurrentTime;
+        }
+
+        @Override
+        public void schedule(Runnable r, long delay) {
+            if (mRunnable != null) {
+                throw new IllegalStateException("task already scheduled");
+            }
+            mRunnable = r;
+        }
+
+        @Override
+        public void cancelAll() {
+            mRunnable = null;
+        }
+    }
+
+    private static final long SNAPSHOT_INTERVAL = 0; // actual time doesn't matter for this test
+
+    public void testUptimeTrackerFromCleanSlate() throws Exception {
+        TestTimingProvider timingProvider = new TestTimingProvider();
+        try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+            UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+                SNAPSHOT_INTERVAL, timingProvider);
+
+            assertEquals(0, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(5000).tick();
+            assertEquals(5000, uptimeTracker.getTotalUptime());
+
+            timingProvider.tick();
+            assertEquals(5000, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(1000).tick();
+            assertEquals(6000, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(400).tick();
+            assertEquals(6400, uptimeTracker.getTotalUptime());
+        }
+    }
+
+    public void testUptimeTrackerWithHistoricalState() throws Exception {
+        TestTimingProvider timingProvider = new TestTimingProvider();
+        try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+            uptimeFile.write("{\"uptime\" : 5000}");
+            UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+                SNAPSHOT_INTERVAL, timingProvider);
+
+            assertEquals(5000, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(5000).tick();
+            assertEquals(10000, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(1000).tick();
+            assertEquals(11000, uptimeTracker.getTotalUptime());
+        }
+    }
+
+    public void testUptimeTrackerAcrossHistoricalState() throws Exception {
+        TestTimingProvider timingProvider = new TestTimingProvider();
+        try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+            uptimeFile.write("{\"uptime\" : 5000}");
+            UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+                SNAPSHOT_INTERVAL, timingProvider);
+
+            assertEquals(5000, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(5000).tick();
+            assertEquals(10000, uptimeTracker.getTotalUptime());
+
+            timingProvider.incrementTime(500).tick();
+            uptimeTracker.onDestroy();
+            timingProvider.cancelAll();
+
+            uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+                SNAPSHOT_INTERVAL, timingProvider);
+
+            timingProvider.incrementTime(3000).tick();
+            assertEquals(13500, uptimeTracker.getTotalUptime());
+        }
+    }
+
+    public void testUptimeTrackerShutdown() throws Exception {
+        TestTimingProvider timingProvider = new TestTimingProvider();
+        try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
+            UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+                SNAPSHOT_INTERVAL, timingProvider);
+
+            timingProvider.incrementTime(6000);
+            uptimeTracker.onDestroy();
+            timingProvider.cancelAll();
+
+            uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
+                SNAPSHOT_INTERVAL, timingProvider);
+            assertEquals(6000, uptimeTracker.getTotalUptime());
+        }
+    }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
index 2b75012..3f922c9 100644
--- a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
@@ -16,14 +16,12 @@
 
 package com.android.car;
 
-import android.car.annotation.FutureFeature;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.util.Arrays;
 import java.util.Map;
 
-@FutureFeature
 @SmallTest
 public class VmsPublishersInfoTest extends AndroidTestCase {
     public static final byte[] MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
diff --git a/tests/carservice_unit_test/src/com/android/car/storagemonitoring/CarStorageMonitoringTest.java b/tests/carservice_unit_test/src/com/android/car/storagemonitoring/CarStorageMonitoringTest.java
new file mode 100644
index 0000000..250a0a7
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/storagemonitoring/CarStorageMonitoringTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.storagemonitoring;
+
+import android.car.storagemonitoring.WearEstimate;
+import android.car.storagemonitoring.WearEstimateChange;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import com.android.car.test.utils.TemporaryFile;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.time.Instant;
+import junit.framework.TestCase;
+
+/**
+ * Tests the storage monitoring API in CarService.
+ */
+@MediumTest
+public class CarStorageMonitoringTest extends TestCase {
+    static final String TAG = CarStorageMonitoringTest.class.getSimpleName();
+
+    public void testEMmcWearInformationProvider() throws Exception {
+        try (TemporaryFile lifetimeFile = new TemporaryFile(TAG)) {
+            try (TemporaryFile eolFile = new TemporaryFile(TAG)) {
+                lifetimeFile.write("0x05 0x00");
+                eolFile.write("01");
+
+                EMmcWearInformationProvider wearInfoProvider = new EMmcWearInformationProvider(
+                        lifetimeFile.getFile(), eolFile.getFile());
+
+                WearInformation wearInformation = wearInfoProvider.load();
+
+                assertNotNull(wearInformation);
+                assertEquals(40, wearInformation.lifetimeEstimateA);
+                assertEquals(WearInformation.UNKNOWN_LIFETIME_ESTIMATE,
+                        wearInformation.lifetimeEstimateB);
+
+                assertEquals(WearInformation.PRE_EOL_INFO_NORMAL, wearInformation.preEolInfo);
+            }
+        }
+    }
+
+    public void testUfsWearInformationProvider() throws Exception {
+        try (TemporaryFile lifetimeFile = new TemporaryFile(TAG)) {
+            lifetimeFile.write("ufs version: 1.0\n" +
+                    "Health Descriptor[Byte offset 0x2]: bPreEOLInfo = 0x2\n" +
+                    "Health Descriptor[Byte offset 0x1]: bDescriptionIDN = 0x1\n" +
+                    "Health Descriptor[Byte offset 0x3]: bDeviceLifeTimeEstA = 0x0\n" +
+                    "Health Descriptor[Byte offset 0x5]: VendorPropInfo = somedatahere\n" +
+                    "Health Descriptor[Byte offset 0x4]: bDeviceLifeTimeEstB = 0xA\n");
+
+            UfsWearInformationProvider wearInfoProvider = new UfsWearInformationProvider(
+                lifetimeFile.getFile());
+
+            WearInformation wearInformation = wearInfoProvider.load();
+
+            assertNotNull(wearInformation);
+            assertEquals(90, wearInformation.lifetimeEstimateB);
+            assertEquals(WearInformation.PRE_EOL_INFO_WARNING, wearInformation.preEolInfo);
+            assertEquals(WearInformation.UNKNOWN_LIFETIME_ESTIMATE,
+                    wearInformation.lifetimeEstimateA);
+        }
+    }
+
+    public void testWearEstimateEquality() {
+        WearEstimate wearEstimate1 = new WearEstimate(10, 20);
+        WearEstimate wearEstimate2 = new WearEstimate(10, 20);
+        WearEstimate wearEstimate3 = new WearEstimate(20, 30);
+        assertEquals(wearEstimate1, wearEstimate1);
+        assertEquals(wearEstimate1, wearEstimate2);
+        assertNotSame(wearEstimate1, wearEstimate3);
+    }
+
+    public void testWearEstimateParcel() throws Exception {
+        WearEstimate originalWearEstimate = new WearEstimate(10, 20);
+        Parcel p = Parcel.obtain();
+        originalWearEstimate.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        WearEstimate newWearEstimate = new WearEstimate(p);
+        assertEquals(originalWearEstimate, newWearEstimate);
+        p.recycle();
+    }
+
+    public void testWearEstimateChangeEquality() {
+        WearEstimateChange wearEstimateChange1 = new WearEstimateChange(
+                new WearEstimate(10, 20),
+                new WearEstimate(20, 30),
+                5000L,
+                Instant.now(),
+                false);
+        WearEstimateChange wearEstimateChange2 = new WearEstimateChange(
+            new WearEstimate(10, 20),
+            new WearEstimate(20, 30),
+            5000L,
+            wearEstimateChange1.dateAtChange,
+            false);
+        assertEquals(wearEstimateChange1, wearEstimateChange1);
+        assertEquals(wearEstimateChange1, wearEstimateChange2);
+        WearEstimateChange wearEstimateChange3 = new WearEstimateChange(
+            new WearEstimate(10, 30),
+            new WearEstimate(20, 30),
+            3000L,
+            Instant.now(),
+            true);
+        assertNotSame(wearEstimateChange1, wearEstimateChange3);
+    }
+
+    public void testWearEstimateChangeParcel() throws Exception {
+        WearEstimateChange originalWearEstimateChange = new WearEstimateChange(
+                new WearEstimate(10, 0),
+                new WearEstimate(20, 10),
+                123456789L,
+                Instant.now(),
+                false);
+        Parcel p = Parcel.obtain();
+        originalWearEstimateChange.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        WearEstimateChange newWearEstimateChange = new WearEstimateChange(p);
+        assertEquals(originalWearEstimateChange, newWearEstimateChange);
+        p.recycle();
+    }
+
+    public void testWearEstimateJson() throws Exception {
+        WearEstimate originalWearEstimate = new WearEstimate(20, 0);
+        StringWriter stringWriter = new StringWriter(1024);
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        originalWearEstimate.writeToJson(jsonWriter);
+        StringReader stringReader = new StringReader(stringWriter.toString());
+        JsonReader jsonReader = new JsonReader(stringReader);
+        WearEstimate newWearEstimate = new WearEstimate(jsonReader);
+        assertEquals(originalWearEstimate, newWearEstimate);
+    }
+}
diff --git a/tools/emulator/vhal_consts_2_1.py b/tests/common_utils/Android.mk
similarity index 72%
rename from tools/emulator/vhal_consts_2_1.py
rename to tests/common_utils/Android.mk
index e5dbcff..19302c6 100644
--- a/tools/emulator/vhal_consts_2_1.py
+++ b/tests/common_utils/Android.mk
@@ -12,6 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# DO NOT EDIT MANUALLY
-# This file was autogenerated by vhal_const_generate.py
-from vhal_consts_2_0 import *
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := com.android.car.test.utils
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/common_utils/src/com/android/car/test/utils/TemporaryDirectory.java b/tests/common_utils/src/com/android/car/test/utils/TemporaryDirectory.java
new file mode 100644
index 0000000..fa5727d
--- /dev/null
+++ b/tests/common_utils/src/com/android/car/test/utils/TemporaryDirectory.java
@@ -0,0 +1,80 @@
+/*
+ * 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.test.utils;
+
+import android.annotation.Nullable;
+import android.os.SystemClock;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * A utility class that creates a temporary directory.
+ * The directory, and any files contained within, are automatically deleted when calling close().
+ *
+ * Example usage:
+ *
+ * try (TemporaryDirectory tf = new TemporaryDirectory("myTest")) {
+ *     ...
+ * } // directory gets deleted here
+ */
+public class TemporaryDirectory implements AutoCloseable {
+    private Path mDirectory;
+
+    private static final class DeletingVisitor extends SimpleFileVisitor<Path> {
+        FileVisitResult consume(Path path) throws IOException {
+            Files.delete(path);
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
+                throws IOException {
+            return consume(path);
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path path, IOException e)
+                throws IOException {
+            return consume(path);
+        }
+    }
+
+    private static final SimpleFileVisitor<Path> DELETE = new DeletingVisitor();
+
+    public TemporaryDirectory(@Nullable String prefix) throws IOException {
+        if (prefix == null) {
+            prefix = TemporaryDirectory.class.getSimpleName();
+        }
+        prefix += String.valueOf(SystemClock.elapsedRealtimeNanos());
+
+        mDirectory = Files.createTempDirectory(prefix);
+    }
+
+    @Override
+    public void close() throws Exception {
+        Files.walkFileTree(mDirectory, DELETE);
+    }
+
+    public File getDirectory() {
+        return mDirectory.toFile();
+    }
+}
diff --git a/tests/common_utils/src/com/android/car/test/utils/TemporaryFile.java b/tests/common_utils/src/com/android/car/test/utils/TemporaryFile.java
new file mode 100644
index 0000000..a26c1ab
--- /dev/null
+++ b/tests/common_utils/src/com/android/car/test/utils/TemporaryFile.java
@@ -0,0 +1,62 @@
+/*
+ * 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.test.utils;
+
+import android.annotation.Nullable;
+import android.os.SystemClock;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * A utility class that creates a temporary file.
+ * The file is automatically deleted when calling close().
+ *
+ * Example usage:
+ *
+ * try (TemporaryFile tf = new TemporaryFile("myTest")) {
+ *     ...
+ * } // file gets deleted here
+ */
+public final class TemporaryFile implements AutoCloseable {
+    private File mFile;
+
+    public TemporaryFile(@Nullable String prefix) throws IOException {
+        if (prefix == null) {
+            prefix = TemporaryFile.class.getSimpleName();
+        }
+        mFile = File.createTempFile(prefix, String.valueOf(SystemClock.elapsedRealtimeNanos()));
+    }
+
+    @Override
+    public void close() throws Exception {
+        Files.delete(mFile.toPath());
+    }
+
+    public void write(String s) throws IOException {
+        BufferedWriter writer = new BufferedWriter(new FileWriter(mFile));
+        writer.write(s);
+        writer.close();
+    }
+
+    public File getFile() {
+        return mFile;
+    }
+}
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
index 6675713..196a6d4 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2ePerformanceTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 import android.annotation.Nullable;
@@ -47,6 +48,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
@@ -259,6 +261,27 @@
 
         final int EXPECTED_INVOCATIONS = 1000;  // How many time get/set will be called.
         final int EXPECTED_DURATION_MS = 2500;
+        // This is a stress test and it can be flaky because it shares resources with all currently
+        // running process. Let's have this number of attempt before giving up.
+        final int ATTEMPTS = 3;
+
+        for (int curAttempt = 0; curAttempt < ATTEMPTS; curAttempt++) {
+            long missingInvocations = stressTestHvacProperties(mgr, cfg,
+                    EXPECTED_INVOCATIONS, EXPECTED_DURATION_MS);
+            if (missingInvocations == 0) return;  // All done.
+
+            Log.w(TAG, "Failed to invoke get/set " + EXPECTED_INVOCATIONS
+                            + " within " + EXPECTED_DURATION_MS + "ms"
+                            + ", actually invoked: "
+                            + (EXPECTED_INVOCATIONS - missingInvocations));
+        }
+        fail("Failed to invoke get/set " + EXPECTED_INVOCATIONS + " within "
+                + EXPECTED_DURATION_MS + "ms. Number of attempts: " + ATTEMPTS
+                + ". See logs for details.");
+    }
+
+    private long stressTestHvacProperties(CarHvacManager mgr, CarPropertyConfig<Float> cfg,
+            int EXPECTED_INVOCATIONS, int EXPECTED_DURATION_MS) throws InterruptedException {
         CountDownLatch counter = new CountDownLatch(EXPECTED_INVOCATIONS);
 
         List<Thread> threads = new ArrayList<>(Lists.newArrayList(
@@ -271,15 +294,12 @@
 
         counter.await(EXPECTED_DURATION_MS, TimeUnit.MILLISECONDS);
         long missingInvocations = counter.getCount();
-        assertTrue("Failed to invoke get/set " + EXPECTED_INVOCATIONS
-                + " within " + EXPECTED_DURATION_MS + "ms"
-                        + ", actually invoked: " + (EXPECTED_INVOCATIONS - missingInvocations),
-                missingInvocations == 0);
 
         for (Thread t : threads) {
             t.join(10000);  // Let thread join to not interfere with other test.
             assertFalse(t.isAlive());
         }
+        return missingInvocations;
     }
 
     private void invokeSetAndGetForHvacFloat(CarHvacManager mgr,
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 5221907..fb97e73 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
@@ -81,14 +81,12 @@
         return readVhalProperty(vehicle, request, f);
     }
 
-    @Nullable
     static IVehicle getVehicle() throws RemoteException {
         IVehicle service;
         try {
-            service = android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
+            service = IVehicle.getService();
         } catch (NoSuchElementException ex) {
-            Log.d(TAG, "Couldn't connect to vehicle@2.1, connecting to vehicle@2.0...");
-            service =  IVehicle.getService();
+            throw new RuntimeException("Couldn't connect to vehicle@2.0", ex);
         }
         Log.d(TAG, "Connected to IVehicle service: " + service);
         return service;
diff --git a/tools/emulator/vhal_const_generate.py b/tools/emulator/vhal_const_generate.py
index 55bcd1b..df9713b 100755
--- a/tools/emulator/vhal_const_generate.py
+++ b/tools/emulator/vhal_const_generate.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3.4
+#!/usr/bin/env python3
 #
 # Copyright (C) 2017 The Android Open Source Project
 #
@@ -94,23 +94,15 @@
     print("Vehicle HAL was not found at %s. lunch may provide a correct environment, or files moved" % vhal_location)
     sys.exit(1)
 
-vhal_20_file = os.path.join(vhal_location, '2.0', 'types.hal')
-vhal_21_file = os.path.join(vhal_location, '2.1', 'types.hal')
-
-print("Generating content from Vehicle HAL 2.0 (%s) and 2.1 (%s)" % (vhal_20_file, vhal_21_file))
-
-vhal_20_doc = parser.parse(vhal_20_file)
-vhal_21_doc = parser.parse(vhal_21_file)
-
-# Work around the fact that the parser doesn't (yet?) deal with inheritance.
-# WARNING:  This pattern is rather unsafe since we're not merging the lists as we should!
-# vhal_21_doc['enums']['VehiclePropertyGroup'] = vhal_20_doc['enums']['VehiclePropertyGroup']
-# vhal_21_doc['enums']['VehiclePropertyType'] = vhal_20_doc['enums']['VehiclePropertyType']
-# vhal_21_doc['enums']['VehicleArea'] = vhal_20_doc['enums']['VehicleArea']
-
 def generateHal20():
-    print("********************************")
-    print("Generating VHal 2.0 constants...")
+    vhal_20_file = os.path.join(vhal_location, '2.0', 'types.hal')
+    if not(os.path.exists(vhal_20_file)):
+        print("Vehicle HAL was not found at %s. lunch may provide a correct environment, or files moved" % vhal_location)
+        sys.exit(1)
+
+    print("Generating constants from Vehicle HAL 2.0 (%s)" % (vhal_20_file))
+    vhal_20_doc = parser.parse(vhal_20_file)
+
     vhal_20_file = open(os.path.join(script_directory, 'vhal_consts_2_0.py'), 'w')
 
     printHeader(vhal_20_file)
@@ -131,17 +123,4 @@
     print("    TYPE_FLOATS  = [VEHICLEPROPERTYTYPE_FLOAT_VEC]", file=vhal_20_file)
     print("    TYPE_COMPLEX = [VEHICLEPROPERTYTYPE_COMPLEX]", file=vhal_20_file)
 
-def generateHal21():
-    print("********************************")
-    print("Generating VHal 2.1 constants...")
-    vhal_21_file = open(os.path.join(script_directory, 'vhal_consts_2_1.py'), 'w')
-    printHeader(vhal_21_file)
-    print('from vhal_consts_2_0 import *', file=vhal_21_file)
-
-    for group in vhal_21_doc['enums']:
-        print(group)
-        printEnum(vhal_21_doc, group, vhal_21_file, lambda x : hex(x))
-
-
 generateHal20()
-# generateHal21()
diff --git a/tools/emulator/vhal_consts_2_0.py b/tools/emulator/vhal_consts_2_0.py
index 59c430c..4eb3a1e 100644
--- a/tools/emulator/vhal_consts_2_0.py
+++ b/tools/emulator/vhal_consts_2_0.py
@@ -15,223 +15,9 @@
 # DO NOT EDIT MANUALLY
 # This file was autogenerated by vhal_const_generate.py
 
-# VehicleAudioContextFlag
-VEHICLEAUDIOCONTEXTFLAG_MUSIC_FLAG = 0x1
-VEHICLEAUDIOCONTEXTFLAG_NAVIGATION_FLAG = 0x2
-VEHICLEAUDIOCONTEXTFLAG_VOICE_COMMAND_FLAG = 0x4
-VEHICLEAUDIOCONTEXTFLAG_CALL_FLAG = 0x8
-VEHICLEAUDIOCONTEXTFLAG_ALARM_FLAG = 0x10
-VEHICLEAUDIOCONTEXTFLAG_NOTIFICATION_FLAG = 0x20
-VEHICLEAUDIOCONTEXTFLAG_UNKNOWN_FLAG = 0x40
-VEHICLEAUDIOCONTEXTFLAG_SAFETY_ALERT_FLAG = 0x80
-VEHICLEAUDIOCONTEXTFLAG_CD_ROM_FLAG = 0x100
-VEHICLEAUDIOCONTEXTFLAG_AUX_AUDIO_FLAG = 0x200
-VEHICLEAUDIOCONTEXTFLAG_SYSTEM_SOUND_FLAG = 0x400
-VEHICLEAUDIOCONTEXTFLAG_RADIO_FLAG = 0x800
-VEHICLEAUDIOCONTEXTFLAG_EXT_SOURCE_FLAG = 0x1000
-
-# VehicleAudioFocusIndex
-VEHICLEAUDIOFOCUSINDEX_FOCUS = 0x0
-VEHICLEAUDIOFOCUSINDEX_STREAMS = 0x1
-VEHICLEAUDIOFOCUSINDEX_EXTERNAL_FOCUS_STATE = 0x2
-VEHICLEAUDIOFOCUSINDEX_AUDIO_CONTEXTS = 0x3
-
-# Obd2CommonIgnitionMonitors
-OBD2COMMONIGNITIONMONITORS_COMPONENTS_AVAILABLE = 0x1
-OBD2COMMONIGNITIONMONITORS_COMPONENTS_INCOMPLETE = 0x2
-OBD2COMMONIGNITIONMONITORS_FUEL_SYSTEM_AVAILABLE = 0x4
-OBD2COMMONIGNITIONMONITORS_FUEL_SYSTEM_INCOMPLETE = 0x8
-OBD2COMMONIGNITIONMONITORS_MISFIRE_AVAILABLE = 0x10
-OBD2COMMONIGNITIONMONITORS_MISFIRE_INCOMPLETE = 0x20
-
-# Obd2FuelType
-OBD2FUELTYPE_NOT_AVAILABLE = 0x0
-OBD2FUELTYPE_GASOLINE = 0x1
-OBD2FUELTYPE_METHANOL = 0x2
-OBD2FUELTYPE_ETHANOL = 0x3
-OBD2FUELTYPE_DIESEL = 0x4
-OBD2FUELTYPE_LPG = 0x5
-OBD2FUELTYPE_CNG = 0x6
-OBD2FUELTYPE_PROPANE = 0x7
-OBD2FUELTYPE_ELECTRIC = 0x8
-OBD2FUELTYPE_BIFUEL_RUNNING_GASOLINE = 0x9
-OBD2FUELTYPE_BIFUEL_RUNNING_METHANOL = 0xa
-OBD2FUELTYPE_BIFUEL_RUNNING_ETHANOL = 0xb
-OBD2FUELTYPE_BIFUEL_RUNNING_LPG = 0xc
-OBD2FUELTYPE_BIFUEL_RUNNING_CNG = 0xd
-OBD2FUELTYPE_BIFUEL_RUNNING_PROPANE = 0xe
-OBD2FUELTYPE_BIFUEL_RUNNING_ELECTRIC = 0xf
-OBD2FUELTYPE_BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 0x10
-OBD2FUELTYPE_HYBRID_GASOLINE = 0x11
-OBD2FUELTYPE_HYBRID_ETHANOL = 0x12
-OBD2FUELTYPE_HYBRID_DIESEL = 0x13
-OBD2FUELTYPE_HYBRID_ELECTRIC = 0x14
-OBD2FUELTYPE_HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 0x15
-OBD2FUELTYPE_HYBRID_REGENERATIVE = 0x16
-OBD2FUELTYPE_BIFUEL_RUNNING_DIESEL = 0x17
-
 # VehicleAudioVolumeState
 VEHICLEAUDIOVOLUMESTATE_STATE_OK = 0x0
-VEHICLEAUDIOVOLUMESTATE_LIMIT_REACHED = 0x1
-
-# VmsMessageWithLayerIntegerValuesIndex
-VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_TYPE = 0x1
-VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_SUBTYPE = 0x2
-VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_VERSION = 0x3
-
-# Obd2SparkIgnitionMonitors
-OBD2SPARKIGNITIONMONITORS_EGR_AVAILABLE = 0x40
-OBD2SPARKIGNITIONMONITORS_EGR_INCOMPLETE = 0x80
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_AVAILABLE = 0x100
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x200
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_AVAILABLE = 0x400
-OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_INCOMPLETE = 0x800
-OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_AVAILABLE = 0x1000
-OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_INCOMPLETE = 0x2000
-OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_AVAILABLE = 0x4000
-OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x8000
-OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_AVAILABLE = 0x10000
-OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_INCOMPLETE = 0x20000
-OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_AVAILABLE = 0x40000
-OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_INCOMPLETE = 0x80000
-OBD2SPARKIGNITIONMONITORS_CATALYST_AVAILABLE = 0x100000
-OBD2SPARKIGNITIONMONITORS_CATALYST_INCOMPLETE = 0x200000
-
-# VehicleArea
-VEHICLEAREA_GLOBAL = 0x1000000
-VEHICLEAREA_ZONE = 0x2000000
-VEHICLEAREA_WINDOW = 0x3000000
-VEHICLEAREA_MIRROR = 0x4000000
-VEHICLEAREA_SEAT = 0x5000000
-VEHICLEAREA_DOOR = 0x6000000
-VEHICLEAREA_MASK = 0xf000000
-
-# Obd2SecondaryAirStatus
-OBD2SECONDARYAIRSTATUS_UPSTREAM = 0x1
-OBD2SECONDARYAIRSTATUS_DOWNSTREAM_OF_CATALYCIC_CONVERTER = 0x2
-OBD2SECONDARYAIRSTATUS_FROM_OUTSIDE_OR_OFF = 0x4
-OBD2SECONDARYAIRSTATUS_PUMP_ON_FOR_DIAGNOSTICS = 0x8
-
-# VehicleAudioHwVariantConfigFlag
-VEHICLEAUDIOHWVARIANTCONFIGFLAG_INTERNAL_RADIO_FLAG = 0x1
-
-# VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
-VMSMESSAGEWITHLAYERANDPUBLISHERIDINTEGERVALUESINDEX_PUBLISHER_ID = 0x4
-
-# Obd2CompressionIgnitionMonitors
-OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_AVAILABLE = 0x40
-OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_INCOMPLETE = 0x80
-OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_AVAILABLE = 0x100
-OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_INCOMPLETE = 0x200
-OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_AVAILABLE = 0x400
-OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_INCOMPLETE = 0x800
-OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_AVAILABLE = 0x1000
-OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_INCOMPLETE = 0x2000
-OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_AVAILABLE = 0x4000
-OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_INCOMPLETE = 0x8000
-OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_AVAILABLE = 0x10000
-OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_INCOMPLETE = 0x20000
-
-# VmsOfferingMessageIntegerValuesIndex
-VMSOFFERINGMESSAGEINTEGERVALUESINDEX_PUBLISHER_ID = 0x1
-VMSOFFERINGMESSAGEINTEGERVALUESINDEX_NUMBER_OF_OFFERS = 0x2
-VMSOFFERINGMESSAGEINTEGERVALUESINDEX_OFFERING_START = 0x3
-
-# VehicleAreaZone
-VEHICLEAREAZONE_ROW_1_LEFT = 0x1
-VEHICLEAREAZONE_ROW_1_CENTER = 0x2
-VEHICLEAREAZONE_ROW_1_RIGHT = 0x4
-VEHICLEAREAZONE_ROW_1 = 0x8
-VEHICLEAREAZONE_ROW_2_LEFT = 0x10
-VEHICLEAREAZONE_ROW_2_CENTER = 0x20
-VEHICLEAREAZONE_ROW_2_RIGHT = 0x40
-VEHICLEAREAZONE_ROW_2 = 0x80
-VEHICLEAREAZONE_ROW_3_LEFT = 0x100
-VEHICLEAREAZONE_ROW_3_CENTER = 0x200
-VEHICLEAREAZONE_ROW_3_RIGHT = 0x400
-VEHICLEAREAZONE_ROW_3 = 0x800
-VEHICLEAREAZONE_ROW_4_LEFT = 0x1000
-VEHICLEAREAZONE_ROW_4_CENTER = 0x2000
-VEHICLEAREAZONE_ROW_4_RIGHT = 0x4000
-VEHICLEAREAZONE_ROW_4 = 0x8000
-VEHICLEAREAZONE_WHOLE_CABIN = 0x80000000
-
-# Obd2IgnitionMonitorKind
-OBD2IGNITIONMONITORKIND_SPARK = 0x0
-OBD2IGNITIONMONITORKIND_COMPRESSION = 0x1
-
-# VmsAvailabilityStateIntegerValuesIndex
-VMSAVAILABILITYSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
-VMSAVAILABILITYSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x2
-VMSAVAILABILITYSTATEINTEGERVALUESINDEX_LAYERS_START = 0x3
-
-# VehicleApPowerStateConfigFlag
-VEHICLEAPPOWERSTATECONFIGFLAG_ENABLE_DEEP_SLEEP_FLAG = 0x1
-VEHICLEAPPOWERSTATECONFIGFLAG_CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2
-
-# VehicleHvacFanDirection
-VEHICLEHVACFANDIRECTION_FACE = 0x1
-VEHICLEHVACFANDIRECTION_FLOOR = 0x2
-VEHICLEHVACFANDIRECTION_FACE_AND_FLOOR = 0x3
-VEHICLEHVACFANDIRECTION_DEFROST = 0x4
-VEHICLEHVACFANDIRECTION_DEFROST_AND_FLOOR = 0x5
-
-# VehicleHwKeyInputAction
-VEHICLEHWKEYINPUTACTION_ACTION_DOWN = 0x0
-VEHICLEHWKEYINPUTACTION_ACTION_UP = 0x1
-
-# Wheel
-WHEEL_UNKNOWN = 0x0
-WHEEL_LEFT_FRONT = 0x1
-WHEEL_RIGHT_FRONT = 0x2
-WHEEL_LEFT_REAR = 0x4
-WHEEL_RIGHT_REAR = 0x8
-
-# VehicleAudioVolumeCapabilityFlag
-VEHICLEAUDIOVOLUMECAPABILITYFLAG_PERSISTENT_STORAGE = 0x1
-VEHICLEAUDIOVOLUMECAPABILITYFLAG_MASTER_VOLUME_ONLY = 0x2
-
-# VehicleAudioVolumeIndex
-VEHICLEAUDIOVOLUMEINDEX_INDEX_STREAM = 0x0
-VEHICLEAUDIOVOLUMEINDEX_INDEX_VOLUME = 0x1
-VEHICLEAUDIOVOLUMEINDEX_INDEX_STATE = 0x2
-
-# VehicleRadioConstants
-VEHICLERADIOCONSTANTS_VEHICLE_RADIO_PRESET_MIN_VALUE = 0x1
-
-# VehicleGear
-VEHICLEGEAR_GEAR_NEUTRAL = 0x1
-VEHICLEGEAR_GEAR_REVERSE = 0x2
-VEHICLEGEAR_GEAR_PARK = 0x4
-VEHICLEGEAR_GEAR_DRIVE = 0x8
-VEHICLEGEAR_GEAR_LOW = 0x10
-VEHICLEGEAR_GEAR_1 = 0x10
-VEHICLEGEAR_GEAR_2 = 0x20
-VEHICLEGEAR_GEAR_3 = 0x40
-VEHICLEGEAR_GEAR_4 = 0x80
-VEHICLEGEAR_GEAR_5 = 0x100
-VEHICLEGEAR_GEAR_6 = 0x200
-VEHICLEGEAR_GEAR_7 = 0x400
-VEHICLEGEAR_GEAR_8 = 0x800
-VEHICLEGEAR_GEAR_9 = 0x1000
-
-# VehicleDrivingStatus
-VEHICLEDRIVINGSTATUS_UNRESTRICTED = 0x0
-VEHICLEDRIVINGSTATUS_NO_VIDEO = 0x1
-VEHICLEDRIVINGSTATUS_NO_KEYBOARD_INPUT = 0x2
-VEHICLEDRIVINGSTATUS_NO_VOICE_INPUT = 0x4
-VEHICLEDRIVINGSTATUS_NO_CONFIG = 0x8
-VEHICLEDRIVINGSTATUS_LIMIT_MESSAGE_LEN = 0x10
-
-# VehicleAudioRoutingPolicyIndex
-VEHICLEAUDIOROUTINGPOLICYINDEX_STREAM = 0x0
-VEHICLEAUDIOROUTINGPOLICYINDEX_CONTEXTS = 0x1
-
-# VmsSubscriptionsStateIntegerValuesIndex
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_LAYERS = 0x2
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x3
-VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SUBSCRIPTIONS_START = 0x4
+VEHICLEAUDIOVOLUMESTATE_STATE_LIMIT_REACHED = 0x1
 
 # SubscribeFlags
 SUBSCRIBEFLAGS_UNDEFINED = 0x0
@@ -239,60 +25,40 @@
 SUBSCRIBEFLAGS_SET_CALL = 0x2
 SUBSCRIBEFLAGS_DEFAULT = 0x1
 
-# VehicleAudioExtFocusFlag
-VEHICLEAUDIOEXTFOCUSFLAG_NONE_FLAG = 0x0
-VEHICLEAUDIOEXTFOCUSFLAG_PERMANENT_FLAG = 0x1
-VEHICLEAUDIOEXTFOCUSFLAG_TRANSIENT_FLAG = 0x2
-VEHICLEAUDIOEXTFOCUSFLAG_PLAY_ONLY_FLAG = 0x4
-VEHICLEAUDIOEXTFOCUSFLAG_MUTE_MEDIA_FLAG = 0x8
-
-# VehicleAudioFocusRequest
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN = 0x1
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT = 0x2
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4
-VEHICLEAUDIOFOCUSREQUEST_REQUEST_RELEASE = 0x5
-
-# VehiclePropertyType
-VEHICLEPROPERTYTYPE_STRING = 0x100000
-VEHICLEPROPERTYTYPE_BOOLEAN = 0x200000
-VEHICLEPROPERTYTYPE_INT32 = 0x400000
-VEHICLEPROPERTYTYPE_INT32_VEC = 0x410000
-VEHICLEPROPERTYTYPE_INT64 = 0x500000
-VEHICLEPROPERTYTYPE_FLOAT = 0x600000
-VEHICLEPROPERTYTYPE_FLOAT_VEC = 0x610000
-VEHICLEPROPERTYTYPE_BYTES = 0x700000
-VEHICLEPROPERTYTYPE_COMPLEX = 0xe00000
-VEHICLEPROPERTYTYPE_MASK = 0xff0000
-
-# VehiclePropertyAccess
-VEHICLEPROPERTYACCESS_NONE = 0x0
-VEHICLEPROPERTYACCESS_READ = 0x1
-VEHICLEPROPERTYACCESS_WRITE = 0x2
-VEHICLEPROPERTYACCESS_READ_WRITE = 0x3
-
-# Obd2FuelSystemStatus
-OBD2FUELSYSTEMSTATUS_OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 0x1
-OBD2FUELSYSTEMSTATUS_CLOSED_LOOP = 0x2
-OBD2FUELSYSTEMSTATUS_OPEN_ENGINE_LOAD_OR_DECELERATION = 0x4
-OBD2FUELSYSTEMSTATUS_OPEN_SYSTEM_FAILURE = 0x8
-OBD2FUELSYSTEMSTATUS_CLOSED_LOOP_BUT_FEEDBACK_FAULT = 0x10
-
-# VehicleTurnSignal
-VEHICLETURNSIGNAL_NONE = 0x0
-VEHICLETURNSIGNAL_RIGHT = 0x1
-VEHICLETURNSIGNAL_LEFT = 0x2
-VEHICLETURNSIGNAL_EMERGENCY = 0x4
-
-# VehicleAudioStreamFlag
-VEHICLEAUDIOSTREAMFLAG_STREAM0_FLAG = 0x1
-VEHICLEAUDIOSTREAMFLAG_STREAM1_FLAG = 0x2
-VEHICLEAUDIOSTREAMFLAG_STREAM2_FLAG = 0x4
-
-# VehicleApPowerBootupReason
-VEHICLEAPPOWERBOOTUPREASON_USER_POWER_ON = 0x0
-VEHICLEAPPOWERBOOTUPREASON_USER_UNLOCK = 0x1
-VEHICLEAPPOWERBOOTUPREASON_TIMER = 0x2
+# DiagnosticIntegerSensorIndex
+DIAGNOSTICINTEGERSENSORINDEX_FUEL_SYSTEM_STATUS = 0x0
+DIAGNOSTICINTEGERSENSORINDEX_MALFUNCTION_INDICATOR_LIGHT_ON = 0x1
+DIAGNOSTICINTEGERSENSORINDEX_IGNITION_MONITORS_SUPPORTED = 0x2
+DIAGNOSTICINTEGERSENSORINDEX_IGNITION_SPECIFIC_MONITORS = 0x3
+DIAGNOSTICINTEGERSENSORINDEX_INTAKE_AIR_TEMPERATURE = 0x4
+DIAGNOSTICINTEGERSENSORINDEX_COMMANDED_SECONDARY_AIR_STATUS = 0x5
+DIAGNOSTICINTEGERSENSORINDEX_NUM_OXYGEN_SENSORS_PRESENT = 0x6
+DIAGNOSTICINTEGERSENSORINDEX_RUNTIME_SINCE_ENGINE_START = 0x7
+DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 0x8
+DIAGNOSTICINTEGERSENSORINDEX_WARMUPS_SINCE_CODES_CLEARED = 0x9
+DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 0xa
+DIAGNOSTICINTEGERSENSORINDEX_ABSOLUTE_BAROMETRIC_PRESSURE = 0xb
+DIAGNOSTICINTEGERSENSORINDEX_CONTROL_MODULE_VOLTAGE = 0xc
+DIAGNOSTICINTEGERSENSORINDEX_AMBIENT_AIR_TEMPERATURE = 0xd
+DIAGNOSTICINTEGERSENSORINDEX_TIME_WITH_MALFUNCTION_LIGHT_ON = 0xe
+DIAGNOSTICINTEGERSENSORINDEX_TIME_SINCE_TROUBLE_CODES_CLEARED = 0xf
+DIAGNOSTICINTEGERSENSORINDEX_MAX_FUEL_AIR_EQUIVALENCE_RATIO = 0x10
+DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_VOLTAGE = 0x11
+DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_CURRENT = 0x12
+DIAGNOSTICINTEGERSENSORINDEX_MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 0x13
+DIAGNOSTICINTEGERSENSORINDEX_MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 0x14
+DIAGNOSTICINTEGERSENSORINDEX_FUEL_TYPE = 0x15
+DIAGNOSTICINTEGERSENSORINDEX_FUEL_RAIL_ABSOLUTE_PRESSURE = 0x16
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_OIL_TEMPERATURE = 0x17
+DIAGNOSTICINTEGERSENSORINDEX_DRIVER_DEMAND_PERCENT_TORQUE = 0x18
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_ACTUAL_PERCENT_TORQUE = 0x19
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_REFERENCE_PERCENT_TORQUE = 0x1a
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_IDLE = 0x1b
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT1 = 0x1c
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT2 = 0x1d
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT3 = 0x1e
+DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT4 = 0x1f
+DIAGNOSTICINTEGERSENSORINDEX_LAST_SYSTEM_INDEX = 0x1f
 
 # VehicleAudioFocusState
 VEHICLEAUDIOFOCUSSTATE_STATE_GAIN = 0x1
@@ -302,9 +68,26 @@
 VEHICLEAUDIOFOCUSSTATE_STATE_LOSS = 0x5
 VEHICLEAUDIOFOCUSSTATE_STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6
 
-# VehicleAudioStream
-VEHICLEAUDIOSTREAM_STREAM0 = 0x0
-VEHICLEAUDIOSTREAM_STREAM1 = 0x1
+# Obd2CommonIgnitionMonitors
+OBD2COMMONIGNITIONMONITORS_COMPONENTS_AVAILABLE = 0x1
+OBD2COMMONIGNITIONMONITORS_COMPONENTS_INCOMPLETE = 0x2
+OBD2COMMONIGNITIONMONITORS_FUEL_SYSTEM_AVAILABLE = 0x4
+OBD2COMMONIGNITIONMONITORS_FUEL_SYSTEM_INCOMPLETE = 0x8
+OBD2COMMONIGNITIONMONITORS_MISFIRE_AVAILABLE = 0x10
+OBD2COMMONIGNITIONMONITORS_MISFIRE_INCOMPLETE = 0x20
+
+# VehicleHvacFanDirection
+VEHICLEHVACFANDIRECTION_FACE = 0x1
+VEHICLEHVACFANDIRECTION_FLOOR = 0x2
+VEHICLEHVACFANDIRECTION_FACE_AND_FLOOR = 0x3
+VEHICLEHVACFANDIRECTION_DEFROST = 0x4
+VEHICLEHVACFANDIRECTION_DEFROST_AND_FLOOR = 0x5
+
+# VehiclePropertyOperation
+VEHICLEPROPERTYOPERATION_GENERIC = 0x0
+VEHICLEPROPERTYOPERATION_SET = 0x1
+VEHICLEPROPERTYOPERATION_GET = 0x2
+VEHICLEPROPERTYOPERATION_SUBSCRIBE = 0x3
 
 # DiagnosticFloatSensorIndex
 DIAGNOSTICFLOATSENSORINDEX_CALCULATED_ENGINE_LOAD = 0x0
@@ -380,10 +163,9 @@
 DIAGNOSTICFLOATSENSORINDEX_ENGINE_FUEL_RATE = 0x46
 DIAGNOSTICFLOATSENSORINDEX_LAST_SYSTEM_INDEX = 0x46
 
-# VehicleAreaMirror
-VEHICLEAREAMIRROR_DRIVER_LEFT = 0x1
-VEHICLEAREAMIRROR_DRIVER_RIGHT = 0x2
-VEHICLEAREAMIRROR_DRIVER_CENTER = 0x4
+# VehicleAudioVolumeLimitIndex
+VEHICLEAUDIOVOLUMELIMITINDEX_STREAM = 0x0
+VEHICLEAUDIOVOLUMELIMITINDEX_MAX_VOLUME = 0x1
 
 # VehicleAreaWindow
 VEHICLEAREAWINDOW_FRONT_WINDSHIELD = 0x1
@@ -396,40 +178,97 @@
 VEHICLEAREAWINDOW_ROW_3_LEFT = 0x1000
 VEHICLEAREAWINDOW_ROW_3_RIGHT = 0x2000
 
-# VehiclePropertyOperation
-VEHICLEPROPERTYOPERATION_GENERIC = 0x0
-VEHICLEPROPERTYOPERATION_SET = 0x1
-VEHICLEPROPERTYOPERATION_GET = 0x2
-VEHICLEPROPERTYOPERATION_SUBSCRIBE = 0x3
+# VehicleGear
+VEHICLEGEAR_GEAR_NEUTRAL = 0x1
+VEHICLEGEAR_GEAR_REVERSE = 0x2
+VEHICLEGEAR_GEAR_PARK = 0x4
+VEHICLEGEAR_GEAR_DRIVE = 0x8
+VEHICLEGEAR_GEAR_LOW = 0x10
+VEHICLEGEAR_GEAR_1 = 0x10
+VEHICLEGEAR_GEAR_2 = 0x20
+VEHICLEGEAR_GEAR_3 = 0x40
+VEHICLEGEAR_GEAR_4 = 0x80
+VEHICLEGEAR_GEAR_5 = 0x100
+VEHICLEGEAR_GEAR_6 = 0x200
+VEHICLEGEAR_GEAR_7 = 0x400
+VEHICLEGEAR_GEAR_8 = 0x800
+VEHICLEGEAR_GEAR_9 = 0x1000
 
-# VehicleAreaDoor
-VEHICLEAREADOOR_ROW_1_LEFT = 0x1
-VEHICLEAREADOOR_ROW_1_RIGHT = 0x4
-VEHICLEAREADOOR_ROW_2_LEFT = 0x10
-VEHICLEAREADOOR_ROW_2_RIGHT = 0x40
-VEHICLEAREADOOR_ROW_3_LEFT = 0x100
-VEHICLEAREADOOR_ROW_3_RIGHT = 0x400
-VEHICLEAREADOOR_HOOD = 0x10000000
-VEHICLEAREADOOR_REAR = 0x20000000
+# VehicleAreaMirror
+VEHICLEAREAMIRROR_DRIVER_LEFT = 0x1
+VEHICLEAREAMIRROR_DRIVER_RIGHT = 0x2
+VEHICLEAREAMIRROR_DRIVER_CENTER = 0x4
 
-# StatusCode
-STATUSCODE_OK = 0x0
-STATUSCODE_TRY_AGAIN = 0x1
-STATUSCODE_INVALID_ARG = 0x2
-STATUSCODE_NOT_AVAILABLE = 0x3
-STATUSCODE_ACCESS_DENIED = 0x4
-STATUSCODE_INTERNAL_ERROR = 0x5
+# VehicleAudioContextFlag
+VEHICLEAUDIOCONTEXTFLAG_MUSIC_FLAG = 0x1
+VEHICLEAUDIOCONTEXTFLAG_NAVIGATION_FLAG = 0x2
+VEHICLEAUDIOCONTEXTFLAG_VOICE_COMMAND_FLAG = 0x4
+VEHICLEAUDIOCONTEXTFLAG_CALL_FLAG = 0x8
+VEHICLEAUDIOCONTEXTFLAG_ALARM_FLAG = 0x10
+VEHICLEAUDIOCONTEXTFLAG_NOTIFICATION_FLAG = 0x20
+VEHICLEAUDIOCONTEXTFLAG_UNKNOWN_FLAG = 0x40
+VEHICLEAUDIOCONTEXTFLAG_SAFETY_ALERT_FLAG = 0x80
+VEHICLEAUDIOCONTEXTFLAG_CD_ROM_FLAG = 0x100
+VEHICLEAUDIOCONTEXTFLAG_AUX_AUDIO_FLAG = 0x200
+VEHICLEAUDIOCONTEXTFLAG_SYSTEM_SOUND_FLAG = 0x400
+VEHICLEAUDIOCONTEXTFLAG_RADIO_FLAG = 0x800
+VEHICLEAUDIOCONTEXTFLAG_EXT_SOURCE_FLAG = 0x1000
+VEHICLEAUDIOCONTEXTFLAG_RINGTONE_FLAG = 0x2000
 
-# VehicleAreaSeat
-VEHICLEAREASEAT_ROW_1_LEFT = 0x1
-VEHICLEAREASEAT_ROW_1_CENTER = 0x2
-VEHICLEAREASEAT_ROW_1_RIGHT = 0x4
-VEHICLEAREASEAT_ROW_2_LEFT = 0x10
-VEHICLEAREASEAT_ROW_2_CENTER = 0x20
-VEHICLEAREASEAT_ROW_2_RIGHT = 0x40
-VEHICLEAREASEAT_ROW_3_LEFT = 0x100
-VEHICLEAREASEAT_ROW_3_CENTER = 0x200
-VEHICLEAREASEAT_ROW_3_RIGHT = 0x400
+# VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
+VMSMESSAGEWITHLAYERANDPUBLISHERIDINTEGERVALUESINDEX_PUBLISHER_ID = 0x4
+
+# VehiclePropertyAccess
+VEHICLEPROPERTYACCESS_NONE = 0x0
+VEHICLEPROPERTYACCESS_READ = 0x1
+VEHICLEPROPERTYACCESS_WRITE = 0x2
+VEHICLEPROPERTYACCESS_READ_WRITE = 0x3
+
+# VehicleApPowerStateIndex
+VEHICLEAPPOWERSTATEINDEX_STATE = 0x0
+VEHICLEAPPOWERSTATEINDEX_ADDITIONAL = 0x1
+
+# VmsBaseMessageIntegerValuesIndex
+VMSBASEMESSAGEINTEGERVALUESINDEX_MESSAGE_TYPE = 0x0
+
+# VehicleAudioStream
+VEHICLEAUDIOSTREAM_STREAM0 = 0x0
+VEHICLEAUDIOSTREAM_STREAM1 = 0x1
+
+# VehiclePropertyChangeMode
+VEHICLEPROPERTYCHANGEMODE_STATIC = 0x0
+VEHICLEPROPERTYCHANGEMODE_ON_CHANGE = 0x1
+VEHICLEPROPERTYCHANGEMODE_CONTINUOUS = 0x2
+VEHICLEPROPERTYCHANGEMODE_POLL = 0x3
+VEHICLEPROPERTYCHANGEMODE_ON_SET = 0x4
+
+# Obd2CompressionIgnitionMonitors
+OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_AVAILABLE = 0x40
+OBD2COMPRESSIONIGNITIONMONITORS_EGR_OR_VVT_INCOMPLETE = 0x80
+OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_AVAILABLE = 0x100
+OBD2COMPRESSIONIGNITIONMONITORS_PM_FILTER_INCOMPLETE = 0x200
+OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_AVAILABLE = 0x400
+OBD2COMPRESSIONIGNITIONMONITORS_EXHAUST_GAS_SENSOR_INCOMPLETE = 0x800
+OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_AVAILABLE = 0x1000
+OBD2COMPRESSIONIGNITIONMONITORS_BOOST_PRESSURE_INCOMPLETE = 0x2000
+OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_AVAILABLE = 0x4000
+OBD2COMPRESSIONIGNITIONMONITORS_NOx_SCR_INCOMPLETE = 0x8000
+OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_AVAILABLE = 0x10000
+OBD2COMPRESSIONIGNITIONMONITORS_NMHC_CATALYST_INCOMPLETE = 0x20000
+
+# VehiclePropertyGroup
+VEHICLEPROPERTYGROUP_SYSTEM = 0x10000000
+VEHICLEPROPERTYGROUP_VENDOR = 0x20000000
+VEHICLEPROPERTYGROUP_MASK = 0xf0000000
+
+# VehicleApPowerSetState
+VEHICLEAPPOWERSETSTATE_BOOT_COMPLETE = 0x1
+VEHICLEAPPOWERSETSTATE_DEEP_SLEEP_ENTRY = 0x2
+VEHICLEAPPOWERSETSTATE_DEEP_SLEEP_EXIT = 0x3
+VEHICLEAPPOWERSETSTATE_SHUTDOWN_POSTPONE = 0x4
+VEHICLEAPPOWERSETSTATE_SHUTDOWN_START = 0x5
+VEHICLEAPPOWERSETSTATE_DISPLAY_OFF = 0x6
+VEHICLEAPPOWERSETSTATE_DISPLAY_ON = 0x7
 
 # VmsMessageType
 VMSMESSAGETYPE_SUBSCRIBE = 0x1
@@ -445,6 +284,32 @@
 VMSMESSAGETYPE_SUBSCRIPTIONS_CHANGE = 0xb
 VMSMESSAGETYPE_DATA = 0xc
 
+# VehicleAreaZone
+VEHICLEAREAZONE_ROW_1_LEFT = 0x1
+VEHICLEAREAZONE_ROW_1_CENTER = 0x2
+VEHICLEAREAZONE_ROW_1_RIGHT = 0x4
+VEHICLEAREAZONE_ROW_1 = 0x8
+VEHICLEAREAZONE_ROW_2_LEFT = 0x10
+VEHICLEAREAZONE_ROW_2_CENTER = 0x20
+VEHICLEAREAZONE_ROW_2_RIGHT = 0x40
+VEHICLEAREAZONE_ROW_2 = 0x80
+VEHICLEAREAZONE_ROW_3_LEFT = 0x100
+VEHICLEAREAZONE_ROW_3_CENTER = 0x200
+VEHICLEAREAZONE_ROW_3_RIGHT = 0x400
+VEHICLEAREAZONE_ROW_3 = 0x800
+VEHICLEAREAZONE_ROW_4_LEFT = 0x1000
+VEHICLEAREAZONE_ROW_4_CENTER = 0x2000
+VEHICLEAREAZONE_ROW_4_RIGHT = 0x4000
+VEHICLEAREAZONE_ROW_4 = 0x8000
+VEHICLEAREAZONE_WHOLE_CABIN = 0x80000000
+
+# Wheel
+WHEEL_UNKNOWN = 0x0
+WHEEL_LEFT_FRONT = 0x1
+WHEEL_RIGHT_FRONT = 0x2
+WHEEL_LEFT_REAR = 0x4
+WHEEL_RIGHT_REAR = 0x8
+
 # VehicleProperty
 VEHICLEPROPERTY_INVALID = 0x0
 VEHICLEPROPERTY_INFO_VIN = 0x11100100
@@ -457,6 +322,7 @@
 VEHICLEPROPERTY_ENGINE_COOLANT_TEMP = 0x11600301
 VEHICLEPROPERTY_ENGINE_OIL_TEMP = 0x11600304
 VEHICLEPROPERTY_ENGINE_RPM = 0x11600305
+VEHICLEPROPERTY_WHEEL_TICK = 0x11e00306
 VEHICLEPROPERTY_GEAR_SELECTION = 0x11400400
 VEHICLEPROPERTY_CURRENT_GEAR = 0x11400401
 VEHICLEPROPERTY_PARKING_BRAKE_ON = 0x11200402
@@ -465,6 +331,8 @@
 VEHICLEPROPERTY_NIGHT_MODE = 0x11200407
 VEHICLEPROPERTY_TURN_SIGNAL_STATE = 0x11400408
 VEHICLEPROPERTY_IGNITION_STATE = 0x11400409
+VEHICLEPROPERTY_ABS_ACTIVE = 0x1120040a
+VEHICLEPROPERTY_TRACTION_CONTROL_ACTIVE = 0x1120040b
 VEHICLEPROPERTY_HVAC_FAN_SPEED = 0x12400500
 VEHICLEPROPERTY_HVAC_FAN_DIRECTION = 0x12400501
 VEHICLEPROPERTY_HVAC_TEMPERATURE_CURRENT = 0x12600502
@@ -481,8 +349,9 @@
 VEHICLEPROPERTY_HVAC_STEERING_WHEEL_TEMP = 0x1140050d
 VEHICLEPROPERTY_HVAC_TEMPERATURE_UNITS = 0x1240050e
 VEHICLEPROPERTY_HVAC_ACTUAL_FAN_SPEED_RPM = 0x1240050f
-VEHICLEPROPERTY_HVAC_FAN_DIRECTION_AVAILABLE = 0x12400511
 VEHICLEPROPERTY_HVAC_POWER_ON = 0x12200510
+VEHICLEPROPERTY_HVAC_FAN_DIRECTION_AVAILABLE = 0x12400511
+VEHICLEPROPERTY_HVAC_AUTO_RECIRC_ON = 0x12200512
 VEHICLEPROPERTY_ENV_OUTSIDE_TEMPERATURE = 0x11600703
 VEHICLEPROPERTY_ENV_CABIN_TEMPERATURE = 0x11600704
 VEHICLEPROPERTY_RADIO_PRESET = 0x11410801
@@ -544,10 +413,6 @@
 VEHICLEPROPERTY_WINDOW_VENT_POS = 0x11400bc2
 VEHICLEPROPERTY_WINDOW_VENT_MOVE = 0x11400bc3
 VEHICLEPROPERTY_WINDOW_LOCK = 0x11200bc4
-VEHICLEPROPERTY_WHEEL_TICK = 0x11e00306
-VEHICLEPROPERTY_ABS_ACTIVE = 0x1120040a
-VEHICLEPROPERTY_TRACTION_CONTROL_ACTIVE = 0x1120040b
-VEHICLEPROPERTY_HVAC_AUTO_RECIRC_ON = 0x12200512
 VEHICLEPROPERTY_VEHICLE_MAP_SERVICE = 0x11e00c00
 VEHICLEPROPERTY_OBD2_LIVE_FRAME = 0x11e00d00
 VEHICLEPROPERTY_OBD2_FREEZE_FRAME = 0x11e00d01
@@ -562,76 +427,25 @@
 VEHICLEIGNITIONSTATE_ON = 0x4
 VEHICLEIGNITIONSTATE_START = 0x5
 
-# VehiclePropertyGroup
-VEHICLEPROPERTYGROUP_SYSTEM = 0x10000000
-VEHICLEPROPERTYGROUP_VENDOR = 0x20000000
-VEHICLEPROPERTYGROUP_MASK = 0xf0000000
+# VehicleAudioVolumeCapabilityFlag
+VEHICLEAUDIOVOLUMECAPABILITYFLAG_PERSISTENT_STORAGE = 0x1
+VEHICLEAUDIOVOLUMECAPABILITYFLAG_MASTER_VOLUME_ONLY = 0x2
 
-# VehicleApPowerSetState
-VEHICLEAPPOWERSETSTATE_BOOT_COMPLETE = 0x1
-VEHICLEAPPOWERSETSTATE_DEEP_SLEEP_ENTRY = 0x2
-VEHICLEAPPOWERSETSTATE_DEEP_SLEEP_EXIT = 0x3
-VEHICLEAPPOWERSETSTATE_SHUTDOWN_POSTPONE = 0x4
-VEHICLEAPPOWERSETSTATE_SHUTDOWN_START = 0x5
-VEHICLEAPPOWERSETSTATE_DISPLAY_OFF = 0x6
-VEHICLEAPPOWERSETSTATE_DISPLAY_ON = 0x7
+# VehicleHwKeyInputAction
+VEHICLEHWKEYINPUTACTION_ACTION_DOWN = 0x0
+VEHICLEHWKEYINPUTACTION_ACTION_UP = 0x1
 
-# VmsBaseMessageIntegerValuesIndex
-VMSBASEMESSAGEINTEGERVALUESINDEX_MESSAGE_TYPE = 0x0
+# VehicleAudioStreamFlag
+VEHICLEAUDIOSTREAMFLAG_STREAM0_FLAG = 0x1
+VEHICLEAUDIOSTREAMFLAG_STREAM1_FLAG = 0x2
+VEHICLEAUDIOSTREAMFLAG_STREAM2_FLAG = 0x4
 
-# DiagnosticIntegerSensorIndex
-DIAGNOSTICINTEGERSENSORINDEX_FUEL_SYSTEM_STATUS = 0x0
-DIAGNOSTICINTEGERSENSORINDEX_MALFUNCTION_INDICATOR_LIGHT_ON = 0x1
-DIAGNOSTICINTEGERSENSORINDEX_IGNITION_MONITORS_SUPPORTED = 0x2
-DIAGNOSTICINTEGERSENSORINDEX_IGNITION_SPECIFIC_MONITORS = 0x3
-DIAGNOSTICINTEGERSENSORINDEX_INTAKE_AIR_TEMPERATURE = 0x4
-DIAGNOSTICINTEGERSENSORINDEX_COMMANDED_SECONDARY_AIR_STATUS = 0x5
-DIAGNOSTICINTEGERSENSORINDEX_NUM_OXYGEN_SENSORS_PRESENT = 0x6
-DIAGNOSTICINTEGERSENSORINDEX_RUNTIME_SINCE_ENGINE_START = 0x7
-DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 0x8
-DIAGNOSTICINTEGERSENSORINDEX_WARMUPS_SINCE_CODES_CLEARED = 0x9
-DIAGNOSTICINTEGERSENSORINDEX_DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 0xa
-DIAGNOSTICINTEGERSENSORINDEX_ABSOLUTE_BAROMETRIC_PRESSURE = 0xb
-DIAGNOSTICINTEGERSENSORINDEX_CONTROL_MODULE_VOLTAGE = 0xc
-DIAGNOSTICINTEGERSENSORINDEX_AMBIENT_AIR_TEMPERATURE = 0xd
-DIAGNOSTICINTEGERSENSORINDEX_TIME_WITH_MALFUNCTION_LIGHT_ON = 0xe
-DIAGNOSTICINTEGERSENSORINDEX_TIME_SINCE_TROUBLE_CODES_CLEARED = 0xf
-DIAGNOSTICINTEGERSENSORINDEX_MAX_FUEL_AIR_EQUIVALENCE_RATIO = 0x10
-DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_VOLTAGE = 0x11
-DIAGNOSTICINTEGERSENSORINDEX_MAX_OXYGEN_SENSOR_CURRENT = 0x12
-DIAGNOSTICINTEGERSENSORINDEX_MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 0x13
-DIAGNOSTICINTEGERSENSORINDEX_MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 0x14
-DIAGNOSTICINTEGERSENSORINDEX_FUEL_TYPE = 0x15
-DIAGNOSTICINTEGERSENSORINDEX_FUEL_RAIL_ABSOLUTE_PRESSURE = 0x16
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_OIL_TEMPERATURE = 0x17
-DIAGNOSTICINTEGERSENSORINDEX_DRIVER_DEMAND_PERCENT_TORQUE = 0x18
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_ACTUAL_PERCENT_TORQUE = 0x19
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_REFERENCE_PERCENT_TORQUE = 0x1a
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_IDLE = 0x1b
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT1 = 0x1c
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT2 = 0x1d
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT3 = 0x1e
-DIAGNOSTICINTEGERSENSORINDEX_ENGINE_PERCENT_TORQUE_DATA_POINT4 = 0x1f
-DIAGNOSTICINTEGERSENSORINDEX_LAST_SYSTEM_INDEX = 0x1f
-
-# VehiclePropertyChangeMode
-VEHICLEPROPERTYCHANGEMODE_STATIC = 0x0
-VEHICLEPROPERTYCHANGEMODE_ON_CHANGE = 0x1
-VEHICLEPROPERTYCHANGEMODE_CONTINUOUS = 0x2
-VEHICLEPROPERTYCHANGEMODE_POLL = 0x3
-VEHICLEPROPERTYCHANGEMODE_ON_SET = 0x4
-
-# VehicleApPowerState
-VEHICLEAPPOWERSTATE_OFF = 0x0
-VEHICLEAPPOWERSTATE_DEEP_SLEEP = 0x1
-VEHICLEAPPOWERSTATE_ON_DISP_OFF = 0x2
-VEHICLEAPPOWERSTATE_ON_FULL = 0x3
-VEHICLEAPPOWERSTATE_SHUTDOWN_PREPARE = 0x4
-
-# VehicleInstrumentClusterType
-VEHICLEINSTRUMENTCLUSTERTYPE_NONE = 0x0
-VEHICLEINSTRUMENTCLUSTERTYPE_HAL_INTERFACE = 0x1
-VEHICLEINSTRUMENTCLUSTERTYPE_EXTERNAL_DISPLAY = 0x2
+# Obd2FuelSystemStatus
+OBD2FUELSYSTEMSTATUS_OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 0x1
+OBD2FUELSYSTEMSTATUS_CLOSED_LOOP = 0x2
+OBD2FUELSYSTEMSTATUS_OPEN_ENGINE_LOAD_OR_DECELERATION = 0x4
+OBD2FUELSYSTEMSTATUS_OPEN_SYSTEM_FAILURE = 0x8
+OBD2FUELSYSTEMSTATUS_CLOSED_LOOP_BUT_FEEDBACK_FAULT = 0x10
 
 # VehicleUnit
 VEHICLEUNIT_SHOULD_NOT_USE = 0x0
@@ -650,22 +464,209 @@
 VEHICLEUNIT_SECS = 0x53
 VEHICLEUNIT_YEAR = 0x59
 
-# VehicleAudioVolumeLimitIndex
-VEHICLEAUDIOVOLUMELIMITINDEX_STREAM = 0x0
-VEHICLEAUDIOVOLUMELIMITINDEX_MAX_VOLUME = 0x1
+# VehicleAudioFocusIndex
+VEHICLEAUDIOFOCUSINDEX_FOCUS = 0x0
+VEHICLEAUDIOFOCUSINDEX_STREAMS = 0x1
+VEHICLEAUDIOFOCUSINDEX_EXTERNAL_FOCUS_STATE = 0x2
+VEHICLEAUDIOFOCUSINDEX_AUDIO_CONTEXTS = 0x3
+
+# VehiclePropertyType
+VEHICLEPROPERTYTYPE_STRING = 0x100000
+VEHICLEPROPERTYTYPE_BOOLEAN = 0x200000
+VEHICLEPROPERTYTYPE_INT32 = 0x400000
+VEHICLEPROPERTYTYPE_INT32_VEC = 0x410000
+VEHICLEPROPERTYTYPE_INT64 = 0x500000
+VEHICLEPROPERTYTYPE_FLOAT = 0x600000
+VEHICLEPROPERTYTYPE_FLOAT_VEC = 0x610000
+VEHICLEPROPERTYTYPE_BYTES = 0x700000
+VEHICLEPROPERTYTYPE_COMPLEX = 0xe00000
+VEHICLEPROPERTYTYPE_MASK = 0xff0000
+
+# VehicleAudioVolumeIndex
+VEHICLEAUDIOVOLUMEINDEX_STREAM = 0x0
+VEHICLEAUDIOVOLUMEINDEX_VOLUME = 0x1
+VEHICLEAUDIOVOLUMEINDEX_STATE = 0x2
+
+# VehicleDrivingStatus
+VEHICLEDRIVINGSTATUS_UNRESTRICTED = 0x0
+VEHICLEDRIVINGSTATUS_NO_VIDEO = 0x1
+VEHICLEDRIVINGSTATUS_NO_KEYBOARD_INPUT = 0x2
+VEHICLEDRIVINGSTATUS_NO_VOICE_INPUT = 0x4
+VEHICLEDRIVINGSTATUS_NO_CONFIG = 0x8
+VEHICLEDRIVINGSTATUS_LIMIT_MESSAGE_LEN = 0x10
+
+# VmsAvailabilityStateIntegerValuesIndex
+VMSAVAILABILITYSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
+VMSAVAILABILITYSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x2
+VMSAVAILABILITYSTATEINTEGERVALUESINDEX_LAYERS_START = 0x3
+
+# VmsSubscriptionsStateIntegerValuesIndex
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SEQUENCE_NUMBER = 0x1
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_LAYERS = 0x2
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_NUMBER_OF_ASSOCIATED_LAYERS = 0x3
+VMSSUBSCRIPTIONSSTATEINTEGERVALUESINDEX_SUBSCRIPTIONS_START = 0x4
+
+# VmsMessageWithLayerIntegerValuesIndex
+VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_TYPE = 0x1
+VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_SUBTYPE = 0x2
+VMSMESSAGEWITHLAYERINTEGERVALUESINDEX_LAYER_VERSION = 0x3
+
+# VehicleAudioFocusRequest
+VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN = 0x1
+VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT = 0x2
+VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3
+VEHICLEAUDIOFOCUSREQUEST_REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4
+VEHICLEAUDIOFOCUSREQUEST_REQUEST_RELEASE = 0x5
+
+# VehicleArea
+VEHICLEAREA_GLOBAL = 0x1000000
+VEHICLEAREA_ZONE = 0x2000000
+VEHICLEAREA_WINDOW = 0x3000000
+VEHICLEAREA_MIRROR = 0x4000000
+VEHICLEAREA_SEAT = 0x5000000
+VEHICLEAREA_DOOR = 0x6000000
+VEHICLEAREA_MASK = 0xf000000
+
+# VehicleTurnSignal
+VEHICLETURNSIGNAL_NONE = 0x0
+VEHICLETURNSIGNAL_RIGHT = 0x1
+VEHICLETURNSIGNAL_LEFT = 0x2
+VEHICLETURNSIGNAL_EMERGENCY = 0x4
+
+# VehicleDisplay
+VEHICLEDISPLAY_MAIN = 0x0
+VEHICLEDISPLAY_INSTRUMENT_CLUSTER = 0x1
+
+# VehicleAudioRoutingPolicyIndex
+VEHICLEAUDIOROUTINGPOLICYINDEX_STREAM = 0x0
+VEHICLEAUDIOROUTINGPOLICYINDEX_CONTEXTS = 0x1
+
+# Obd2IgnitionMonitorKind
+OBD2IGNITIONMONITORKIND_SPARK = 0x0
+OBD2IGNITIONMONITORKIND_COMPRESSION = 0x1
+
+# VehicleApPowerBootupReason
+VEHICLEAPPOWERBOOTUPREASON_USER_POWER_ON = 0x0
+VEHICLEAPPOWERBOOTUPREASON_USER_UNLOCK = 0x1
+VEHICLEAPPOWERBOOTUPREASON_TIMER = 0x2
+
+# Obd2FuelType
+OBD2FUELTYPE_NOT_AVAILABLE = 0x0
+OBD2FUELTYPE_GASOLINE = 0x1
+OBD2FUELTYPE_METHANOL = 0x2
+OBD2FUELTYPE_ETHANOL = 0x3
+OBD2FUELTYPE_DIESEL = 0x4
+OBD2FUELTYPE_LPG = 0x5
+OBD2FUELTYPE_CNG = 0x6
+OBD2FUELTYPE_PROPANE = 0x7
+OBD2FUELTYPE_ELECTRIC = 0x8
+OBD2FUELTYPE_BIFUEL_RUNNING_GASOLINE = 0x9
+OBD2FUELTYPE_BIFUEL_RUNNING_METHANOL = 0xa
+OBD2FUELTYPE_BIFUEL_RUNNING_ETHANOL = 0xb
+OBD2FUELTYPE_BIFUEL_RUNNING_LPG = 0xc
+OBD2FUELTYPE_BIFUEL_RUNNING_CNG = 0xd
+OBD2FUELTYPE_BIFUEL_RUNNING_PROPANE = 0xe
+OBD2FUELTYPE_BIFUEL_RUNNING_ELECTRIC = 0xf
+OBD2FUELTYPE_BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 0x10
+OBD2FUELTYPE_HYBRID_GASOLINE = 0x11
+OBD2FUELTYPE_HYBRID_ETHANOL = 0x12
+OBD2FUELTYPE_HYBRID_DIESEL = 0x13
+OBD2FUELTYPE_HYBRID_ELECTRIC = 0x14
+OBD2FUELTYPE_HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 0x15
+OBD2FUELTYPE_HYBRID_REGENERATIVE = 0x16
+OBD2FUELTYPE_BIFUEL_RUNNING_DIESEL = 0x17
+
+# VehicleAudioExtFocusFlag
+VEHICLEAUDIOEXTFOCUSFLAG_NONE_FLAG = 0x0
+VEHICLEAUDIOEXTFOCUSFLAG_PERMANENT_FLAG = 0x1
+VEHICLEAUDIOEXTFOCUSFLAG_TRANSIENT_FLAG = 0x2
+VEHICLEAUDIOEXTFOCUSFLAG_PLAY_ONLY_FLAG = 0x4
+VEHICLEAUDIOEXTFOCUSFLAG_MUTE_MEDIA_FLAG = 0x8
 
 # VehicleApPowerStateShutdownParam
 VEHICLEAPPOWERSTATESHUTDOWNPARAM_SHUTDOWN_IMMEDIATELY = 0x1
 VEHICLEAPPOWERSTATESHUTDOWNPARAM_CAN_SLEEP = 0x2
 VEHICLEAPPOWERSTATESHUTDOWNPARAM_SHUTDOWN_ONLY = 0x3
 
-# VehicleApPowerStateIndex
-VEHICLEAPPOWERSTATEINDEX_STATE = 0x0
-VEHICLEAPPOWERSTATEINDEX_ADDITIONAL = 0x1
+# VehicleInstrumentClusterType
+VEHICLEINSTRUMENTCLUSTERTYPE_NONE = 0x0
+VEHICLEINSTRUMENTCLUSTERTYPE_HAL_INTERFACE = 0x1
+VEHICLEINSTRUMENTCLUSTERTYPE_EXTERNAL_DISPLAY = 0x2
 
-# VehicleDisplay
-VEHICLEDISPLAY_MAIN = 0x0
-VEHICLEDISPLAY_INSTRUMENT_CLUSTER = 0x1
+# Obd2SparkIgnitionMonitors
+OBD2SPARKIGNITIONMONITORS_EGR_AVAILABLE = 0x40
+OBD2SPARKIGNITIONMONITORS_EGR_INCOMPLETE = 0x80
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_AVAILABLE = 0x100
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x200
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_AVAILABLE = 0x400
+OBD2SPARKIGNITIONMONITORS_OXYGEN_SENSOR_INCOMPLETE = 0x800
+OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_AVAILABLE = 0x1000
+OBD2SPARKIGNITIONMONITORS_AC_REFRIGERANT_INCOMPLETE = 0x2000
+OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_AVAILABLE = 0x4000
+OBD2SPARKIGNITIONMONITORS_SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x8000
+OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_AVAILABLE = 0x10000
+OBD2SPARKIGNITIONMONITORS_EVAPORATIVE_SYSTEM_INCOMPLETE = 0x20000
+OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_AVAILABLE = 0x40000
+OBD2SPARKIGNITIONMONITORS_HEATED_CATALYST_INCOMPLETE = 0x80000
+OBD2SPARKIGNITIONMONITORS_CATALYST_AVAILABLE = 0x100000
+OBD2SPARKIGNITIONMONITORS_CATALYST_INCOMPLETE = 0x200000
+
+# VehicleApPowerStateConfigFlag
+VEHICLEAPPOWERSTATECONFIGFLAG_ENABLE_DEEP_SLEEP_FLAG = 0x1
+VEHICLEAPPOWERSTATECONFIGFLAG_CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2
+
+# VmsOfferingMessageIntegerValuesIndex
+VMSOFFERINGMESSAGEINTEGERVALUESINDEX_PUBLISHER_ID = 0x1
+VMSOFFERINGMESSAGEINTEGERVALUESINDEX_NUMBER_OF_OFFERS = 0x2
+VMSOFFERINGMESSAGEINTEGERVALUESINDEX_OFFERING_START = 0x3
+
+# VehicleAreaDoor
+VEHICLEAREADOOR_ROW_1_LEFT = 0x1
+VEHICLEAREADOOR_ROW_1_RIGHT = 0x4
+VEHICLEAREADOOR_ROW_2_LEFT = 0x10
+VEHICLEAREADOOR_ROW_2_RIGHT = 0x40
+VEHICLEAREADOOR_ROW_3_LEFT = 0x100
+VEHICLEAREADOOR_ROW_3_RIGHT = 0x400
+VEHICLEAREADOOR_HOOD = 0x10000000
+VEHICLEAREADOOR_REAR = 0x20000000
+
+# VehicleApPowerState
+VEHICLEAPPOWERSTATE_OFF = 0x0
+VEHICLEAPPOWERSTATE_DEEP_SLEEP = 0x1
+VEHICLEAPPOWERSTATE_ON_DISP_OFF = 0x2
+VEHICLEAPPOWERSTATE_ON_FULL = 0x3
+VEHICLEAPPOWERSTATE_SHUTDOWN_PREPARE = 0x4
+
+# VehicleAreaSeat
+VEHICLEAREASEAT_ROW_1_LEFT = 0x1
+VEHICLEAREASEAT_ROW_1_CENTER = 0x2
+VEHICLEAREASEAT_ROW_1_RIGHT = 0x4
+VEHICLEAREASEAT_ROW_2_LEFT = 0x10
+VEHICLEAREASEAT_ROW_2_CENTER = 0x20
+VEHICLEAREASEAT_ROW_2_RIGHT = 0x40
+VEHICLEAREASEAT_ROW_3_LEFT = 0x100
+VEHICLEAREASEAT_ROW_3_CENTER = 0x200
+VEHICLEAREASEAT_ROW_3_RIGHT = 0x400
+
+# Obd2SecondaryAirStatus
+OBD2SECONDARYAIRSTATUS_UPSTREAM = 0x1
+OBD2SECONDARYAIRSTATUS_DOWNSTREAM_OF_CATALYCIC_CONVERTER = 0x2
+OBD2SECONDARYAIRSTATUS_FROM_OUTSIDE_OR_OFF = 0x4
+OBD2SECONDARYAIRSTATUS_PUMP_ON_FOR_DIAGNOSTICS = 0x8
+
+# VehicleRadioConstants
+VEHICLERADIOCONSTANTS_VEHICLE_RADIO_PRESET_MIN_VALUE = 0x1
+
+# VehicleAudioHwVariantConfigFlag
+VEHICLEAUDIOHWVARIANTCONFIGFLAG_INTERNAL_RADIO_FLAG = 0x1
+
+# StatusCode
+STATUSCODE_OK = 0x0
+STATUSCODE_TRY_AGAIN = 0x1
+STATUSCODE_INVALID_ARG = 0x2
+STATUSCODE_NOT_AVAILABLE = 0x3
+STATUSCODE_ACCESS_DENIED = 0x4
+STATUSCODE_INTERNAL_ERROR = 0x5
 
 # Create a container of value_type constants to be used by vhal_emulator
 class vhal_types_2_0: