Add errorcode in AconfigStorageException
This chagne adds errorCode in AconfigStorageException, so when the
caller catch this error, the caller have the ability to know the detail
about the error
Test: atest aconfig_storage_file.test.java aconfig_storage_package
Bug: 367765164
Flag: EXEMPT refactor
Change-Id: I1da3b4383e2875e60933803c94ca2da8f9c6ad06
diff --git a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/AconfigStorageException.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/AconfigStorageException.java
index 86a75f2..b1c7ee7 100644
--- a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/AconfigStorageException.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/AconfigStorageException.java
@@ -16,12 +16,118 @@
package android.aconfig.storage;
+/**
+ * Exception thrown when an error occurs while accessing Aconfig Storage.
+ *
+ * <p>This exception indicates a general problem with Aconfig Storage, such as an inability to read
+ * or write data.
+ */
public class AconfigStorageException extends RuntimeException {
+
+ /** Generic error code indicating an unspecified Aconfig Storage error. */
+ public static final int ERROR_GENERIC = 0;
+
+ /** Error code indicating that the Aconfig Storage system is not found on the device. */
+ public static final int ERROR_STORAGE_SYSTEM_NOT_FOUND = 1;
+
+ /** Error code indicating that the requested configuration package is not found. */
+ public static final int ERROR_PACKAGE_NOT_FOUND = 2;
+
+ /** Error code indicating that the specified container is not found. */
+ public static final int ERROR_CONTAINER_NOT_FOUND = 3;
+
+ /** Error code indicating that there was an error reading the Aconfig Storage file. */
+ public static final int ERROR_CANNOT_READ_STORAGE_FILE = 4;
+
+ private final int mErrorCode;
+
+ /**
+ * Constructs a new {@code AconfigStorageException} with a generic error code and the specified
+ * detail message.
+ *
+ * @param msg The detail message for this exception.
+ */
public AconfigStorageException(String msg) {
super(msg);
+ mErrorCode = ERROR_GENERIC;
}
+ /**
+ * Constructs a new {@code AconfigStorageException} with a generic error code, the specified
+ * detail message, and cause.
+ *
+ * @param msg The detail message for this exception.
+ * @param cause The cause of this exception.
+ */
public AconfigStorageException(String msg, Throwable cause) {
super(msg, cause);
+ mErrorCode = ERROR_GENERIC;
+ }
+
+ /**
+ * Constructs a new {@code AconfigStorageException} with the specified error code and detail
+ * message.
+ *
+ * @param errorCode The error code for this exception.
+ * @param msg The detail message for this exception.
+ */
+ public AconfigStorageException(int errorCode, String msg) {
+ super(msg);
+ mErrorCode = errorCode;
+ }
+
+ /**
+ * Constructs a new {@code AconfigStorageException} with the specified error code, detail
+ * message, and cause.
+ *
+ * @param errorCode The error code for this exception.
+ * @param msg The detail message for this exception.
+ * @param cause The cause of this exception.
+ */
+ public AconfigStorageException(int errorCode, String msg, Throwable cause) {
+ super(msg, cause);
+ mErrorCode = errorCode;
+ }
+
+ /**
+ * Returns the error code associated with this exception.
+ *
+ * @return The error code.
+ */
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+
+ /**
+ * Returns the error message for this exception, including the error code and the original
+ * message.
+ *
+ * @return The error message.
+ */
+ @Override
+ public String getMessage() {
+ return errorString() + ": " + super.getMessage();
+ }
+
+ /**
+ * Returns a string representation of the error code.
+ *
+ * @return The error code string.
+ */
+ private String errorString() {
+ switch (mErrorCode) {
+ case ERROR_GENERIC:
+ return "ERROR_GENERIC";
+ case ERROR_STORAGE_SYSTEM_NOT_FOUND:
+ return "ERROR_STORAGE_SYSTEM_NOT_FOUND";
+ case ERROR_PACKAGE_NOT_FOUND:
+ return "ERROR_PACKAGE_NOT_FOUND";
+ case ERROR_CONTAINER_NOT_FOUND:
+ return "ERROR_CONTAINER_NOT_FOUND";
+ case ERROR_CANNOT_READ_STORAGE_FILE:
+ return "ERROR_CANNOT_READ_STORAGE_FILE";
+ default:
+ return "<Unknown error code " + mErrorCode + ">";
+ }
}
}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
index 5d8e7cb..c2bef31 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
@@ -27,29 +27,26 @@
private PackageTable.Node mPNode;
/** @hide */
- public static final int ERROR_NEW_STORAGE_SYSTEM_NOT_FOUND = 1;
+ private AconfigPackageImpl() {}
/** @hide */
- public static final int ERROR_PACKAGE_NOT_FOUND = 2;
-
- /** @hide */
- public static final int ERROR_CONTAINER_NOT_FOUND = 3;
-
- /** @hide */
- public AconfigPackageImpl() {}
-
- /** @hide */
- public int load(String packageName, StorageFileProvider fileProvider) {
- return init(null, packageName, fileProvider);
+ public static AconfigPackageImpl load(String packageName, StorageFileProvider fileProvider) {
+ AconfigPackageImpl impl = new AconfigPackageImpl();
+ impl.init(null, packageName, fileProvider);
+ return impl;
}
/** @hide */
- public int load(String container, String packageName, StorageFileProvider fileProvider) {
+ public static AconfigPackageImpl load(
+ String container, String packageName, StorageFileProvider fileProvider) {
if (container == null) {
- return ERROR_CONTAINER_NOT_FOUND;
+ throw new AconfigStorageException(
+ AconfigStorageException.ERROR_CONTAINER_NOT_FOUND,
+ "container null cannot be found on the device");
}
-
- return init(container, packageName, fileProvider);
+ AconfigPackageImpl impl = new AconfigPackageImpl();
+ impl.init(container, packageName, fileProvider);
+ return impl;
}
/** @hide */
@@ -76,13 +73,15 @@
return mPNode.hasPackageFingerprint();
}
- private int init(String containerName, String packageName, StorageFileProvider fileProvider) {
+ private void init(String containerName, String packageName, StorageFileProvider fileProvider) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
String container = containerName;
try {
// for devices don't have new storage directly return
if (!fileProvider.containerFileExists(null)) {
- return ERROR_NEW_STORAGE_SYSTEM_NOT_FOUND;
+ throw new AconfigStorageException(
+ AconfigStorageException.ERROR_STORAGE_SYSTEM_NOT_FOUND,
+ "aconfig storage cannot be found on the device");
}
PackageTable.Node pNode = null;
@@ -107,7 +106,9 @@
}
} else {
if (!fileProvider.containerFileExists(container)) {
- return ERROR_CONTAINER_NOT_FOUND;
+ throw new AconfigStorageException(
+ AconfigStorageException.ERROR_CONTAINER_NOT_FOUND,
+ "container " + container + " cannot be found on the device");
}
pNode = fileProvider.getPackageTable(container).get(packageName);
}
@@ -115,7 +116,13 @@
if (pNode == null) {
// for the case package is not found in all container, return instead of throwing
// error
- return ERROR_PACKAGE_NOT_FOUND;
+ throw new AconfigStorageException(
+ AconfigStorageException.ERROR_PACKAGE_NOT_FOUND,
+ "package "
+ + packageName
+ + " in container "
+ + container
+ + " cannot be found on the device");
}
mFlagTable = fileProvider.getFlagTable(container);
@@ -126,6 +133,5 @@
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
- return 0;
}
}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
index 1f84a51..b28341e 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
@@ -105,7 +105,9 @@
return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
} catch (Exception e) {
throw new AconfigStorageException(
- String.format("Fail to mmap storage file %s", file), e);
+ AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE,
+ String.format("Fail to mmap storage file %s", file),
+ e);
} finally {
quietlyDispose(channel);
}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
index 8a72f0a..18f70e8 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
@@ -43,53 +43,73 @@
@Test
public void testLoad_onlyPackageName() throws Exception {
- AconfigPackageImpl p = new AconfigPackageImpl();
- p.load("com.android.aconfig.storage.test_1", pr);
+ AconfigPackageImpl p = AconfigPackageImpl.load("com.android.aconfig.storage.test_1", pr);
assertNotNull(p);
}
@Test
public void testLoad_groupNameFingerprint() throws Exception {
- AconfigPackageImpl p = new AconfigPackageImpl();
- p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ AconfigPackageImpl p =
+ AconfigPackageImpl.load("mockup", "com.android.aconfig.storage.test_1", pr);
assertNotNull(p);
}
@Test
public void testLoad_error() throws Exception {
- AconfigPackageImpl p = new AconfigPackageImpl();
+ AconfigPackageImpl p;
+ AconfigStorageException e =
+ assertThrows(
+ AconfigStorageException.class,
+ () ->
+ AconfigPackageImpl.load(
+ "mockup", "com.android.aconfig.storage.test_10", pr));
// cannot find package
- assertEquals(
- AconfigPackageImpl.ERROR_PACKAGE_NOT_FOUND,
- p.load("mockup", "com.android.aconfig.storage.test_10", pr));
+ assertEquals(AconfigStorageException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
// cannot find package
- assertEquals(
- AconfigPackageImpl.ERROR_PACKAGE_NOT_FOUND,
- p.load("com.android.aconfig.storage.test_10", pr));
+ e =
+ assertThrows(
+ AconfigStorageException.class,
+ () -> AconfigPackageImpl.load("com.android.aconfig.storage.test_10", pr));
+ assertEquals(AconfigStorageException.ERROR_PACKAGE_NOT_FOUND, e.getErrorCode());
// cannot find container
- assertEquals(
- AconfigPackageImpl.ERROR_CONTAINER_NOT_FOUND,
- p.load(null, "com.android.aconfig.storage.test_1", pr));
- assertEquals(
- AconfigPackageImpl.ERROR_CONTAINER_NOT_FOUND,
- p.load("test", "com.android.aconfig.storage.test_1", pr));
+ e =
+ assertThrows(
+ AconfigStorageException.class,
+ () ->
+ AconfigPackageImpl.load(
+ null, "com.android.aconfig.storage.test_1", pr));
+ assertEquals(AconfigStorageException.ERROR_CONTAINER_NOT_FOUND, e.getErrorCode());
+ e =
+ assertThrows(
+ AconfigStorageException.class,
+ () ->
+ AconfigPackageImpl.load(
+ "test", "com.android.aconfig.storage.test_1", pr));
+ assertEquals(AconfigStorageException.ERROR_CONTAINER_NOT_FOUND, e.getErrorCode());
// new storage doesn't exist
pr = new StorageFileProvider("fake/path/", "fake/path/");
- assertEquals(
- AconfigPackageImpl.ERROR_NEW_STORAGE_SYSTEM_NOT_FOUND, p.load("fake_package", pr));
+ e =
+ assertThrows(
+ AconfigStorageException.class,
+ () -> AconfigPackageImpl.load("fake_package", pr));
+ assertEquals(AconfigStorageException.ERROR_STORAGE_SYSTEM_NOT_FOUND, e.getErrorCode());
// file read issue
pr = new StorageFileProvider(TestDataUtils.TESTDATA_PATH, "fake/path/");
- assertThrows(
- AconfigStorageException.class,
- () -> p.load("mockup", "com.android.aconfig.storage.test_1", pr));
+ e =
+ assertThrows(
+ AconfigStorageException.class,
+ () ->
+ AconfigPackageImpl.load(
+ "mockup", "com.android.aconfig.storage.test_1", pr));
+ assertEquals(AconfigStorageException.ERROR_CANNOT_READ_STORAGE_FILE, e.getErrorCode());
}
@Test
public void testGetBooleanFlagValue_flagName() throws Exception {
- AconfigPackageImpl p = new AconfigPackageImpl();
- p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ AconfigPackageImpl p =
+ AconfigPackageImpl.load("mockup", "com.android.aconfig.storage.test_1", pr);
assertFalse(p.getBooleanFlagValue("disabled_rw", true));
assertTrue(p.getBooleanFlagValue("enabled_ro", false));
assertTrue(p.getBooleanFlagValue("enabled_rw", false));
@@ -98,8 +118,8 @@
@Test
public void testGetBooleanFlagValue_index() throws Exception {
- AconfigPackageImpl p = new AconfigPackageImpl();
- p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ AconfigPackageImpl p =
+ AconfigPackageImpl.load("mockup", "com.android.aconfig.storage.test_1", pr);
assertFalse(p.getBooleanFlagValue(0));
assertTrue(p.getBooleanFlagValue(1));
assertTrue(p.getBooleanFlagValue(2));
@@ -107,8 +127,8 @@
@Test
public void testHasPackageFingerprint() throws Exception {
- AconfigPackageImpl p = new AconfigPackageImpl();
- p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ AconfigPackageImpl p =
+ AconfigPackageImpl.load("mockup", "com.android.aconfig.storage.test_1", pr);
assertFalse(p.hasPackageFingerprint());
}
}