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

Commit bc487b57 authored by Chris Wren's avatar Chris Wren
Browse files

track and report packages with undecorated remoteviews

print query results with:
  adb shell dumpsys notification --remote-view-stats

test the pulled atom with:
  make statsd_testdrive
  ./out/host/linux-x86/bin/statsd_testdrive 10066

Bug: 144855217
Test: atest frameworks/base/services/tests/uiservicestests/src/com/android/server/notification
Change-Id: I6dcc9871f78298a8b213a051223c7316f8feefc5
Merged-In: I773378fc7cfb47a9f9c7495404ddafa63f39cfaf
parent 2c5bd63e
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -325,7 +325,7 @@ message Atom {
    }

    // Pulled events will start at field 10000.
    // Next: 10062
    // Next: 10067
    oneof pulled {
        WifiBytesTransfer wifi_bytes_transfer = 10000;
        WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -390,6 +390,7 @@ message Atom {
        AppOps app_ops = 10060;
        ProcessSystemIonHeapSize process_system_ion_heap_size = 10061;
        VmsClientStats vms_client_stats = 10065;
        NotificationRemoteViews notification_remote_views = 10066;
    }

    // DO NOT USE field numbers above 100,000 in AOSP.
@@ -4751,6 +4752,24 @@ message ProcStatsPkgProc {
    optional ProcessStatsSectionProto proc_stats_section = 1;
}

// Next Tag: 2
message PackageRemoteViewInfoProto {
    optional string package_name = 1;
    // add per-package additional info here (like channels)
}

// Next Tag: 2
message NotificationRemoteViewsProto {
    repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
}

/**
 * Pulled from NotificationManagerService.java
 */
message NotificationRemoteViews {
    optional NotificationRemoteViewsProto notification_remote_views = 1;
}

message PowerProfileProto {
    optional double cpu_suspend = 1;

+3 −0
Original line number Diff line number Diff line
@@ -271,6 +271,9 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
        {android::util::VMS_CLIENT_STATS,
         {.additiveFields = {5, 6, 7, 8, 9, 10},
          .puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
        // NotiifcationRemoteViews.
        {android::util::NOTIFICATION_REMOTE_VIEWS,
         {.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}},
};

StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
+2 −0
Original line number Diff line number Diff line
@@ -202,4 +202,6 @@ interface INotificationManager

    void setPrivateNotificationsAllowed(boolean allow);
    boolean getPrivateNotificationsAllowed();

    long pullStats(long startNs, int report, boolean doAgg, out List<ParcelFileDescriptor> stats);
}
+11 −0
Original line number Diff line number Diff line
@@ -264,3 +264,14 @@ message ZenPolicyProto {
    optional Sender priority_calls = 16;
    optional Sender priority_messages = 17;
}

// Next Tag: 2
message PackageRemoteViewInfoProto {
    optional string package_name = 1;
    // add per-package additional info here (like channels)
}

// Next Tag: 2
message NotificationRemoteViewsProto {
    repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
}
 No newline at end of file
+67 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ import android.os.IDeviceIdleController;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -281,6 +282,9 @@ public class NotificationManagerService extends SystemService {
    public static final boolean ENABLE_CHILD_NOTIFICATIONS
            = SystemProperties.getBoolean("debug.child_notifs", true);

    // pullStats report request: undecorated remote view stats
    public static final int REPORT_REMOTE_VIEWS = 0x01;

    static final boolean DEBUG_INTERRUPTIVENESS = SystemProperties.getBoolean(
            "debug.notification.interruptiveness", false);

@@ -3734,6 +3738,8 @@ public class NotificationManagerService extends SystemService {
            try {
                if (filter.stats) {
                    dumpJson(pw, filter);
                } else if (filter.rvStats) {
                    dumpRemoteViewStats(pw, filter);
                } else if (filter.proto) {
                    dumpProto(fd, filter);
                } else if (filter.criticalPriority) {
@@ -4210,6 +4216,49 @@ public class NotificationManagerService extends SystemService {
            new NotificationShellCmd(NotificationManagerService.this)
                    .exec(this, in, out, err, args, callback, resultReceiver);
        }

        /**
         * Get stats committed after startNs
         *
         * @param startNs Report stats committed after this time in nanoseconds.
         * @param report  Indicatess which section to include in the stats.
         * @param doAgg   Whether to aggregate the stats or keep them separated.
         * @param out   List of protos of individual commits or one representing the
         *                aggregate.
         * @return the report time in nanoseconds, or 0 on error.
         */
        @Override
        public long pullStats(long startNs, int report, boolean doAgg,
                List<ParcelFileDescriptor> out) {
            checkCallerIsSystemOrShell();
            long startMs = TimeUnit.MILLISECONDS.convert(startNs, TimeUnit.NANOSECONDS);

            final long identity = Binder.clearCallingIdentity();
            try {
                switch (report) {
                    case REPORT_REMOTE_VIEWS:
                        Slog.e(TAG, "pullStats REPORT_REMOTE_VIEWS from: "
                                + startMs + "  wtih " + doAgg);
                        PulledStats stats = mUsageStats.remoteViewStats(startMs, doAgg);
                        if (stats != null) {
                            out.add(stats.toParcelFileDescriptor(report));
                            Slog.e(TAG, "exiting pullStats with: " + out.size());
                            long endNs = TimeUnit.NANOSECONDS
                                    .convert(stats.endTimeMs(), TimeUnit.MILLISECONDS);
                            return endNs;
                        }
                        Slog.e(TAG, "null stats for: " + report);
                }
            } catch (IOException e) {

                Slog.e(TAG, "exiting pullStats: on error", e);
                return 0;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
            Slog.e(TAG, "exiting pullStats: bad request");
            return 0;
        }
    };

    @VisibleForTesting
@@ -4425,6 +4474,15 @@ public class NotificationManagerService extends SystemService {
        pw.println(dump);
    }

    private void dumpRemoteViewStats(PrintWriter pw, @NonNull DumpFilter filter) {
        PulledStats stats = mUsageStats.remoteViewStats(filter.since, true);
        if (stats == null) {
            pw.println("no remote view stats reported.");
            return;
        }
        stats.dump(REPORT_REMOTE_VIEWS, pw, filter);
    }

    private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter) {
        final ProtoOutputStream proto = new ProtoOutputStream(fd);
        synchronized (mNotificationLock) {
@@ -8559,6 +8617,7 @@ public class NotificationManagerService extends SystemService {
        public boolean zen;
        public long since;
        public boolean stats;
        public boolean rvStats;
        public boolean redact = true;
        public boolean proto = false;
        public boolean criticalPriority = false;
@@ -8594,6 +8653,14 @@ public class NotificationManagerService extends SystemService {
                    } else {
                        filter.since = 0;
                    }
                } else if ("--remote-view-stats".equals(a)) {
                    filter.rvStats = true;
                    if (ai < args.length-1) {
                        ai++;
                        filter.since = Long.parseLong(args[ai]);
                    } else {
                        filter.since = 0;
                    }
                } else if (PRIORITY_ARG.equals(a)) {
                    // Bugreport will call the service twice with priority arguments, first to dump
                    // critical sections and then non critical ones. Set approriate filters
Loading