Merge "Add some recent broadcast and notification events to the dumpsys." into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2b49ffd640
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.usage;
|
||||
|
||||
import static android.app.ActivityManager.procStateToString;
|
||||
|
||||
import static com.android.server.usage.BroadcastResponseStatsTracker.NOTIFICATION_EVENT_TYPE_CANCELLED;
|
||||
import static com.android.server.usage.BroadcastResponseStatsTracker.NOTIFICATION_EVENT_TYPE_POSTED;
|
||||
import static com.android.server.usage.BroadcastResponseStatsTracker.NOTIFICATION_EVENT_TYPE_UPDATED;
|
||||
import static com.android.server.usage.BroadcastResponseStatsTracker.TAG;
|
||||
import static com.android.server.usage.UsageStatsService.DEBUG_RESPONSE_STATS;
|
||||
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.ProcessState;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.TimeUtils;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.RingBuffer;
|
||||
import com.android.server.usage.BroadcastResponseStatsTracker.NotificationEventType;
|
||||
|
||||
public class BroadcastResponseStatsLogger {
|
||||
|
||||
private static final int MAX_LOG_SIZE =
|
||||
ActivityManager.isLowRamDeviceStatic() ? 20 : 50;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final LogBuffer mBroadcastEventsBuffer = new LogBuffer(
|
||||
BroadcastEvent.class, MAX_LOG_SIZE);
|
||||
@GuardedBy("mLock")
|
||||
private final LogBuffer mNotificationEventsBuffer = new LogBuffer(
|
||||
NotificationEvent.class, MAX_LOG_SIZE);
|
||||
|
||||
void logBroadcastDispatchEvent(int sourceUid, @NonNull String targetPackage,
|
||||
UserHandle targetUser, long idForResponseEvent,
|
||||
@ElapsedRealtimeLong long timeStampMs, @ProcessState int targetUidProcessState) {
|
||||
synchronized (mLock) {
|
||||
if (DEBUG_RESPONSE_STATS) {
|
||||
Slog.d(TAG, getBroadcastDispatchEventLog(sourceUid, targetPackage,
|
||||
targetUser.getIdentifier(), idForResponseEvent, timeStampMs,
|
||||
targetUidProcessState));
|
||||
}
|
||||
mBroadcastEventsBuffer.logBroadcastDispatchEvent(sourceUid, targetPackage,
|
||||
targetUser, idForResponseEvent, timeStampMs, targetUidProcessState);
|
||||
}
|
||||
}
|
||||
|
||||
void logNotificationEvent(@NotificationEventType int event,
|
||||
@NonNull String packageName, UserHandle user, @ElapsedRealtimeLong long timestampMs) {
|
||||
synchronized (mLock) {
|
||||
if (DEBUG_RESPONSE_STATS) {
|
||||
Slog.d(TAG, getNotificationEventLog(event, packageName, user.getIdentifier(),
|
||||
timestampMs));
|
||||
}
|
||||
mNotificationEventsBuffer.logNotificationEvent(event, packageName, user, timestampMs);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpLogs(IndentingPrintWriter ipw) {
|
||||
synchronized (mLock) {
|
||||
ipw.println("Broadcast events (most recent first):");
|
||||
ipw.increaseIndent();
|
||||
mBroadcastEventsBuffer.reverseDump(ipw);
|
||||
ipw.decreaseIndent();
|
||||
|
||||
ipw.println();
|
||||
ipw.println("Notification events (most recent first):");
|
||||
ipw.increaseIndent();
|
||||
mNotificationEventsBuffer.reverseDump(ipw);
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LogBuffer<T extends Data> extends RingBuffer<T> {
|
||||
|
||||
LogBuffer(Class<T> classType, int capacity) {
|
||||
super(classType, capacity);
|
||||
}
|
||||
|
||||
void logBroadcastDispatchEvent(int sourceUid, @NonNull String targetPackage,
|
||||
UserHandle targetUser, long idForResponseEvent,
|
||||
@ElapsedRealtimeLong long timeStampMs, @ProcessState int targetUidProcessState) {
|
||||
final Data data = getNextSlot();
|
||||
if (data == null) return;
|
||||
|
||||
data.reset();
|
||||
final BroadcastEvent event = (BroadcastEvent) data;
|
||||
event.sourceUid = sourceUid;
|
||||
event.targetUserId = targetUser.getIdentifier();
|
||||
event.targetUidProcessState = targetUidProcessState;
|
||||
event.targetPackage = targetPackage;
|
||||
event.idForResponseEvent = idForResponseEvent;
|
||||
event.timestampMs = timeStampMs;
|
||||
}
|
||||
|
||||
void logNotificationEvent(@NotificationEventType int type,
|
||||
@NonNull String packageName, UserHandle user,
|
||||
@ElapsedRealtimeLong long timestampMs) {
|
||||
final Data data = getNextSlot();
|
||||
if (data == null) return;
|
||||
|
||||
data.reset();
|
||||
final NotificationEvent event = (NotificationEvent) data;
|
||||
event.type = type;
|
||||
event.packageName = packageName;
|
||||
event.userId = user.getIdentifier();
|
||||
event.timestampMs = timestampMs;
|
||||
}
|
||||
|
||||
public void reverseDump(IndentingPrintWriter pw) {
|
||||
final Data[] allData = toArray();
|
||||
for (int i = allData.length - 1; i >= 0; --i) {
|
||||
if (allData[i] == null) {
|
||||
continue;
|
||||
}
|
||||
pw.println(getContent(allData[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getContent(Data data) {
|
||||
return data.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String getBroadcastDispatchEventLog(int sourceUid, @NonNull String targetPackage,
|
||||
@UserIdInt int targetUserId, long idForResponseEvent,
|
||||
@ElapsedRealtimeLong long timestampMs, @ProcessState int targetUidProcState) {
|
||||
return TextUtils.formatSimple(
|
||||
"broadcast:%s; srcUid=%d, tgtPkg=%s, tgtUsr=%d, id=%d, state=%s",
|
||||
TimeUtils.formatDuration(timestampMs), sourceUid, targetPackage, targetUserId,
|
||||
idForResponseEvent, procStateToString(targetUidProcState));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String getNotificationEventLog(@NotificationEventType int event,
|
||||
@NonNull String packageName, @UserIdInt int userId,
|
||||
@ElapsedRealtimeLong long timestampMs) {
|
||||
return TextUtils.formatSimple("notification:%s; event=<%s>, pkg=%s, usr=%d",
|
||||
TimeUtils.formatDuration(timestampMs), notificationEventToString(event),
|
||||
packageName, userId);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String notificationEventToString(@NotificationEventType int event) {
|
||||
switch (event) {
|
||||
case NOTIFICATION_EVENT_TYPE_POSTED:
|
||||
return "posted";
|
||||
case NOTIFICATION_EVENT_TYPE_UPDATED:
|
||||
return "updated";
|
||||
case NOTIFICATION_EVENT_TYPE_CANCELLED:
|
||||
return "cancelled";
|
||||
default:
|
||||
return String.valueOf(event);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BroadcastEvent implements Data {
|
||||
public int sourceUid;
|
||||
public int targetUserId;
|
||||
public int targetUidProcessState;
|
||||
public String targetPackage;
|
||||
public long idForResponseEvent;
|
||||
public long timestampMs;
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
targetPackage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getBroadcastDispatchEventLog(sourceUid, targetPackage, targetUserId,
|
||||
idForResponseEvent, timestampMs, targetUidProcessState);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class NotificationEvent implements Data {
|
||||
public int type;
|
||||
public String packageName;
|
||||
public int userId;
|
||||
public long timestampMs;
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
packageName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNotificationEventLog(type, packageName, userId, timestampMs);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Data {
|
||||
void reset();
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
package com.android.server.usage;
|
||||
|
||||
import static android.app.ActivityManager.procStateToString;
|
||||
|
||||
import static com.android.server.usage.UsageStatsService.DEBUG_RESPONSE_STATS;
|
||||
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
@@ -29,11 +25,9 @@ import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManager.ProcessState;
|
||||
import android.app.usage.BroadcastResponseStats;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.LongSparseArray;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TimeUtils;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
@@ -44,19 +38,19 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class BroadcastResponseStatsTracker {
|
||||
private static final String TAG = "ResponseStatsTracker";
|
||||
static final String TAG = "ResponseStatsTracker";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = {"NOTIFICATION_EVENT"}, value = {
|
||||
NOTIFICATION_EVENT_POSTED,
|
||||
NOTIFICATION_EVENT_UPDATED,
|
||||
NOTIFICATION_EVENT_CANCELLED
|
||||
@IntDef(prefix = {"NOTIFICATION_EVENT_TYPE_"}, value = {
|
||||
NOTIFICATION_EVENT_TYPE_POSTED,
|
||||
NOTIFICATION_EVENT_TYPE_UPDATED,
|
||||
NOTIFICATION_EVENT_TYPE_CANCELLED
|
||||
})
|
||||
public @interface NotificationEvent {}
|
||||
public @interface NotificationEventType {}
|
||||
|
||||
private static final int NOTIFICATION_EVENT_POSTED = 0;
|
||||
private static final int NOTIFICATION_EVENT_UPDATED = 1;
|
||||
private static final int NOTIFICATION_EVENT_CANCELLED = 2;
|
||||
static final int NOTIFICATION_EVENT_TYPE_POSTED = 0;
|
||||
static final int NOTIFICATION_EVENT_TYPE_UPDATED = 1;
|
||||
static final int NOTIFICATION_EVENT_TYPE_CANCELLED = 2;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@@ -76,21 +70,19 @@ class BroadcastResponseStatsTracker {
|
||||
new SparseArray<>();
|
||||
|
||||
private AppStandbyInternal mAppStandby;
|
||||
private BroadcastResponseStatsLogger mLogger;
|
||||
|
||||
BroadcastResponseStatsTracker(@NonNull AppStandbyInternal appStandby) {
|
||||
mAppStandby = appStandby;
|
||||
mLogger = new BroadcastResponseStatsLogger();
|
||||
}
|
||||
|
||||
// TODO (206518114): Move all callbacks handling to a handler thread.
|
||||
void reportBroadcastDispatchEvent(int sourceUid, @NonNull String targetPackage,
|
||||
UserHandle targetUser, long idForResponseEvent,
|
||||
@ElapsedRealtimeLong long timestampMs, @ProcessState int targetUidProcState) {
|
||||
if (DEBUG_RESPONSE_STATS) {
|
||||
Slog.d(TAG, TextUtils.formatSimple("reportBroadcastDispatchEvent; "
|
||||
+ "srcUid=%d, tgtPkg=%s, tgtUsr=%d, id=%d, ts=%s, state=%s",
|
||||
sourceUid, targetPackage, targetUser, idForResponseEvent,
|
||||
TimeUtils.formatDuration(timestampMs), procStateToString(targetUidProcState)));
|
||||
}
|
||||
mLogger.logBroadcastDispatchEvent(sourceUid, targetPackage, targetUser,
|
||||
idForResponseEvent, timestampMs, targetUidProcState);
|
||||
if (targetUidProcState <= mAppStandby.getBroadcastResponseFgThresholdState()) {
|
||||
// No need to track the broadcast response state while the target app is
|
||||
// in the foreground.
|
||||
@@ -110,29 +102,23 @@ class BroadcastResponseStatsTracker {
|
||||
|
||||
void reportNotificationPosted(@NonNull String packageName, UserHandle user,
|
||||
@ElapsedRealtimeLong long timestampMs) {
|
||||
reportNotificationEvent(NOTIFICATION_EVENT_POSTED, packageName, user, timestampMs);
|
||||
reportNotificationEvent(NOTIFICATION_EVENT_TYPE_POSTED, packageName, user, timestampMs);
|
||||
}
|
||||
|
||||
void reportNotificationUpdated(@NonNull String packageName, UserHandle user,
|
||||
@ElapsedRealtimeLong long timestampMs) {
|
||||
reportNotificationEvent(NOTIFICATION_EVENT_UPDATED, packageName, user, timestampMs);
|
||||
reportNotificationEvent(NOTIFICATION_EVENT_TYPE_UPDATED, packageName, user, timestampMs);
|
||||
|
||||
}
|
||||
|
||||
void reportNotificationCancelled(@NonNull String packageName, UserHandle user,
|
||||
@ElapsedRealtimeLong long timestampMs) {
|
||||
reportNotificationEvent(NOTIFICATION_EVENT_CANCELLED, packageName, user, timestampMs);
|
||||
reportNotificationEvent(NOTIFICATION_EVENT_TYPE_CANCELLED, packageName, user, timestampMs);
|
||||
}
|
||||
|
||||
private void reportNotificationEvent(@NotificationEvent int event,
|
||||
private void reportNotificationEvent(@NotificationEventType int event,
|
||||
@NonNull String packageName, UserHandle user, @ElapsedRealtimeLong long timestampMs) {
|
||||
if (DEBUG_RESPONSE_STATS) {
|
||||
Slog.d(TAG, TextUtils.formatSimple(
|
||||
"reportNotificationEvent; event=<%s>, pkg=%s, usr=%d, ts=%s",
|
||||
notificationEventToString(event), packageName, user.getIdentifier(),
|
||||
TimeUtils.formatDuration(timestampMs)));
|
||||
}
|
||||
// TODO (206518114): Store last N events to dump for debugging purposes.
|
||||
mLogger.logNotificationEvent(event, packageName, user, timestampMs);
|
||||
synchronized (mLock) {
|
||||
final LongSparseArray<BroadcastEvent> broadcastEvents =
|
||||
getBroadcastEventsLocked(packageName, user);
|
||||
@@ -157,13 +143,13 @@ class BroadcastResponseStatsTracker {
|
||||
continue;
|
||||
}
|
||||
switch (event) {
|
||||
case NOTIFICATION_EVENT_POSTED:
|
||||
case NOTIFICATION_EVENT_TYPE_POSTED:
|
||||
responseStats.incrementNotificationsPostedCount(1);
|
||||
break;
|
||||
case NOTIFICATION_EVENT_UPDATED:
|
||||
case NOTIFICATION_EVENT_TYPE_UPDATED:
|
||||
responseStats.incrementNotificationsUpdatedCount(1);
|
||||
break;
|
||||
case NOTIFICATION_EVENT_CANCELLED:
|
||||
case NOTIFICATION_EVENT_TYPE_CANCELLED:
|
||||
responseStats.incrementNotificationsCancelledCount(1);
|
||||
break;
|
||||
default:
|
||||
@@ -329,20 +315,6 @@ class BroadcastResponseStatsTracker {
|
||||
return userResponseStats.getOrCreateBroadcastResponseStats(broadcastEvent);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String notificationEventToString(@NotificationEvent int event) {
|
||||
switch (event) {
|
||||
case NOTIFICATION_EVENT_POSTED:
|
||||
return "posted";
|
||||
case NOTIFICATION_EVENT_UPDATED:
|
||||
return "updated";
|
||||
case NOTIFICATION_EVENT_CANCELLED:
|
||||
return "cancelled";
|
||||
default:
|
||||
return String.valueOf(event);
|
||||
}
|
||||
}
|
||||
|
||||
void dump(@NonNull IndentingPrintWriter ipw) {
|
||||
ipw.println("Broadcast response stats:");
|
||||
ipw.increaseIndent();
|
||||
@@ -351,6 +323,8 @@ class BroadcastResponseStatsTracker {
|
||||
dumpBroadcastEventsLocked(ipw);
|
||||
ipw.println();
|
||||
dumpResponseStatsLocked(ipw);
|
||||
ipw.println();
|
||||
mLogger.dumpLogs(ipw);
|
||||
}
|
||||
|
||||
ipw.decreaseIndent();
|
||||
|
||||
Reference in New Issue
Block a user