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

Commit cf753aaf authored by mrulhania's avatar mrulhania Committed by Manjeet Rulhania
Browse files

Add SQLite database info to appops dumpsys

Also add app op records for privacy indicators
for last 1 hour. This data would be available
within bugreports, as it would be printed by
default.

Fix: 420930779
Test: manual dumpsys
Flag: android.permission.flags.enable_all_sqlite_appops_accesses

Change-Id: I1d0a7540a057e849ac04ae6e6e1e81fc41414ba9
parent 2ab4238b
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -238,11 +238,31 @@ class AppOpHistoryDbHelper extends SQLiteOpenHelper {
                db.endTransaction();
            }
        } catch (SQLiteException exception) {
            Slog.e(LOG_TAG, "Error reading attribution chain id", exception);
            Slog.e(LOG_TAG, "Error reading chain id " + mDatabaseFile.getName(), exception);
        }
        return chainId;
    }

    long getTotalRecordsCount() {
        long count = 0;
        try {
            SQLiteDatabase db = getReadableDatabase();
            db.beginTransactionReadOnly();
            try (SQLiteRawStatement statement = db.createRawStatement(
                    AppOpHistoryTable.SELECT_RECORDS_COUNT)) {
                if (statement.step()) {
                    count = statement.getColumnLong(0);
                }
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        } catch (SQLiteException exception) {
            Slog.e(LOG_TAG, "Error reading records count " + mDatabaseFile.getName(), exception);
        }
        return count;
    }

    @VisibleForTesting
    List<AggregatedAppOpAccessEvent> getAppOpHistory() {
        List<AggregatedAppOpAccessEvent> results = new ArrayList<>();
+16 −15
Original line number Diff line number Diff line
@@ -309,6 +309,10 @@ public class AppOpHistoryHelper {
                SQLITE_APP_OP_EVENT_REPORTED__WRITE_TYPE__WRITE_MIGRATION);
    }

    long getTotalRecordsCount() {
        return mDbHelper.getTotalRecordsCount();
    }

    @VisibleForTesting
    List<AggregatedAppOpAccessEvent> getAppOpHistory() {
        List<AggregatedAppOpAccessEvent> ops = new ArrayList<>();
@@ -364,29 +368,24 @@ public class AppOpHistoryHelper {
        return chains;
    }

    void dump(PrintWriter pw, int filterUid,
            @Nullable String filterPackage, @Nullable String filterAttributionTag, int filterOp,
    void dump(long beginTimeMillis, long endTimeMillis, PrintWriter pw, int filterUid,
            @Nullable String filterPackage, @Nullable String filterAttributionTag, IntArray opCodes,
            @AppOpsManager.HistoricalOpsRequestFilter int filter, @NonNull SimpleDateFormat sdf,
            @NonNull Date date, int limit) {
        // flush caches to the database
        insertAppOpHistory(mCache.evictAll(),
                SQLITE_APP_OP_EVENT_REPORTED__WRITE_TYPE__WRITE_READ);
        long currentTime = System.currentTimeMillis();
        long beginTimeMillis = discretizeTimestamp(currentTime - mHistoryRetentionMillis);
        IntArray opCodes = new IntArray();
        if ((filter & AppOpsManager.FILTER_BY_OP_NAMES) != 0
                && filterOp != AppOpsManager.OP_NONE) {
            opCodes.add(filterOp);
        }
        beginTimeMillis = discretizeTimestamp(beginTimeMillis);

        List<AggregatedAppOpAccessEvent> appOpHistoryAccesses = mDbHelper.getAppOpHistory(
                filter, beginTimeMillis, currentTime, filterUid, filterPackage,
                filter, beginTimeMillis, endTimeMillis, filterUid, filterPackage,
                filterAttributionTag, opCodes, AppOpsManager.OP_FLAGS_ALL, limit,
                AppOpHistoryTable.Columns.ACCESS_TIME, false);

        pw.println();
        pw.println("UID|PACKAGE_NAME|DEVICE_ID|OP_NAME|ATTRIBUTION_TAG|UID_STATE|OP_FLAGS|"
                + "ACCESS_TIME|ACCESS_COUNTS|REJECT_COUNTS|DURATION");
        pw.println("UID|PACKAGE_NAME|DEVICE_ID|OP_NAME|ATTRIBUTION_TAG|ACCESS_TIME|ACCESS_COUNTS"
                + "|REJECT_COUNTS|DURATION|UID_STATE|OP_FLAGS"
                + "|ATTRIBUTION_CHAIN_ID|ATTRIBUTION_FLAGS");
        for (AggregatedAppOpAccessEvent aggAppOpAccess : appOpHistoryAccesses) {
            date.setTime(aggAppOpAccess.accessTimeMillis());
            pw.println(aggAppOpAccess.uid() + "|"
@@ -394,12 +393,14 @@ public class AppOpHistoryHelper {
                    + aggAppOpAccess.deviceId() + "|"
                    + AppOpsManager.opToName(aggAppOpAccess.opCode()) + "|"
                    + aggAppOpAccess.attributionTag() + "|"
                    + getUidStateName(aggAppOpAccess.uidState()) + "|"
                    + flagsToString(aggAppOpAccess.opFlags()) + "|"
                    + sdf.format(date) + "|"
                    + aggAppOpAccess.totalAccessCount() + "|"
                    + aggAppOpAccess.totalRejectCount() + "|"
                    + aggAppOpAccess.durationMillis());
                    + aggAppOpAccess.totalDurationMillis() + "|"
                    + getUidStateName(aggAppOpAccess.uidState()) + "|"
                    + flagsToString(aggAppOpAccess.opFlags()) + "|"
                    + aggAppOpAccess.attributionChainId() + "|"
                    + aggAppOpAccess.attributionFlags());
        }
        pw.println();
    }
+2 −0
Original line number Diff line number Diff line
@@ -167,6 +167,8 @@ final class AppOpHistoryTable {
    static final String SELECT_MAX_ATTRIBUTION_CHAIN_ID = "SELECT MAX(" + Columns.CHAIN_ID + ")"
            + " FROM " + TABLE_NAME;

    static final String SELECT_RECORDS_COUNT = "SELECT COUNT(1) FROM " + TABLE_NAME;

    // Index on access time
    static final String CREATE_INDEX_SQL = "CREATE INDEX IF NOT EXISTS "
            + INDEX_APP_OP + " ON " + TABLE_NAME
+4 −5
Original line number Diff line number Diff line
@@ -6271,7 +6271,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        boolean dumpHistory = false;
        boolean includeDiscreteOps = false;
        boolean dumpUidStateChangeLogs = false;
        int historyLimit = 10;
        int historyLimit = 100;
        @HistoricalOpsRequestFilter int dumpFilter = 0;
        boolean dumpAll = false;

@@ -6762,10 +6762,9 @@ public class AppOpsService extends IAppOpsService.Stub {
        }

        if (Flags.enableAllSqliteAppopsAccesses()) {
            if (dumpHistory && !dumpWatchers) {
            mHistoricalRegistry.dump("", pw, dumpUid, dumpPackage, dumpAttributionTag,
                        dumpOp, dumpFilter, sdf, date, includeDiscreteOps, historyLimit);
            }
                    dumpOp, dumpFilter, sdf, date, includeDiscreteOps, historyLimit,
                    dumpHistory && !dumpWatchers);
        } else {
            // Must not hold the appops lock
            if (dumpHistory && !dumpWatchers) {
+52 −5
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.os.RemoteCallback;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -378,20 +379,66 @@ public class HistoricalRegistry implements HistoricalRegistryInterface {
    public void dump(String prefix, PrintWriter pw, int filterUid, @Nullable String filterPackage,
            @Nullable String filterAttributionTag, int filterOp, int filter,
            @NonNull SimpleDateFormat sdf, @NonNull Date date, boolean includeDiscreteOps,
            int limit) {
            int limit, boolean dumpHistory) {
        pw.println();
        pw.print(prefix);
        pw.print("History:");
        pw.print("  mode=");
        pw.println(AppOpsManager.historicalModeToString(mMode));

        long shortIntervalMinute = Duration.ofMillis(mShortIntervalQuantizationMillis).toMinutes();
        long longIntervalMinute = Duration.ofMillis(mLongIntervalQuantizationMillis).toMinutes();
        pw.print("SHORT_INTERVAL(Aggregation Bucket)=");
        pw.print(shortIntervalMinute + " Minute");
        pw.print(", LONG_INTERVAL(Aggregation Bucket)=");
        pw.println(longIntervalMinute + " Minutes");

        pw.print("Database size(bytes): SHORT_INTERVAL=");
        pw.print(getDatabaseFile(SHORT_INTERVAL_DATABASE_FILE).length());
        pw.print(", LONG_INTERVAL=");
        pw.println(getDatabaseFile(LONG_INTERVAL_DATABASE_FILE).length());

        pw.print("Database Total records: SHORT_INTERVAL=");
        pw.print(mShortIntervalHistoryHelper.getTotalRecordsCount());
        pw.print(", LONG_INTERVAL=");
        pw.println(mLongIntervalHistoryHelper.getTotalRecordsCount());
        IntArray opCodes = new IntArray();
        long endTimeMillis = System.currentTimeMillis();
        if (!dumpHistory && !includeDiscreteOps) {
            filter = AppOpsManager.FILTER_BY_OP_NAMES;
            // print privacy indicator records for last 1 hour (or up to 500 records)
            long beginTimeMillis = endTimeMillis - Duration.ofHours(1).toMillis();
            opCodes.add(OP_CAMERA);
            opCodes.add(OP_PHONE_CALL_CAMERA);

            opCodes.add(OP_RECORD_AUDIO);
            opCodes.add(OP_PHONE_CALL_MICROPHONE);
            opCodes.add(OP_RECEIVE_AMBIENT_TRIGGER_AUDIO);
            opCodes.add(OP_RECEIVE_SANDBOX_TRIGGER_AUDIO);

            opCodes.add(OP_FINE_LOCATION);
            opCodes.add(OP_COARSE_LOCATION);
            opCodes.add(OP_EMERGENCY_LOCATION);
            pw.println("----Location, Microphone, and Camera App Ops (Last 1 Hour)----");
            mShortIntervalHistoryHelper.dump(beginTimeMillis, endTimeMillis, pw,
                    Process.INVALID_UID, null, null, opCodes, filter,
                    sdf, date, 500);
            return;
        }

        if ((filter & AppOpsManager.FILTER_BY_OP_NAMES) != 0
                && filterOp != AppOpsManager.OP_NONE) {
            opCodes.add(filterOp);
        }
        long beginTimeMillis = endTimeMillis - mHistoryRetentionMillis;
        if (includeDiscreteOps) {
            pw.println("------------Discrete App Ops-------------");
            mShortIntervalHistoryHelper.dump(pw, filterUid, filterPackage,
                    filterAttributionTag, filterOp, filter, sdf, date, limit);
            mShortIntervalHistoryHelper.dump(beginTimeMillis, endTimeMillis, pw, filterUid,
                    filterPackage, filterAttributionTag, opCodes, filter, sdf, date, limit);
        } else {
            pw.println("------------Aggregated App Ops-------------");
            mLongIntervalHistoryHelper.dump(pw, filterUid, filterPackage,
                    filterAttributionTag, filterOp, filter, sdf, date, limit);
            mLongIntervalHistoryHelper.dump(beginTimeMillis, endTimeMillis, pw, filterUid,
                    filterPackage, filterAttributionTag, opCodes, filter, sdf, date, limit);
        }
    }

Loading