Add logging to content inflation pipeline

Use new LogBuffer to add more logging to content inflation classes,
namely NotifBindPipeline and RowContentBindStage to make our debugging
lives easier.

Test: adb shell settings put global systemui/buffer/NotifLog2 debug
Observe new logs in logcat
Change-Id: Ia4232c2586bab4a766d9900b56d3aface512f29f
This commit is contained in:
Kevin Han
2020-02-07 12:23:52 -08:00
parent 0fe79c3fe2
commit c1f04488b9
9 changed files with 141 additions and 17 deletions

View File

@@ -26,26 +26,23 @@ import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.Window
import android.view.WindowInsets.Type
import android.view.WindowInsets.Type.statusBars
import android.view.WindowManager
import android.widget.TextView
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
import javax.inject.Inject
import javax.inject.Singleton
const val TAG = "ChannelDialogController"
private const val TAG = "ChannelDialogController"
/**
* ChannelEditorDialogController is the controller for the dialog half-shelf
@@ -149,9 +146,9 @@ class ChannelEditorDialogController @Inject constructor(
val channels = groupList
.flatMap { group ->
group.channels.asSequence().filterNot { channel ->
channel.isImportanceLockedByOEM
|| channel.importance == IMPORTANCE_NONE
|| channel.isImportanceLockedByCriticalDeviceFunction
channel.isImportanceLockedByOEM ||
channel.importance == IMPORTANCE_NONE ||
channel.isImportanceLockedByCriticalDeviceFunction
}
}

View File

@@ -74,11 +74,15 @@ import javax.inject.Singleton;
@Singleton
public final class NotifBindPipeline {
private final Map<NotificationEntry, BindEntry> mBindEntries = new ArrayMap<>();
private final NotifBindPipelineLogger mLogger;
private BindStage mStage;
@Inject
NotifBindPipeline(CommonNotifCollection collection) {
NotifBindPipeline(
CommonNotifCollection collection,
NotifBindPipelineLogger logger) {
collection.addCollectionListener(mCollectionListener);
mLogger = logger;
}
/**
@@ -86,6 +90,8 @@ public final class NotifBindPipeline {
*/
public void setStage(
BindStage stage) {
mLogger.logStageSet(stage.getClass().getName());
mStage = stage;
mStage.setBindRequestListener(this::onBindRequested);
}
@@ -96,6 +102,8 @@ public final class NotifBindPipeline {
public void manageRow(
@NonNull NotificationEntry entry,
@NonNull ExpandableNotificationRow row) {
mLogger.logManagedRow(entry.getKey());
final BindEntry bindEntry = getBindEntry(entry);
bindEntry.row = row;
if (bindEntry.invalidated) {
@@ -130,6 +138,8 @@ public final class NotifBindPipeline {
* callbacks when the run finishes. If a run is already in progress, it is restarted.
*/
private void startPipeline(NotificationEntry entry) {
mLogger.logStartPipeline(entry.getKey());
if (mStage == null) {
throw new IllegalStateException("No stage was ever set on the pipeline");
}
@@ -147,10 +157,11 @@ public final class NotifBindPipeline {
private void onPipelineComplete(NotificationEntry entry) {
final BindEntry bindEntry = getBindEntry(entry);
final Set<BindCallback> callbacks = bindEntry.callbacks;
mLogger.logFinishedPipeline(entry.getKey(), callbacks.size());
bindEntry.invalidated = false;
final Set<BindCallback> callbacks = bindEntry.callbacks;
for (BindCallback cb : callbacks) {
cb.onBindFinished(entry);
}

View File

@@ -0,0 +1,61 @@
/*
* 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.row
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.NotificationLog
import javax.inject.Inject
class NotifBindPipelineLogger @Inject constructor(
@NotificationLog private val buffer: LogBuffer
) {
fun logStageSet(stageName: String) {
buffer.log(TAG, INFO, {
str1 = stageName
}, {
"Stage set: $str1"
})
}
fun logManagedRow(notifKey: String) {
buffer.log(TAG, INFO, {
str1 = notifKey
}, {
"Row set for notif: $str1"
})
}
fun logStartPipeline(notifKey: String) {
buffer.log(TAG, INFO, {
str1 = notifKey
}, {
"Start pipeline for notif: $str1"
})
}
fun logFinishedPipeline(notifKey: String, numCallbacks: Int) {
buffer.log(TAG, INFO, {
str1 = notifKey
int1 = numCallbacks
}, {
"Finished pipeline for notif $str1 with $int1 callbacks"
})
}
}
private const val TAG = "NotifBindPipeline"

View File

@@ -157,6 +157,15 @@ public final class RowContentBindParams {
return mViewsNeedReinflation;
}
@Override
public String toString() {
return String.format("RowContentBindParams[mContentViews=%x mDirtyContentViews=%x "
+ "mUseLowPriority=%b mUseChildInGroup=%b mUseIncreasedHeight=%b "
+ "mUseIncreasedHeadsUpHeight=%b mViewsNeedReinflation=%b]",
mContentViews, mDirtyContentViews, mUseLowPriority, mUseChildInGroup,
mUseIncreasedHeight, mUseIncreasedHeadsUpHeight, mViewsNeedReinflation);
}
/**
* Content views that should be inflated by default for all notifications.
*/

View File

@@ -38,13 +38,16 @@ import javax.inject.Singleton;
public class RowContentBindStage extends BindStage<RowContentBindParams> {
private final NotificationRowContentBinder mBinder;
private final NotifInflationErrorManager mNotifInflationErrorManager;
private final RowContentBindStageLogger mLogger;
@Inject
RowContentBindStage(
NotificationRowContentBinder binder,
NotifInflationErrorManager errorManager) {
NotifInflationErrorManager errorManager,
RowContentBindStageLogger logger) {
mBinder = binder;
mNotifInflationErrorManager = errorManager;
mLogger = logger;
}
@Override
@@ -54,6 +57,8 @@ public class RowContentBindStage extends BindStage<RowContentBindParams> {
@NonNull StageCallback callback) {
RowContentBindParams params = getStageParams(entry);
mLogger.logStageParams(entry.getKey(), params.toString());
// Resolve content to bind/unbind.
@InflationFlag int inflationFlags = params.getContentViews();
@InflationFlag int invalidatedFlags = params.getDirtyContentViews();

View File

@@ -0,0 +1,37 @@
/*
* 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.row
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.NotificationLog
import javax.inject.Inject
class RowContentBindStageLogger @Inject constructor(
@NotificationLog private val buffer: LogBuffer
) {
fun logStageParams(notifKey: String, stageParams: String) {
buffer.log(TAG, INFO, {
str1 = notifKey
str2 = stageParams
}, {
"Invalidated notif $str1 with params: \n$str2"
})
}
}
private const val TAG = "RowContentBindStage"

View File

@@ -59,7 +59,7 @@ public class NotifBindPipelineTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
CommonNotifCollection collection = mock(CommonNotifCollection.class);
mBindPipeline = new NotifBindPipeline(collection);
mBindPipeline = new NotifBindPipeline(collection, mock(NotifBindPipelineLogger.class));
mBindPipeline.setStage(mStage);
ArgumentCaptor<NotifCollectionListener> collectionListenerCaptor =

View File

@@ -111,11 +111,13 @@ public class NotificationTestHelper {
mock(NotifRemoteViewCache.class),
mock(NotificationRemoteInputManager.class));
contentBinder.setInflateSynchronously(true);
mBindStage = new RowContentBindStage(contentBinder, mock(NotifInflationErrorManager.class));
mBindStage = new RowContentBindStage(contentBinder,
mock(NotifInflationErrorManager.class),
mock(RowContentBindStageLogger.class));
CommonNotifCollection collection = mock(CommonNotifCollection.class);
mBindPipeline = new NotifBindPipeline(collection);
mBindPipeline = new NotifBindPipeline(collection, mock(NotifBindPipelineLogger.class));
mBindPipeline.setStage(mBindStage);
ArgumentCaptor<NotifCollectionListener> collectionListenerCaptor =

View File

@@ -60,8 +60,10 @@ public class RowContentBindStageTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mRowContentBindStage = new RowContentBindStage(mBinder,
mock(NotifInflationErrorManager.class));
mRowContentBindStage = new RowContentBindStage(
mBinder,
mock(NotifInflationErrorManager.class),
mock(RowContentBindStageLogger.class));
mRowContentBindStage.createStageParams(mEntry);
}