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

Commit 4ff21545 authored by Julia Tuttle's avatar Julia Tuttle
Browse files

Log lots more about notification inflation

We're debugging a bug in which an incoming call notification never
appeared, and seemed like it might've been stuck partway through the
inflation process.

We also don't have great logs at the lower levels of the inflation
process.

So, add a new log buffer (NotifInflationLog) and add logging in many
more places, making sure to cover potentially slow/hung operations well.

Bug: 290800796
Test: manual
Change-Id: I891a648748b612faae1fc732b08aa057a6cb2504
parent 163a9def
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -80,6 +80,14 @@ public class LogModule {
        return factory.create("NotifHeadsUpLog", 1000);
    }

    /** Provides a logging buffer for logs related to inflation of notifications. */
    @Provides
    @SysUISingleton
    @NotifInflationLog
    public static LogBuffer provideNotifInflationLogBuffer(LogBufferFactory factory) {
        return factory.create("NotifInflationLog", 100);
    }

    /** Provides a logging buffer for notification interruption calculations. */
    @Provides
    @SysUISingleton
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.log.dagger;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.android.systemui.log.LogBuffer;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

import javax.inject.Qualifier;

/** A {@link LogBuffer} for messages related to inflation of notifications. */
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface NotifInflationLog {
}
+7 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.BindEven
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationContentInflaterLogger
import com.android.systemui.statusbar.notification.row.NotificationContentView
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -47,7 +48,11 @@ class ConversationNotificationProcessor @Inject constructor(
    private val launcherApps: LauncherApps,
    private val conversationNotificationManager: ConversationNotificationManager
) {
    fun processNotification(entry: NotificationEntry, recoveredBuilder: Notification.Builder) {
    fun processNotification(
            entry: NotificationEntry,
            recoveredBuilder: Notification.Builder,
            logger: NotificationContentInflaterLogger
    ) {
        val messagingStyle = recoveredBuilder.style as? Notification.MessagingStyle ?: return
        messagingStyle.conversationType =
                if (entry.ranking.channel.isImportantConversation)
@@ -55,6 +60,7 @@ class ConversationNotificationProcessor @Inject constructor(
                else
                    Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL
        entry.ranking.conversationShortcutInfo?.let { shortcutInfo ->
            logger.logAsyncTaskProgress(entry, "getting shortcut icon")
            messagingStyle.shortcutIcon = launcherApps.getShortcutIcon(shortcutInfo)
            shortcutInfo.label?.let { label ->
                messagingStyle.conversationTitle = label
+24 −8
Original line number Diff line number Diff line
@@ -36,12 +36,14 @@ import javax.inject.Inject;
public class NotifInflaterImpl implements NotifInflater {

    private final NotifInflationErrorManager mNotifErrorManager;
    private final NotifInflaterLogger mLogger;

    private NotificationRowBinderImpl mNotificationRowBinder;

    @Inject
    public NotifInflaterImpl(NotifInflationErrorManager errorManager) {
    public NotifInflaterImpl(NotifInflationErrorManager errorManager, NotifInflaterLogger logger) {
        mNotifErrorManager = errorManager;
        mLogger = logger;
    }

    /**
@@ -51,12 +53,6 @@ public class NotifInflaterImpl implements NotifInflater {
        mNotificationRowBinder = rowBinder;
    }

    @Override
    public void rebindViews(@NonNull NotificationEntry entry, @NonNull Params params,
            @NonNull InflationCallback callback) {
        inflateViews(entry, params, callback);
    }

    /**
     * Called to inflate the views of an entry.  Views are not considered inflated until all of its
     * views are bound.
@@ -64,23 +60,43 @@ public class NotifInflaterImpl implements NotifInflater {
    @Override
    public void inflateViews(@NonNull NotificationEntry entry, @NonNull Params params,
            @NonNull InflationCallback callback) {
        mLogger.logInflatingViews(entry, params);
        inflateViewsImpl(entry, params, callback);
        mLogger.logInflatedViews(entry);
    }
    @Override
    public void rebindViews(@NonNull NotificationEntry entry, @NonNull Params params,
            @NonNull InflationCallback callback) {
        mLogger.logRebindingViews(entry, params);
        inflateViewsImpl(entry, params, callback);
        mLogger.logReboundViews(entry);
    }

    private void inflateViewsImpl(@NonNull NotificationEntry entry, @NonNull Params params,
            @NonNull InflationCallback callback) {
        try {
            requireBinder().inflateViews(
                    entry,
                    params,
                    wrapInflationCallback(callback));
        } catch (InflationException e) {
            mLogger.logInflationException(entry, e);
            mNotifErrorManager.setInflationError(entry, e);
        }
    }

    @Override
    public boolean abortInflation(NotificationEntry entry) {
        return entry.abortTask();
        final boolean abortedTask = entry.abortTask();
        if (abortedTask) {
            mLogger.logAbortInflationAbortedTask(entry);
        }
        return abortedTask;
    }

    @Override
    public void releaseViews(@NonNull NotificationEntry entry) {
        mLogger.logReleasingViews(entry);
        requireBinder().releaseViews(entry);
    }

+86 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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

import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.NotifInflationLog
import com.android.systemui.statusbar.notification.InflationException
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater.Params
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject

class NotifInflaterLogger @Inject constructor(@NotifInflationLog private val buffer: LogBuffer) {
    fun logInflatingViews(entry: NotificationEntry, params: Params) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                str1 = entry.logKey
                str2 = params.reason
            },
            { "inflating views for $str1: $str2" }
        )
    }

    fun logInflatedViews(entry: NotificationEntry) {
        buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "inflated views for $str1" })
    }

    fun logRebindingViews(entry: NotificationEntry, params: Params) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                str1 = entry.logKey
                str2 = params.reason
            },
            { "rebinding views for $str1: $str2" }
        )
    }

    fun logReboundViews(entry: NotificationEntry) {
        buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "rebound views for $str1" })
    }

    fun logInflationException(entry: NotificationEntry, exc: InflationException) {
        buffer.log(
            TAG,
            LogLevel.WARNING,
            {
                str1 = entry.logKey
                str2 = exc.stackTraceToString()
            },
            { "exception inflating views for $str1: $str2" }
        )
    }

    fun logAbortInflationAbortedTask(entry: NotificationEntry) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            { str1 = entry.logKey },
            { "aborted task to abort inflation for $str1" }
        )
    }

    fun logReleasingViews(entry: NotificationEntry) {
        buffer.log(TAG, LogLevel.DEBUG, { str1 = entry.logKey }, { "aborting inflation for $str1" })
    }
}

private const val TAG = "NotifInflater"
Loading