Loading cmds/statsd/src/atoms.proto +47 −1 Original line number Diff line number Diff line Loading @@ -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"]; Loading Loading @@ -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. Loading Loading @@ -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). Loading services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +81 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -550,6 +552,7 @@ public class StatsPullAtomService extends SystemService { registerAppsOnExternalStorageInfo(); registerFaceSettings(); registerAppOps(); registerAppFeaturesOps(); registerRuntimeAppOpAccessMessage(); registerNotificationRemoteViews(); registerDangerousPermissionState(); Loading Loading @@ -2843,7 +2846,6 @@ public class StatsPullAtomService extends SystemService { BackgroundThread.getExecutor(), mStatsCallbackImpl ); } private void registerRuntimeAppOpAccessMessage() { Loading @@ -2854,7 +2856,6 @@ public class StatsPullAtomService extends SystemService { BackgroundThread.getExecutor(), mStatsCallbackImpl ); } int pullAppOps(int atomTag, List<StatsEvent> pulledData) { Loading Loading @@ -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 { Loading Loading
cmds/statsd/src/atoms.proto +47 −1 Original line number Diff line number Diff line Loading @@ -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"]; Loading Loading @@ -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. Loading Loading @@ -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). Loading
services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +81 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -550,6 +552,7 @@ public class StatsPullAtomService extends SystemService { registerAppsOnExternalStorageInfo(); registerFaceSettings(); registerAppOps(); registerAppFeaturesOps(); registerRuntimeAppOpAccessMessage(); registerNotificationRemoteViews(); registerDangerousPermissionState(); Loading Loading @@ -2843,7 +2846,6 @@ public class StatsPullAtomService extends SystemService { BackgroundThread.getExecutor(), mStatsCallbackImpl ); } private void registerRuntimeAppOpAccessMessage() { Loading @@ -2854,7 +2856,6 @@ public class StatsPullAtomService extends SystemService { BackgroundThread.getExecutor(), mStatsCallbackImpl ); } int pullAppOps(int atomTag, List<StatsEvent> pulledData) { Loading Loading @@ -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 { Loading