Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 974f1f31 authored by Zhi Dou's avatar Zhi Dou Committed by Gerrit Code Review
Browse files

Merge "Add errorcode in AconfigStorageException" into main

parents 66e0b243 3b50d0d1
Loading
Loading
Loading
Loading
+106 −0
Original line number Diff line number Diff line
@@ -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 + ">";
        }
    }
}
+27 −21
Original line number Diff line number Diff line
@@ -27,29 +27,26 @@ public class AconfigPackageImpl {
    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 @@ public class AconfigPackageImpl {
        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 @@ public class AconfigPackageImpl {
                }
            } 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 @@ public class AconfigPackageImpl {
            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 @@ public class AconfigPackageImpl {
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
        return 0;
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -105,7 +105,9 @@ public class StorageFileProvider {
            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);
        }
+48 −28
Original line number Diff line number Diff line
@@ -43,53 +43,73 @@ public class AconfigPackageImplTest {

    @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/");
        e =
                assertThrows(
                        AconfigStorageException.class,
                () -> p.load("mockup", "com.android.aconfig.storage.test_1", pr));
                        () ->
                                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 @@ public class AconfigPackageImplTest {

    @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 @@ public class AconfigPackageImplTest {

    @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());
    }
}