Add atoms for publishing ban state.
This will replace the current dumpsys ban state logging from Android
Sessions.
Bug: 146158683
Test: manually ran adb shell cmd stats pull-source 10071/10072/10073.
Change-Id: I4123180a139efefa9ff4774bab87ce7c0ad25f21
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5e2dbf3..d0e50ee 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -395,7 +395,7 @@
}
// Pulled events will start at field 10000.
- // Next: 10071
+ // Next: 10074
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -470,6 +470,12 @@
GraphicsStats graphics_stats = 10068;
RuntimeAppOpAccess runtime_app_op_access = 10069 [(module) = "framework"];
IonHeapSize ion_heap_size = 10070 [(module) = "framework"];
+ PackageNotificationPreferences package_notification_preferences =
+ 10071 [(module) = "framework"];
+ PackageNotificationChannelPreferences package_notification_channel_preferences =
+ 10072 [(module) = "framework"];
+ PackageNotificationChannelGroupPreferences package_notification_channel_group_preferences =
+ 10073 [(module) = "framework"];
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -5468,6 +5474,65 @@
optional NotificationRemoteViewsProto notification_remote_views = 1;
}
+/**
+ * Atom that contains a list of a package's preferences, pulled from NotificationManagerService.java
+ */
+message PackageNotificationPreferences {
+ // Uid under which the package is installed.
+ optional int32 uid = 1;
+ // Notification importance, which specifies when and how a notification is displayed.
+ // Specified under core/java/android/app/NotificationManager.java.
+ optional int32 importance = 2;
+ // Lockscreen visibility as set by the user.
+ optional int32 visibility = 3;
+ // Bitfield mask indicating what fields were locked by the user (see LockableAppfields in
+ // PreferencesHelper.java)
+ optional int32 user_locked_fields = 4;
+}
+
+/**
+ * Atom that contains a list of a package's channel preferences, pulled from
+ * NotificationManagerService.java.
+ */
+message PackageNotificationChannelPreferences {
+ // Uid under which the package is installed.
+ optional int32 uid = 1;
+ // Channel's ID. Should always be available.
+ optional string channel_id = 2;
+ // Channel's name. Should always be available.
+ optional string channel_name = 3;
+ // Channel's description. Optionally set by the channel creator.
+ optional string description = 4;
+ // Notification importance, which specifies when and how a notification is displayed. Specified
+ // under core/java/android/app/NotificationManager.java.
+ optional int32 importance = 5;
+ // Bitmask representing which fields have been set by the user. See field bitmask descriptions
+ // at core/java/android/app/NotificationChannel.java
+ optional int32 user_locked_fields = 6;
+ // Indicates if the channel was deleted by the app.
+ optional bool is_deleted = 7;
+}
+
+/**
+ * Atom that contains a list of a package's channel group preferences, pulled from
+ * NotificationManagerService.java.
+ */
+message PackageNotificationChannelGroupPreferences {
+ // Uid under which the package is installed.
+ optional int32 uid = 1;
+ // Channel Group's ID. Should always be available.
+ optional string group_id = 2;
+ // Channel Group's name. Should always be available.
+ optional string group_name = 3;
+ // Channel Group's description. Optionally set by group creator.
+ optional string description = 4;
+ // Indicates if notifications from this channel group are blocked.
+ optional bool is_blocked = 5;
+ // Bitmask representing which fields have been set by the user. See field bitmask descriptions
+ // at core/java/android/app/NotificationChannelGroup.java
+ optional int32 user_locked_fields = 6;
+}
+
message PowerProfileProto {
optional double cpu_suspend = 1;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ea77c36..5e69ab1 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -94,6 +94,9 @@
import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
@@ -129,6 +132,7 @@
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
+import android.app.StatsManager;
import android.app.StatusBarManager;
import android.app.UriGrantsManager;
import android.app.admin.DeviceAdminInfo;
@@ -220,6 +224,7 @@
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.StatsEvent;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;
import android.view.accessibility.AccessibilityEvent;
@@ -473,6 +478,8 @@
private AppOpsManager mAppOps;
private UsageStatsManagerInternal mAppUsageStats;
private DevicePolicyManagerInternal mDpm;
+ private StatsManager mStatsManager;
+ private StatsPullAtomCallbackImpl mPullAtomCallback;
private Archive mArchive;
@@ -1890,7 +1897,8 @@
ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am,
UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm,
IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal, AppOpsManager appOps,
- UserManager userManager, NotificationHistoryManager historyManager) {
+ UserManager userManager, NotificationHistoryManager historyManager,
+ StatsManager statsManager) {
mHandler = handler;
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
@@ -2050,6 +2058,7 @@
mStripRemoteViewsSizeBytes = getContext().getResources().getInteger(
com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
+ mStatsManager = statsManager;
}
@Override
@@ -2093,7 +2102,9 @@
LocalServices.getService(UriGrantsManagerInternal.class),
(AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE),
getContext().getSystemService(UserManager.class),
- new NotificationHistoryManager(getContext(), handler));
+ new NotificationHistoryManager(getContext(), handler),
+ mStatsManager = (StatsManager) getContext().getSystemService(
+ Context.STATS_MANAGER));
// register for various Intents
IntentFilter filter = new IntentFilter();
@@ -2168,6 +2179,57 @@
}
}
+ private void registerNotificationPreferencesPullers() {
+ mPullAtomCallback = new StatsPullAtomCallbackImpl();
+ mStatsManager.registerPullAtomCallback(
+ PACKAGE_NOTIFICATION_PREFERENCES,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ mPullAtomCallback
+ );
+ mStatsManager.registerPullAtomCallback(
+ PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ mPullAtomCallback
+ );
+ mStatsManager.registerPullAtomCallback(
+ PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ mPullAtomCallback
+ );
+ }
+
+ private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
+ @Override
+ public int onPullAtom(int atomTag, List<StatsEvent> data) {
+ switch (atomTag) {
+ case PACKAGE_NOTIFICATION_PREFERENCES:
+ case PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES:
+ case PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES:
+ return pullNotificationStates(atomTag, data);
+ default:
+ throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
+ }
+ }
+ }
+
+ private int pullNotificationStates(int atomTag, List<StatsEvent> data) {
+ switch(atomTag) {
+ case PACKAGE_NOTIFICATION_PREFERENCES:
+ mPreferencesHelper.pullPackagePreferencesStats(data);
+ break;
+ case PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES:
+ mPreferencesHelper.pullPackageChannelPreferencesStats(data);
+ break;
+ case PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES:
+ mPreferencesHelper.pullPackageChannelGroupPreferencesStats(data);
+ break;
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
private GroupHelper getGroupHelper() {
mAutoGroupAtCount =
getContext().getResources().getInteger(R.integer.config_autoGroupAtCount);
@@ -2246,6 +2308,7 @@
mRoleObserver.init();
mLauncherAppsService =
(LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE);
+ registerNotificationPreferencesPullers();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
// This observer will force an update when observe is called, causing us to
// bind to listener services.
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index a244c48..9f8362c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -20,6 +20,10 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
+import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -46,6 +50,7 @@
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
@@ -80,6 +85,10 @@
@VisibleForTesting
static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
+ private static final int NOTIFICATION_PREFERENCES_PULL_LIMIT = 1000;
+ private static final int NOTIFICATION_CHANNEL_PULL_LIMIT = 2000;
+ private static final int NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT = 1000;
+
@VisibleForTesting
static final String TAG_RANKING = "ranking";
private static final String TAG_PACKAGE = "package";
@@ -1682,6 +1691,88 @@
}
}
+ /**
+ * Fills out {@link PackageNotificationPreferences} proto and wraps it in a {@link StatsEvent}.
+ */
+ public void pullPackagePreferencesStats(List<StatsEvent> events) {
+ synchronized (mPackagePreferences) {
+ for (int i = 0; i < mPackagePreferences.size(); i++) {
+ if (i > NOTIFICATION_PREFERENCES_PULL_LIMIT) {
+ break;
+ }
+ StatsEvent.Builder event = StatsEvent.newBuilder()
+ .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES);
+ final PackagePreferences r = mPackagePreferences.valueAt(i);
+ event.writeInt(r.uid);
+ event.writeInt(r.importance);
+ event.writeInt(r.visibility);
+ event.writeInt(r.lockedAppFields);
+ events.add(event.build());
+ }
+ }
+ }
+
+ /**
+ * Fills out {@link PackageNotificationChannelPreferences} proto and wraps it in a
+ * {@link StatsEvent}.
+ */
+ public void pullPackageChannelPreferencesStats(List<StatsEvent> events) {
+ synchronized (mPackagePreferences) {
+ int totalChannelsPulled = 0;
+ for (int i = 0; i < mPackagePreferences.size(); i++) {
+ if (totalChannelsPulled > NOTIFICATION_CHANNEL_PULL_LIMIT) {
+ break;
+ }
+ final PackagePreferences r = mPackagePreferences.valueAt(i);
+ for (NotificationChannel channel : r.channels.values()) {
+ if (++totalChannelsPulled > NOTIFICATION_CHANNEL_PULL_LIMIT) {
+ break;
+ }
+ StatsEvent.Builder event = StatsEvent.newBuilder()
+ .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES);
+ event.writeInt(r.uid);
+ event.writeString(channel.getId());
+ event.writeString(channel.getName().toString());
+ event.writeString(channel.getDescription());
+ event.writeInt(channel.getImportance());
+ event.writeInt(channel.getUserLockedFields());
+ event.writeBoolean(channel.isDeleted());
+ events.add(event.build());
+ }
+ }
+ }
+ }
+
+ /**
+ * Fills out {@link PackageNotificationChannelGroupPreferences} proto and wraps it in a
+ * {@link StatsEvent}.
+ */
+ public void pullPackageChannelGroupPreferencesStats(List<StatsEvent> events) {
+ synchronized (mPackagePreferences) {
+ int totalGroupsPulled = 0;
+ for (int i = 0; i < mPackagePreferences.size(); i++) {
+ if (totalGroupsPulled > NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT) {
+ break;
+ }
+ final PackagePreferences r = mPackagePreferences.valueAt(i);
+ for (NotificationChannelGroup groupChannel : r.groups.values()) {
+ if (++totalGroupsPulled > NOTIFICATION_CHANNEL_GROUP_PULL_LIMIT) {
+ break;
+ }
+ StatsEvent.Builder event = StatsEvent.newBuilder()
+ .setAtomId(PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES);
+ event.writeInt(r.uid);
+ event.writeString(groupChannel.getId());
+ event.writeString(groupChannel.getName().toString());
+ event.writeString(groupChannel.getDescription());
+ event.writeBoolean(groupChannel.isBlocked());
+ event.writeInt(groupChannel.getUserLockedFields());
+ events.add(event.build());
+ }
+ }
+ }
+ }
+
public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
JSONObject ranking = new JSONObject();
JSONArray PackagePreferencess = new JSONArray();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9ec339d..53c27577 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -32,7 +32,6 @@
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
@@ -97,6 +96,7 @@
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
+import android.app.StatsManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.usage.UsageStatsManagerInternal;
import android.companion.ICompanionDeviceManager;
@@ -266,6 +266,8 @@
UserManager mUm;
@Mock
NotificationHistoryManager mHistoryManager;
+ @Mock
+ StatsManager mStatsManager;
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
1 << 30);
@@ -439,7 +441,7 @@
mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
mGroupHelper, mAm, mAppUsageStats,
mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
- mAppOpsManager, mUm, mHistoryManager);
+ mAppOpsManager, mUm, mHistoryManager, mStatsManager);
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mService.setAudioManager(mAudioManager);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 64a9804..27f72a1 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -35,6 +35,7 @@
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.IUriGrantsManager;
+import android.app.StatsManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.role.RoleManager;
import android.app.usage.UsageStatsManagerInternal;
@@ -142,7 +143,8 @@
mock(UsageStatsManagerInternal.class),
mock(DevicePolicyManagerInternal.class), mock(IUriGrantsManager.class),
mock(UriGrantsManagerInternal.class),
- mock(AppOpsManager.class), mUm, mock(NotificationHistoryManager.class));
+ mock(AppOpsManager.class), mUm, mock(NotificationHistoryManager.class),
+ mock(StatsManager.class));
} catch (SecurityException e) {
if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
throw e;