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

Commit 3a12e4eb authored by Manjeet Rulhania's avatar Manjeet Rulhania Committed by Android (Google) Code Review
Browse files

Merge "Handle rollback from unified sqlite to xml" into main

parents 5e405508 719bee98
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -117,6 +117,35 @@ public class DiscreteOpsMigrationHelper {
        }
    }

    /**
     * rollback discrete ops from unified schema sqlite to xml schema.
     */
    static void rollbackFromUnifiedSchemaSqliteToXml(AppOpHistoryHelper sourceRegistry,
            DiscreteOpsXmlRegistry targetRegistry) {
        try {
            List<AggregatedAppOpAccessEvent> unifiedSchemaSqliteOps =
                    sourceRegistry.getAppOpHistory();
            List<DiscreteOpsSqlRegistry.DiscreteOp> discreteOps = new ArrayList<>();
            for (AggregatedAppOpAccessEvent event : unifiedSchemaSqliteOps) {
                discreteOps.add(new DiscreteOpsSqlRegistry.DiscreteOp(event.uid(),
                        event.packageName(), event.attributionTag(),
                        event.deviceId(), event.opCode(), event.opFlags(),
                        event.attributionFlags(),
                        event.uidState(), event.attributionChainId(),
                        event.accessTimeMillis(),
                        event.durationMillis()));
            }
            DiscreteOpsXmlRegistry.DiscreteOps xmlOps = getXmlDiscreteOps(discreteOps);
            targetRegistry.migrateDiscreteAppOpHistory(xmlOps);
            if (!sourceRegistry.deleteDatabase()) {
                Slog.w(LOG_TAG, "Couldn't delete appops unified sql database.");
            }
        } catch (Exception ex) {
            Slog.e(LOG_TAG, "rollbackFromUnifiedSchemaSqliteToXml failed.", ex);
            sourceRegistry.deleteDatabase();
        }
    }

    /**
     * rollback discrete ops from sqlite to xml.
     */
+15 −0
Original line number Diff line number Diff line
@@ -237,15 +237,21 @@ public class HistoricalRegistry implements HistoricalRegistryInterface {
                mHistoryRetentionMillis);
        // migrate discrete ops from xml or sqlite to unified-schema sqlite database.
        if (DiscreteOpsXmlRegistry.getDiscreteOpsDir().exists()) {
            Slog.i(TAG, "migrate discrete ops from xml to unified sqlite.");
            DiscreteOpsXmlRegistry xmlRegistry = new DiscreteOpsXmlRegistry(mContext);
            DiscreteOpsMigrationHelper.migrateFromXmlToUnifiedSchemaSqlite(
                    xmlRegistry, mShortIntervalHistoryHelper);
        } else if (DiscreteOpsDbHelper.getDatabaseFile().exists()) {
            Slog.i(TAG, "migrate discrete ops from sqlite to unified sqlite.");
            DiscreteOpsSqlRegistry sqlRegistry = new DiscreteOpsSqlRegistry(mContext);
            DiscreteOpsMigrationHelper.migrateFromSqliteToUnifiedSchemaSqlite(
                    sqlRegistry, mShortIntervalHistoryHelper);
        }

        if (LegacyHistoricalRegistry.historicalOpsDirExist()) {
            LegacyHistoricalRegistry.deleteHistoricalOpsDir();
        }

        mChainIdOffset = mShortIntervalHistoryHelper.getLargestAttributionChainId();

        // Set up listener for quantization, op flags or app ops list config for testing
@@ -686,6 +692,15 @@ public class HistoricalRegistry implements HistoricalRegistryInterface {
        mIsReady = true;
    }


    static boolean historicalOpsDbExist() {
        return getDatabaseFile(LONG_INTERVAL_DATABASE_FILE).exists();
    }

    static void deleteHistoricalOpsDb(Context context) {
        context.deleteDatabase(getDatabaseFile(LONG_INTERVAL_DATABASE_FILE).getAbsolutePath());
    }

    @NonNull
    // This is used during rollback in LegacyHistoricalRegistry, will be removed during flag
    // cleanup
+35 −8
Original line number Diff line number Diff line
@@ -262,32 +262,51 @@ final class LegacyHistoricalRegistry implements HistoricalRegistryInterface {
        if (Flags.enableSqliteAppopsAccesses()) {
            DiscreteOpsSqlRegistry sqlRegistry = (DiscreteOpsSqlRegistry) mDiscreteRegistry;
            if (DiscreteOpsXmlRegistry.getDiscreteOpsDir().exists()) {
                Slog.i(LOG_TAG, "migrate discrete ops from xml to sqlite.");
                DiscreteOpsXmlRegistry xmlRegistry = new DiscreteOpsXmlRegistry(mContext);
                xmlRegistry.systemReady();
                DiscreteOpsMigrationHelper.migrateFromXmlToSqlite(
                        xmlRegistry, sqlRegistry);
            } else if (HistoricalRegistry.getDiscreteOpsDatabaseFile().exists()) {
                // roll back from unified schema sqlite to discrete ops sqlite.
                AppOpHistoryHelper appOpHistoryHelper = new AppOpHistoryHelper(mContext,
                        HistoricalRegistry.getDiscreteOpsDatabaseFile(),
                        HistoricalRegistry.AggregationTimeWindow.SHORT,
                        HistoricalRegistry.getDiscreteOpsDatabaseVersion());
                appOpHistoryHelper.systemReady(
                        HistoricalRegistry.getDiscreteOpsQuantizationMillis(),
                        HistoricalRegistry.getAppOpsHistoryRetentionMillis());
                Slog.i(LOG_TAG, "rollback discrete ops from unified sqlite to sqlite.");
                AppOpHistoryHelper appOpHistoryHelper = getAppOpHistoryHelper();
                DiscreteOpsMigrationHelper.rollbackFromUnifiedSchemaSqliteToSqlite(
                        appOpHistoryHelper, sqlRegistry);
            }
        } else {
            if (DiscreteOpsDbHelper.getDatabaseFile().exists()) { // roll-back sqlite to xml
            if (HistoricalRegistry.getDiscreteOpsDatabaseFile().exists()) {
                Slog.i(LOG_TAG, "rollback discrete ops from unified sqlite to xml.");
                DiscreteOpsXmlRegistry xmlRegistry = new DiscreteOpsXmlRegistry(mContext);
                AppOpHistoryHelper appOpHistoryHelper = getAppOpHistoryHelper();
                DiscreteOpsMigrationHelper.rollbackFromUnifiedSchemaSqliteToXml(
                        appOpHistoryHelper, xmlRegistry);
                if (HistoricalRegistry.historicalOpsDbExist()) {
                    HistoricalRegistry.deleteHistoricalOpsDb(mContext);
                }
            } else if (DiscreteOpsDbHelper.getDatabaseFile().exists()) {
                Slog.i(LOG_TAG, "rollback discrete ops from sqlite to xml.");
                DiscreteOpsSqlRegistry sqlRegistry = new DiscreteOpsSqlRegistry(mContext);
                sqlRegistry.systemReady();
                DiscreteOpsXmlRegistry xmlRegistry = (DiscreteOpsXmlRegistry) mDiscreteRegistry;
                DiscreteOpsMigrationHelper.rollbackFromSqliteToXml(sqlRegistry, xmlRegistry);
            }


        }
    }

    private @NonNull AppOpHistoryHelper getAppOpHistoryHelper() {
        AppOpHistoryHelper appOpHistoryHelper = new AppOpHistoryHelper(mContext,
                HistoricalRegistry.getDiscreteOpsDatabaseFile(),
                HistoricalRegistry.AggregationTimeWindow.SHORT,
                HistoricalRegistry.getDiscreteOpsDatabaseVersion());
        appOpHistoryHelper.systemReady(
                HistoricalRegistry.getDiscreteOpsQuantizationMillis(),
                HistoricalRegistry.getAppOpsHistoryRetentionMillis());
        return appOpHistoryHelper;
    }

    private boolean isPersistenceInitializedMLocked() {
        return mPersistence != null;
    }
@@ -864,6 +883,14 @@ final class LegacyHistoricalRegistry implements HistoricalRegistryInterface {
        }
    }

    static boolean historicalOpsDirExist() {
        return Persistence.sHistoricalAppOpsDir.exists();
    }

    static void deleteHistoricalOpsDir() {
        Persistence.sHistoricalAppOpsDir.delete();
    }

    private static final class Persistence {
        private static final boolean DEBUG = false;

+32 −0
Original line number Diff line number Diff line
@@ -232,6 +232,38 @@ public class DiscreteOpsMigrationAndRollbackTest {
        assertThat(appOpHistoryHelper.getLargestAttributionChainId()).isEqualTo(RECORD_COUNT);
    }

    @Test
    public void rollbackFromUnifiedSchemaSqliteToXml() {
        // write to unified schema sqlite registry
        AppOpHistoryHelper appOpHistoryHelper = new AppOpHistoryHelper(mContext,
                mContext.getDatabasePath(DISCRETE_OPS_UNIFIED_SCHEMA_DB_NAME),
                HistoricalRegistry.AggregationTimeWindow.SHORT, 1);
        appOpHistoryHelper.systemReady(Duration.ofMinutes(1).toMillis(),
                Duration.ofDays(7).toMillis());
        for (int i = 1; i <= RECORD_COUNT; i++) {
            appOpHistoryHelper.incrementOpAccessedCount(AppOpsManager.OP_COARSE_LOCATION,
                    RECORD_COUNT + i, mContext.getPackageName(),
                    VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,  null,
                    UID_STATE_FOREGROUND, AppOpsManager.OP_FLAG_SELF, System.currentTimeMillis(),
                    ATTRIBUTION_FLAG_ACCESSOR, i, 1, false);
        }
        // flush records from cache to the database.
        appOpHistoryHelper.shutdown();
        assertThat(appOpHistoryHelper.getAppOpHistory().size()).isEqualTo(RECORD_COUNT);
        assertThat(appOpHistoryHelper.getLargestAttributionChainId()).isEqualTo(RECORD_COUNT);

        // now rollback to xml registry
        DiscreteOpsXmlRegistry xmlRegistry = new DiscreteOpsXmlRegistry(mLock, mMockDataDirectory);
        xmlRegistry.systemReady();
        DiscreteOpsMigrationHelper.rollbackFromUnifiedSchemaSqliteToXml(
                appOpHistoryHelper, xmlRegistry);
        DiscreteOpsXmlRegistry.DiscreteOps xmlOps = xmlRegistry.getAllDiscreteOps();

        assertThat(appOpHistoryHelper.getAppOpHistory()).isEmpty();
        assertThat(xmlOps.mLargestChainId).isEqualTo(RECORD_COUNT);
        assertThat(xmlOps.mUids.size()).isEqualTo(RECORD_COUNT);
    }

    private static class DiscreteOpBuilder {
        private int mUid;
        private String mPackageName;