blob: 46e01c33bae33a0f8e49eb801b9563dda46f6cc4 [file] [log] [blame]
/*
* Copyright (C) 2020 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.systemui.statusbar.notification.collection.notifcollection
import android.os.RemoteException
import android.service.notification.NotificationListenerService
import android.service.notification.NotificationListenerService.RankingMap
import android.service.notification.StatusBarNotification
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.ERROR
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.log.LogLevel.WTF
import com.android.systemui.log.dagger.NotificationLog
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason
import com.android.systemui.statusbar.notification.collection.NotifCollection.FutureDismissal
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
fun cancellationReasonDebugString(@CancellationReason reason: Int) =
"$reason:" + when (reason) {
-1 -> "REASON_NOT_CANCELED" // NotifCollection.REASON_NOT_CANCELED
NotifCollection.REASON_UNKNOWN -> "REASON_UNKNOWN"
NotificationListenerService.REASON_CLICK -> "REASON_CLICK"
NotificationListenerService.REASON_CANCEL -> "REASON_CANCEL"
NotificationListenerService.REASON_CANCEL_ALL -> "REASON_CANCEL_ALL"
NotificationListenerService.REASON_ERROR -> "REASON_ERROR"
NotificationListenerService.REASON_PACKAGE_CHANGED -> "REASON_PACKAGE_CHANGED"
NotificationListenerService.REASON_USER_STOPPED -> "REASON_USER_STOPPED"
NotificationListenerService.REASON_PACKAGE_BANNED -> "REASON_PACKAGE_BANNED"
NotificationListenerService.REASON_APP_CANCEL -> "REASON_APP_CANCEL"
NotificationListenerService.REASON_APP_CANCEL_ALL -> "REASON_APP_CANCEL_ALL"
NotificationListenerService.REASON_LISTENER_CANCEL -> "REASON_LISTENER_CANCEL"
NotificationListenerService.REASON_LISTENER_CANCEL_ALL -> "REASON_LISTENER_CANCEL_ALL"
NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED -> "REASON_GROUP_SUMMARY_CANCELED"
NotificationListenerService.REASON_GROUP_OPTIMIZATION -> "REASON_GROUP_OPTIMIZATION"
NotificationListenerService.REASON_PACKAGE_SUSPENDED -> "REASON_PACKAGE_SUSPENDED"
NotificationListenerService.REASON_PROFILE_TURNED_OFF -> "REASON_PROFILE_TURNED_OFF"
NotificationListenerService.REASON_UNAUTOBUNDLED -> "REASON_UNAUTOBUNDLED"
NotificationListenerService.REASON_CHANNEL_BANNED -> "REASON_CHANNEL_BANNED"
NotificationListenerService.REASON_SNOOZED -> "REASON_SNOOZED"
NotificationListenerService.REASON_TIMEOUT -> "REASON_TIMEOUT"
NotificationListenerService.REASON_CHANNEL_REMOVED -> "REASON_CHANNEL_REMOVED"
NotificationListenerService.REASON_CLEAR_DATA -> "REASON_CLEAR_DATA"
NotificationListenerService.REASON_ASSISTANT_CANCEL -> "REASON_ASSISTANT_CANCEL"
else -> "unknown"
}
class NotifCollectionLogger @Inject constructor(
@NotificationLog private val buffer: LogBuffer
) {
fun logNotifPosted(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"POSTED $str1"
})
}
fun logNotifGroupPosted(groupKey: String, batchSize: Int) {
buffer.log(TAG, INFO, {
str1 = logKey(groupKey)
int1 = batchSize
}, {
"POSTED GROUP $str1 ($int1 events)"
})
}
fun logNotifUpdated(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"UPDATED $str1"
})
}
fun logNotifRemoved(sbn: StatusBarNotification, @CancellationReason reason: Int) {
buffer.log(TAG, INFO, {
str1 = sbn.logKey
int1 = reason
}, {
"REMOVED $str1 reason=${cancellationReasonDebugString(int1)}"
})
}
fun logNotifReleased(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"RELEASED $str1"
})
}
fun logNotifDismissed(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"DISMISSED $str1"
})
}
fun logNonExistentNotifDismissed(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"DISMISSED Non Existent $str1"
})
}
fun logChildDismissed(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
str1 = entry.logKey
}, {
"CHILD DISMISSED (inferred): $str1"
})
}
fun logDismissAll(userId: Int) {
buffer.log(TAG, INFO, {
int1 = userId
}, {
"DISMISS ALL notifications for user $int1"
})
}
fun logDismissOnAlreadyCanceledEntry(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
str1 = entry.logKey
}, {
"Dismiss on $str1, which was already canceled. Trying to remove..."
})
}
fun logNotifDismissedIntercepted(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"DISMISS INTERCEPTED $str1"
})
}
fun logNotifClearAllDismissalIntercepted(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
}, {
"CLEAR ALL DISMISSAL INTERCEPTED $str1"
})
}
fun logNotifInternalUpdate(entry: NotificationEntry, name: String, reason: String) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
str2 = name
str3 = reason
}, {
"UPDATED INTERNALLY $str1 BY $str2 BECAUSE $str3"
})
}
fun logNotifInternalUpdateFailed(sbn: StatusBarNotification, name: String, reason: String) {
buffer.log(TAG, INFO, {
str1 = sbn.logKey
str2 = name
str3 = reason
}, {
"FAILED INTERNAL UPDATE $str1 BY $str2 BECAUSE $str3"
})
}
fun logNoNotificationToRemoveWithKey(
sbn: StatusBarNotification,
@CancellationReason reason: Int
) {
buffer.log(TAG, ERROR, {
str1 = sbn.logKey
int1 = reason
}, {
"No notification to remove with key $str1 reason=${cancellationReasonDebugString(int1)}"
})
}
fun logRankingMissing(entry: NotificationEntry, rankingMap: RankingMap) {
buffer.log(TAG, WARNING, {
str1 = entry.logKey
}, {
"Ranking update is missing ranking for $str1"
})
buffer.log(TAG, DEBUG, {}, { "Ranking map contents:" })
for (entry in rankingMap.orderedKeys) {
buffer.log(TAG, DEBUG, { str1 = logKey(entry) }, { " $str1" })
}
}
fun logRemoteExceptionOnNotificationClear(entry: NotificationEntry, e: RemoteException) {
buffer.log(TAG, WTF, {
str1 = entry.logKey
str2 = e.toString()
}, {
"RemoteException while attempting to clear $str1:\n$str2"
})
}
fun logRemoteExceptionOnClearAllNotifications(e: RemoteException) {
buffer.log(TAG, WTF, {
str1 = e.toString()
}, {
"RemoteException while attempting to clear all notifications:\n$str1"
})
}
fun logLifetimeExtended(entry: NotificationEntry, extender: NotifLifetimeExtender) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
str2 = extender.name
}, {
"LIFETIME EXTENDED: $str1 by $str2"
})
}
fun logLifetimeExtensionEnded(
entry: NotificationEntry,
extender: NotifLifetimeExtender,
totalExtenders: Int
) {
buffer.log(TAG, INFO, {
str1 = entry.logKey
str2 = extender.name
int1 = totalExtenders
}, {
"LIFETIME EXTENSION ENDED for $str1 by '$str2'; $int1 remaining extensions"
})
}
fun logIgnoredError(message: String?) {
buffer.log(TAG, ERROR, {
str1 = message
}, {
"ERROR suppressed due to initialization forgiveness: $str1"
})
}
fun logEntryBeingExtendedNotInCollection(
entry: NotificationEntry,
extender: NotifLifetimeExtender,
collectionEntryIs: String
) {
buffer.log(TAG, WARNING, {
str1 = entry.logKey
str2 = extender.name
str3 = collectionEntryIs
}, {
"While ending lifetime extension by $str2 of $str1, entry in collection is $str3"
})
}
fun logFutureDismissalReused(dismissal: FutureDismissal) {
buffer.log(TAG, INFO, {
str1 = dismissal.label
}, {
"Reusing existing registration: $str1"
})
}
fun logFutureDismissalRegistered(dismissal: FutureDismissal) {
buffer.log(TAG, DEBUG, {
str1 = dismissal.label
}, {
"Registered: $str1"
})
}
fun logFutureDismissalDoubleCancelledByServer(dismissal: FutureDismissal) {
buffer.log(TAG, WARNING, {
str1 = dismissal.label
}, {
"System server double cancelled: $str1"
})
}
fun logFutureDismissalDoubleRun(dismissal: FutureDismissal) {
buffer.log(TAG, WARNING, {
str1 = dismissal.label
}, {
"Double run: $str1"
})
}
fun logFutureDismissalAlreadyCancelledByServer(dismissal: FutureDismissal) {
buffer.log(TAG, DEBUG, {
str1 = dismissal.label
}, {
"Ignoring: entry already cancelled by server: $str1"
})
}
fun logFutureDismissalGotSystemServerCancel(
dismissal: FutureDismissal,
@CancellationReason cancellationReason: Int
) {
buffer.log(TAG, DEBUG, {
str1 = dismissal.label
int1 = cancellationReason
}, {
"SystemServer cancelled: $str1 reason=${cancellationReasonDebugString(int1)}"
})
}
fun logFutureDismissalDismissing(dismissal: FutureDismissal, type: String) {
buffer.log(TAG, DEBUG, {
str1 = dismissal.label
str2 = type
}, {
"Dismissing $str2 for: $str1"
})
}
fun logFutureDismissalMismatchedEntry(
dismissal: FutureDismissal,
type: String,
latestEntry: NotificationEntry?
) {
buffer.log(TAG, WARNING, {
str1 = dismissal.label
str2 = type
str3 = latestEntry.logKey
}, {
"Mismatch: current $str2 is $str3 for: $str1"
})
}
}
private const val TAG = "NotifCollection"