From cd95d4613f8d14279671860f63d19aa8126d3248 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 25 Apr 2019 17:09:45 +0200 Subject: Atom and puller for historical AppOps. This atom contains information about historical AppOps performed by applications. Bug: 128925078 Test: builds adb shell cmd stats pull-source 10060 Change-Id: Iaaec0987712779e2062139d3ad0e2d4544d4d45f --- cmds/statsd/src/atoms.proto | 39 ++++++++++++++ cmds/statsd/src/external/StatsPullerManager.cpp | 3 ++ .../server/stats/StatsCompanionService.java | 60 ++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index b9a4b52d6c48..474c644fcc4d 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -363,6 +363,7 @@ message Atom { AppsOnExternalStorageInfo apps_on_external_storage_info = 10057; FaceSettings face_settings = 10058; CoolingDevice cooling_device = 10059; + AppOps app_ops = 10060; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -6339,3 +6340,41 @@ message GarageModeInfo { // Whether GarageMode is entered. optional bool is_garage_mode = 1; } + +/** + * Historical app ops data per package. + */ +message AppOps { + // Uid of the package requesting the op + optional int32 uid = 1 [(is_uid) = true]; + + // Nmae of the package performing the op + optional string package_name = 2; + + // operation id; maps to the OP_* constants in AppOpsManager.java + optional int32 op_id = 3; + + // 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 = 4; + + // 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 = 5; + + // 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 = 6; + + // 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 = 7; + + // 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 = 8; + + // 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 = 9; +} diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 2ffe18e20c24..914d60d3daca 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -260,6 +260,9 @@ std::map StatsPullerManager::kAllPullAtomInfo = { // Face Settings {android::util::FACE_SETTINGS, {.puller = new StatsCompanionServicePuller(android::util::FACE_SETTINGS)}}, + // App ops + {android::util::APP_OPS, + {.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}}, }; StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 1edb93a0cdb9..7d0da68a0750 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -15,6 +15,7 @@ */ package com.android.server.stats; +import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.os.Process.getPidsForCommands; @@ -33,6 +34,11 @@ import android.annotation.Nullable; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.AlarmManager.OnAlarmListener; +import android.app.AppOpsManager; +import android.app.AppOpsManager.HistoricalOps; +import android.app.AppOpsManager.HistoricalOpsRequest; +import android.app.AppOpsManager.HistoricalPackageOps; +import android.app.AppOpsManager.HistoricalUidOps; import android.app.ProcessMemoryHighWaterMark; import android.app.ProcessMemoryState; import android.app.StatsManager; @@ -146,6 +152,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -154,6 +162,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -1941,6 +1950,53 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } + private void pullAppOps(long elapsedNanos, final long wallClockNanos, + List pulledData) { + long token = Binder.clearCallingIdentity(); + try { + AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); + + CompletableFuture ops = new CompletableFuture<>(); + HistoricalOpsRequest histOpsRequest = + new HistoricalOpsRequest.Builder( + Instant.now().minus(1, ChronoUnit.HOURS).toEpochMilli(), + Long.MAX_VALUE).build(); + appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete); + + HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS, + TimeUnit.MILLISECONDS); + + StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.APP_OPS, elapsedNanos, + wallClockNanos); + + 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 opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) { + final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx); + e.writeInt(uid); + e.writeString(packageOps.getPackageName()); + e.writeInt(op.getOpCode()); + e.writeLong(op.getForegroundAccessCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getForegroundRejectCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); + e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_ALL_TRUSTED)); + pulledData.add(e); + } + } + } + } catch (Throwable t) { + Log.e(TAG, "Could not read appops", t); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** * Add a RoleHolder atom for each package that holds a role. * @@ -2331,6 +2387,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { pullFaceSettings(tagId, elapsedNanos, wallClockNanos, ret); break; } + case StatsLog.APP_OPS: { + pullAppOps(elapsedNanos, wallClockNanos, ret); + break; + } default: Slog.w(TAG, "No such tagId data as " + tagId); return null; -- cgit v1.2.3-59-g8ed1b