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

Commit 53aa8b8d authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Add atom and puller for AppOps with FeatureIds" into rvc-dev am: fd2f367d

Change-Id: Idee18668f7021a8f5d2945356d7d5f75bf32dbcc
parents ae74c70a fd2f367d
Loading
Loading
Loading
Loading
+47 −1
Original line number Diff line number Diff line
@@ -397,7 +397,7 @@ message Atom {
    }

    // Pulled events will start at field 10000.
    // Next: 10075
    // Next: 10076
    oneof pulled {
        WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
        WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -479,6 +479,7 @@ message Atom {
        PackageNotificationChannelGroupPreferences package_notification_channel_group_preferences =
                10073 [(module) = "framework"];
        GnssStats gnss_stats = 10074 [(module) = "framework"];
        AppFeaturesOps app_features_ops = 10075 [(module) = "framework"];
    }

    // DO NOT USE field numbers above 100,000 in AOSP.
@@ -7547,6 +7548,51 @@ message AppOps {
    optional bool is_runtime_permission = 10;
}

/**
 * Historical app ops data per package and features.
 */
message AppFeaturesOps {
    // Uid of the package requesting the op
    optional int32 uid = 1 [(is_uid) = true];

    // Name of the package performing the op
    optional string package_name = 2;

    // feature id; provided by developer when accessing related API, limited at 50 chars by API.
    // Features must be provided through manifest using <feature> tag available in R and above.
    optional string feature_id = 3;

    // operation id; maps to the OPSTR_* constants in AppOpsManager.java
    optional string op = 4;

    // The number of times the op was granted while the app was in the
    // foreground (only for trusted requests)
    optional int64 trusted_foreground_granted_count = 5;

    // The number of times the op was granted while the app was in the
    // background (only for trusted requests)
    optional int64 trusted_background_granted_count = 6;

    // The number of times the op was rejected while the app was in the
    // foreground (only for trusted requests)
    optional int64 trusted_foreground_rejected_count = 7;

    // The number of times the op was rejected while the app was in the
    // background (only for trusted requests)
    optional int64 trusted_background_rejected_count = 8;

    // For long-running operations, total duration of the operation
    // while the app was in the foreground (only for trusted requests)
    optional int64 trusted_foreground_duration_millis = 9;

    // For long-running operations, total duration of the operation
    // while the app was in the background (only for trusted requests)
    optional int64 trusted_background_duration_millis = 10;

    // Whether AppOps is guarded by Runtime permission
    optional bool is_runtime_permission = 11;
}

/**
 * Location Manager API Usage information(e.g. API under usage,
 * API call's parameters).
+81 −2
Original line number Diff line number Diff line
@@ -395,6 +395,8 @@ public class StatsPullAtomService extends SystemService {
                    case FrameworkStatsLog.BATTERY_VOLTAGE:
                    case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
                        return pullHealthHal(atomTag, data);
                    case FrameworkStatsLog.APP_FEATURES_OPS:
                        return pullAppFeaturesOps(atomTag, data);
                    default:
                        throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
                }
@@ -550,6 +552,7 @@ public class StatsPullAtomService extends SystemService {
        registerAppsOnExternalStorageInfo();
        registerFaceSettings();
        registerAppOps();
        registerAppFeaturesOps();
        registerRuntimeAppOpAccessMessage();
        registerNotificationRemoteViews();
        registerDangerousPermissionState();
@@ -2843,7 +2846,6 @@ public class StatsPullAtomService extends SystemService {
                BackgroundThread.getExecutor(),
                mStatsCallbackImpl
        );

    }

    private void registerRuntimeAppOpAccessMessage() {
@@ -2854,7 +2856,6 @@ public class StatsPullAtomService extends SystemService {
                BackgroundThread.getExecutor(),
                mStatsCallbackImpl
        );

    }

    int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
@@ -2917,6 +2918,84 @@ public class StatsPullAtomService extends SystemService {
        return StatsManager.PULL_SUCCESS;
    }

    private void registerAppFeaturesOps() {
        int tagId = FrameworkStatsLog.APP_FEATURES_OPS;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                BackgroundThread.getExecutor(),
                mStatsCallbackImpl
        );
    }

    int pullAppFeaturesOps(int atomTag, List<StatsEvent> pulledData) {
        final long token = Binder.clearCallingIdentity();
        try {
            AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);

            CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
            HistoricalOpsRequest histOpsRequest =
                    new HistoricalOpsRequest.Builder(0, Long.MAX_VALUE).setFlags(
                            OP_FLAGS_PULLED).build();
            appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete);

            HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
                    TimeUnit.MILLISECONDS);

            for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
                final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
                final int uid = uidOps.getUid();
                for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
                    final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
                    for (int featureIdx = 0; featureIdx < packageOps.getFeatureCount();
                            featureIdx++) {
                        final AppOpsManager.HistoricalFeatureOps featureOps =
                                packageOps.getFeatureOpsAt(featureIdx);
                        for (int opIdx = 0; opIdx < featureOps.getOpCount(); opIdx++) {
                            final AppOpsManager.HistoricalOp op = featureOps.getOpAt(opIdx);
                            StatsEvent.Builder e = StatsEvent.newBuilder();
                            e.setAtomId(atomTag);
                            e.writeInt(uid);
                            e.writeString(packageOps.getPackageName());
                            e.writeString(featureOps.getFeatureId());
                            e.writeString(op.getOpName());
                            e.writeLong(op.getForegroundAccessCount(OP_FLAGS_PULLED));
                            e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_PULLED));
                            e.writeLong(op.getForegroundRejectCount(OP_FLAGS_PULLED));
                            e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_PULLED));
                            e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_PULLED));
                            e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_PULLED));

                            String perm = AppOpsManager.opToPermission(op.getOpCode());
                            if (perm == null) {
                                e.writeBoolean(false);
                            } else {
                                PermissionInfo permInfo;
                                try {
                                    permInfo = mContext.getPackageManager().getPermissionInfo(perm,
                                            0);
                                    e.writeBoolean(
                                            permInfo.getProtection() == PROTECTION_DANGEROUS);
                                } catch (PackageManager.NameNotFoundException exception) {
                                    e.writeBoolean(false);
                                }
                            }
                            pulledData.add(e.build());
                        }

                    }
                }
            }
        } catch (Throwable t) {
            // TODO: catch exceptions at a more granular level
            Slog.e(TAG, "Could not read appops", t);
            return StatsManager.PULL_SKIP;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        return StatsManager.PULL_SUCCESS;
    }

    int pullRuntimeAppOpAccessMessage(int atomTag, List<StatsEvent> pulledData) {
        final long token = Binder.clearCallingIdentity();
        try {