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

Commit f959756f authored by Xiao Ma's avatar Xiao Ma
Browse files

Wipe the data in IpMemoryStore database upon network factory reset.

Bug:128499160
Test: manual
Test: atest FrameworksNetTests NetworkStackTests
Merged-In: I13ad04454e638905b74dd42a1c83266c7c37652f
Merged-In: Ia13ff10a57c2043f6676976f23ecfb2d2a9a6ef0
(cherry picked from commit ef6ef68c48b869aa9960edd81c73f3d31391ae26)

Change-Id: I42507451d55a620c0e2d271c895ad158f348c1a5
parent ac95b9f1
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -410,6 +410,7 @@ public class IpMemoryStoreDatabase {
    private static final String[] DATA_COLUMN = new String[] {
            PrivateDataContract.COLNAME_DATA
    };

    @Nullable
    static byte[] retrieveBlob(@NonNull final SQLiteDatabase db, @NonNull final String key,
            @NonNull final String clientId, @NonNull final String name) {
@@ -431,6 +432,57 @@ public class IpMemoryStoreDatabase {
        return result;
    }

    /**
     * Wipe all data in tables when network factory reset occurs.
     */
    static void wipeDataUponNetworkReset(@NonNull final SQLiteDatabase db) {
        for (int remainingRetries = 3; remainingRetries > 0; --remainingRetries) {
            db.beginTransaction();
            try {
                db.delete(NetworkAttributesContract.TABLENAME, null, null);
                db.delete(PrivateDataContract.TABLENAME, null, null);
                final Cursor cursorNetworkAttributes = db.query(
                        // table name
                        NetworkAttributesContract.TABLENAME,
                        // column name
                        new String[] { NetworkAttributesContract.COLNAME_L2KEY },
                        null, // selection
                        null, // selectionArgs
                        null, // groupBy
                        null, // having
                        null, // orderBy
                        "1"); // limit
                if (0 != cursorNetworkAttributes.getCount()) {
                    cursorNetworkAttributes.close();
                    continue;
                }
                cursorNetworkAttributes.close();
                final Cursor cursorPrivateData = db.query(
                        // table name
                        PrivateDataContract.TABLENAME,
                        // column name
                        new String[] { PrivateDataContract.COLNAME_L2KEY },
                        null, // selection
                        null, // selectionArgs
                        null, // groupBy
                        null, // having
                        null, // orderBy
                        "1"); // limit
                if (0 != cursorPrivateData.getCount()) {
                    cursorPrivateData.close();
                    continue;
                }
                cursorPrivateData.close();
                db.setTransactionSuccessful();
                return;
            } catch (SQLiteException e) {
                Log.e(TAG, "Could not wipe the data in database", e);
            } finally {
                db.endTransaction();
            }
        }
    }

    /**
     * The following is a horrible hack that is necessary because the Android SQLite API does not
     * have a way to query a binary blob. This, almost certainly, is an overlook.
+4 −0
Original line number Diff line number Diff line
@@ -410,8 +410,12 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub {
        });
    }

    /**
     * Wipe the data in IpMemoryStore database upon network factory reset.
     */
    @Override
    public void factoryReset() {
        mExecutor.execute(() -> IpMemoryStoreDatabase.wipeDataUponNetworkReset(mDb));
    }

    /** Get db size threshold. */
+100 −28
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -77,7 +78,11 @@ public class IpMemoryStoreServiceTest {
    private static final int DEFAULT_TIMEOUT_MS = 5000;
    private static final int LONG_TIMEOUT_MS = 30000;
    private static final int FAKE_KEY_COUNT = 20;
    private static final long LEASE_EXPIRY_NULL = -1L;
    private static final int MTU_NULL = -1;
    private static final String[] FAKE_KEYS;
    private static final byte[] TEST_BLOB_DATA = new byte[] { -3, 6, 8, -9, 12,
            -128, 0, 89, 112, 91, -34 };
    static {
        FAKE_KEYS = new String[FAKE_KEY_COUNT];
        for (int i = 0; i < FAKE_KEYS.length; ++i) {
@@ -124,6 +129,29 @@ public class IpMemoryStoreServiceTest {
        mDbFile.delete();
    }

    /** Helper method to build test network attributes */
    private static NetworkAttributes.Builder buildTestNetworkAttributes(
            final Inet4Address ipAddress, final long expiry, final String hint,
            final List<InetAddress> dnsServers, final int mtu) {
        final NetworkAttributes.Builder na = new NetworkAttributes.Builder();
        if (null != ipAddress) {
            na.setAssignedV4Address(ipAddress);
        }
        if (LEASE_EXPIRY_NULL != expiry) {
            na.setAssignedV4AddressExpiry(expiry);
        }
        if (null != hint) {
            na.setGroupHint(hint);
        }
        if (null != dnsServers) {
            na.setDnsAddresses(dnsServers);
        }
        if (MTU_NULL != mtu) {
            na.setMtu(mtu);
        }
        return na;
    }

    /** Helper method to make a vanilla IOnStatusListener */
    private IOnStatusListener onStatus(Consumer<Status> functor) {
        return new IOnStatusListener() {
@@ -265,7 +293,7 @@ public class IpMemoryStoreServiceTest {
        }
    }

    // Helper methods to factorize more boilerplate
    // Helper method to store network attributes to database
    private void storeAttributes(final String l2Key, final NetworkAttributes na) {
        storeAttributes("Did not complete storing attributes", l2Key, na);
    }
@@ -278,15 +306,28 @@ public class IpMemoryStoreServiceTest {
                })));
    }

    // Helper method to store blob data to database
    private void storeBlobOrFail(final String l2Key, final Blob b, final byte[] data) {
        storeBlobOrFail("Did not complete storing private data", l2Key, b, data);
    }
    private void storeBlobOrFail(final String timeoutMessage, final String l2Key, final Blob b,
            final byte[] data) {
        b.data = data;
        doLatched(timeoutMessage, latch -> mService.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME,
                b, onStatus(status -> {
                    assertTrue("Store status not successful : " + status.resultCode,
                            status.isSuccess());
                    latch.countDown();
                })));
    }

    /** Insert large data that db size will be over threshold for maintenance test usage. */
    private void insertFakeDataAndOverThreshold() {
        try {
            final NetworkAttributes.Builder na = new NetworkAttributes.Builder();
            na.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
            na.setGroupHint("hint1");
            na.setMtu(219);
            na.setDnsAddresses(Arrays.asList(Inet6Address.getByName("0A1C:2E40:480A::1CA6")));
            final byte[] data = new byte[]{-3, 6, 8, -9, 12, -128, 0, 89, 112, 91, -34};
            final NetworkAttributes.Builder na = buildTestNetworkAttributes(
                    (Inet4Address) Inet4Address.getByName("1.2.3.4"), LEASE_EXPIRY_NULL,
                    "hint1", Arrays.asList(Inet6Address.getByName("0A1C:2E40:480A::1CA6")),
                    219);
            final long time = System.currentTimeMillis() - 1;
            for (int i = 0; i < 1000; i++) {
                int errorCode = IpMemoryStoreDatabase.storeNetworkAttributes(
@@ -298,7 +339,8 @@ public class IpMemoryStoreServiceTest {
                assertEquals(errorCode, Status.SUCCESS);

                errorCode = IpMemoryStoreDatabase.storeBlob(
                        mService.mDb, "fakeKey" + i, TEST_CLIENT_ID, TEST_DATA_NAME, data);
                        mService.mDb, "fakeKey" + i, TEST_CLIENT_ID, TEST_DATA_NAME,
                        TEST_BLOB_DATA);
                assertEquals(errorCode, Status.SUCCESS);
            }

@@ -320,12 +362,10 @@ public class IpMemoryStoreServiceTest {

    @Test
    public void testNetworkAttributes() throws UnknownHostException {
        final NetworkAttributes.Builder na = new NetworkAttributes.Builder();
        na.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
        na.setAssignedV4AddressExpiry(System.currentTimeMillis() + 7_200_000);
        na.setGroupHint("hint1");
        na.setMtu(219);
        final String l2Key = FAKE_KEYS[0];
        final NetworkAttributes.Builder na = buildTestNetworkAttributes(
                (Inet4Address) Inet4Address.getByName("1.2.3.4"),
                System.currentTimeMillis() + 7_200_000, "hint1", null, 219);
        NetworkAttributes attributes = na.build();
        storeAttributes(l2Key, attributes);

@@ -420,16 +460,9 @@ public class IpMemoryStoreServiceTest {

    @Test
    public void testPrivateData() {
        final Blob b = new Blob();
        b.data = new byte[] { -3, 6, 8, -9, 12, -128, 0, 89, 112, 91, -34 };
        final String l2Key = FAKE_KEYS[0];
        doLatched("Did not complete storing private data", latch ->
                mService.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
                        onStatus(status -> {
                            assertTrue("Store status not successful : " + status.resultCode,
                                    status.isSuccess());
                            latch.countDown();
                        })));
        final Blob b = new Blob();
        storeBlobOrFail(l2Key, b, TEST_BLOB_DATA);

        doLatched("Did not complete retrieving private data", latch ->
                mService.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, onBlobRetrieved(
@@ -564,11 +597,10 @@ public class IpMemoryStoreServiceTest {

    @Test
    public void testIsSameNetwork() throws UnknownHostException {
        final NetworkAttributes.Builder na = new NetworkAttributes.Builder();
        na.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
        na.setGroupHint("hint1");
        na.setMtu(219);
        na.setDnsAddresses(Arrays.asList(Inet6Address.getByName("0A1C:2E40:480A::1CA6")));
        final NetworkAttributes.Builder na = buildTestNetworkAttributes(
                (Inet4Address) Inet4Address.getByName("1.2.3.4"), LEASE_EXPIRY_NULL,
                "hint1", Arrays.asList(Inet6Address.getByName("0A1C:2E40:480A::1CA6")),
                219);

        storeAttributes(FAKE_KEYS[0], na.build());
        // 0 and 1 have identical attributes
@@ -601,7 +633,6 @@ public class IpMemoryStoreServiceTest {
                })));
    }


    @Test
    public void testFullMaintenance() {
        insertFakeDataAndOverThreshold();
@@ -660,4 +691,45 @@ public class IpMemoryStoreServiceTest {
        // still be over the threshold.
        assertTrue(mService.isDbSizeOverThreshold());
    }

    @Test
    public void testFactoryReset() throws UnknownHostException {
        final String l2Key = FAKE_KEYS[0];

        // store network attributes
        final NetworkAttributes.Builder na = buildTestNetworkAttributes(
                (Inet4Address) Inet4Address.getByName("1.2.3.4"),
                System.currentTimeMillis() + 7_200_000, "hint1", null, 219);
        storeAttributes(l2Key, na.build());

        // store private data blob
        final Blob b = new Blob();
        storeBlobOrFail(l2Key, b, TEST_BLOB_DATA);

        // wipe all data in Database
        mService.factoryReset();

        // retrieved network attributes should be null
        doLatched("Did not complete retrieving attributes", latch ->
                mService.retrieveNetworkAttributes(l2Key, onNetworkAttributesRetrieved(
                        (status, key, attr) -> {
                            assertTrue("Retrieve network attributes not successful : "
                                    + status.resultCode, status.isSuccess());
                            assertEquals(l2Key, key);
                            assertNull(attr);
                            latch.countDown();
                        })));

        // retrieved private data blob should be null
        doLatched("Did not complete retrieving private data", latch ->
                mService.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, onBlobRetrieved(
                        (status, key, name, data) -> {
                            assertTrue("Retrieve blob status not successful : " + status.resultCode,
                                    status.isSuccess());
                            assertEquals(l2Key, key);
                            assertEquals(name, TEST_DATA_NAME);
                            assertNull(data);
                            latch.countDown();
                        })));
    }
}