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

Commit fd2f367d authored by Stanislav Zholnin's avatar Stanislav Zholnin Committed by Android (Google) Code Review
Browse files

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

parents 9fa3a870 7dcc51dc
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 {