Merge "Fix an issue where running multiple test cases would cause a NPE in CarStorageMonitoringService"
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index bd46857..568d611 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -32,6 +32,7 @@
field public static final java.lang.String PERMISSION_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";
@@ -1004,6 +1005,7 @@
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
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index c894504..6101797 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -300,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;
diff --git a/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java b/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
index 6d7aede..aa2ad84 100644
--- a/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
+++ b/car-lib/src/android/car/storagemonitoring/CarStorageMonitoringManager.java
@@ -67,5 +67,28 @@
}
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
index 8d05f79..61910c5 100644
--- a/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl
+++ b/car-lib/src/android/car/storagemonitoring/ICarStorageMonitoring.aidl
@@ -16,10 +16,17 @@
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/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/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/CarStorageMonitoringService.java b/service/src/com/android/car/CarStorageMonitoringService.java
index 8182e2e..113adf9 100644
--- a/service/src/com/android/car/CarStorageMonitoringService.java
+++ b/service/src/com/android/car/CarStorageMonitoringService.java
@@ -16,12 +16,13 @@
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.storagemonitoring.EMmcWearInformationProvider;
-import com.android.car.storagemonitoring.UfsWearInformationProvider;
+import com.android.car.internal.CarPermission;
import com.android.car.storagemonitoring.WearInformation;
import com.android.car.storagemonitoring.WearInformationProvider;
import java.io.File;
@@ -40,6 +41,8 @@
private final File mWearInfoFile;
private final OnShutdownReboot mOnShutdownReboot;
+ private final CarPermission mStorageMonitoringPermission;
+
private UptimeTracker mUptimeTracker;
private Optional<WearInformation> mWearInformation = Optional.empty();
@@ -49,6 +52,8 @@
mWearInfoFile = new File(mContext.getFilesDir(), WEAR_INFO_FILENAME);
mOnShutdownReboot = new OnShutdownReboot(mContext);
mWearInformationProviders = systemInterface.getFlashWearInformationProviders();
+ mStorageMonitoringPermission =
+ new CarPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
}
/**
@@ -98,7 +103,18 @@
@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/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index e7c53eb..c308d81 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -248,7 +248,7 @@
case Car.BLUETOOTH_SERVICE:
return mCarBluetoothService;
case Car.STORAGE_MONITORING_SERVICE:
- // TODO(egranata): enforce permission here
+ assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
return mCarStorageMonitoringService;
default:
Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
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/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
index 51150ac..b5165a8 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
@@ -64,8 +64,10 @@
mStorageManager =
(CarStorageMonitoringManager) mActivity.getCar().getCarManager(
Car.STORAGE_MONITORING_SERVICE);
- mStorageWearInfo.setText("Pre EOL indicator: " + preEolToString(
- mStorageManager.getPreEolIndicatorStatus()));
+
+ 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);
diff --git a/tests/carservice_test/AndroidManifest.xml b/tests/carservice_test/AndroidManifest.xml
index b610e78..7330aaa 100644
--- a/tests/carservice_test/AndroidManifest.xml
+++ b/tests/carservice_test/AndroidManifest.xml
@@ -24,6 +24,7 @@
<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"/>
diff --git a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
index 532bc1c..cd104f8 100644
--- a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
+++ b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
@@ -18,6 +18,7 @@
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;
@@ -26,14 +27,14 @@
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(new WearInformation(
- WearInformation.UNKNOWN_LIFETIME_ESTIMATE,
- WearInformation.UNKNOWN_LIFETIME_ESTIMATE,
- WearInformation.PRE_EOL_INFO_NORMAL));
+ setFlashWearInformation(DEFAULT_WEAR_INFORMATION);
}
@Override
@@ -45,7 +46,15 @@
}
public void testReadPreEolInformation() throws Exception {
- assertEquals(WearInformation.PRE_EOL_INFO_NORMAL,
+ 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);
+ }
}