Add new QS Ui EVents
This CL adds events for: * QS interactions * StatusBarState changes * User Switcher interaction * DND panel interaction The new QS events that refer to particular tiles attach the following: * spec (if framework tile) or package (if CustomTile) * instanceId associated with the QSTile object on creation Test: atest SystemUITests (including new tests) Test: manual using statsd_testdrive Fixes: 147508235 Change-Id: I43d8fe1fdb2aec1f16032da61a599ebc29809afc
This commit is contained in:
@@ -19,6 +19,7 @@ import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
|
||||
@ProvidesInterface(version = DetailAdapter.VERSION)
|
||||
@@ -44,4 +45,18 @@ public interface DetailAdapter {
|
||||
default boolean hasHeader() {
|
||||
return true;
|
||||
}
|
||||
|
||||
default UiEventLogger.UiEventEnum openDetailEvent() {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
default UiEventLogger.UiEventEnum closeDetailEvent() {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
default UiEventLogger.UiEventEnum moreSettingsEvent() {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
UiEventLogger.UiEventEnum INVALID = () -> 0;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.graphics.drawable.Drawable;
|
||||
import android.metrics.LogMaker;
|
||||
import android.service.quicksettings.Tile;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.systemui.plugins.annotations.DependsOn;
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
import com.android.systemui.plugins.qs.QSTile.Callback;
|
||||
@@ -81,6 +82,18 @@ public interface QSTile {
|
||||
return logMaker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string to be used to identify the tile in UiEvents.
|
||||
*/
|
||||
default String getMetricsSpec() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link InstanceId} to be used to identify the tile in UiEvents.
|
||||
*/
|
||||
InstanceId getInstanceId();
|
||||
|
||||
@ProvidesInterface(version = Callback.VERSION)
|
||||
public interface Callback {
|
||||
public static final int VERSION = 1;
|
||||
|
||||
@@ -33,6 +33,8 @@ import android.view.LayoutInflater;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.UiEventLoggerImpl;
|
||||
import com.android.internal.util.NotificationMessagingUtil;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.ViewMediatorCallback;
|
||||
@@ -218,4 +220,11 @@ public class DependencyProvider {
|
||||
public Choreographer providesChoreographer() {
|
||||
return Choreographer.getInstance();
|
||||
}
|
||||
|
||||
/** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */
|
||||
@Singleton
|
||||
@Provides
|
||||
static UiEventLogger provideUiEventLogger() {
|
||||
return new UiEventLoggerImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,14 @@ import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.android.internal.logging.UiEventLogger
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.qs.TileLayout.exactly
|
||||
|
||||
class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTileLayout {
|
||||
class DoubleLineTileLayout(
|
||||
context: Context,
|
||||
private val uiEventLogger: UiEventLogger
|
||||
) : ViewGroup(context), QSPanel.QSTileLayout {
|
||||
|
||||
companion object {
|
||||
private const val NUM_LINES = 2
|
||||
@@ -86,6 +90,13 @@ class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTil
|
||||
for (record in mRecords) {
|
||||
record.tile.setListening(this, listening)
|
||||
}
|
||||
if (listening) {
|
||||
for (i in 0 until numVisibleTiles) {
|
||||
val tile = mRecords[i].tile
|
||||
uiEventLogger.logWithInstanceId(
|
||||
QSEvent.QQS_TILE_VISIBLE, 0, tile.metricsSpec, tile.instanceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNumVisibleTiles() = tilesToShow
|
||||
|
||||
@@ -22,7 +22,9 @@ import android.widget.Scroller;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.qs.QSTile;
|
||||
import com.android.systemui.qs.QSPanel.QSTileLayout;
|
||||
import com.android.systemui.qs.QSPanel.TileRecord;
|
||||
|
||||
@@ -63,7 +65,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
||||
private int mLayoutDirection;
|
||||
private int mHorizontalClipBound;
|
||||
private final Rect mClippingRect;
|
||||
private int mLastMaxHeight = -1;
|
||||
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
|
||||
|
||||
public PagedTileLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -75,6 +77,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
||||
mLayoutDirection = getLayoutDirection();
|
||||
mClippingRect = new Rect();
|
||||
}
|
||||
private int mLastMaxHeight = -1;
|
||||
|
||||
public void saveInstanceState(Bundle outState) {
|
||||
outState.putInt(CURRENT_PAGE, getCurrentItem());
|
||||
@@ -126,6 +129,15 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
||||
return page;
|
||||
}
|
||||
|
||||
// This will dump to the ui log all the tiles that are visible in this page
|
||||
private void logVisibleTiles(TilePage page) {
|
||||
for (int i = 0; i < page.mRecords.size(); i++) {
|
||||
QSTile t = page.mRecords.get(i).tile;
|
||||
mUiEventLogger.logWithInstanceId(QSEvent.QS_TILE_VISIBLE, 0, t.getMetricsSpec(),
|
||||
t.getInstanceId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListening(boolean listening) {
|
||||
if (mListening == listening) return;
|
||||
@@ -218,7 +230,11 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
||||
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
int currentItem = getCurrentPageNumber();
|
||||
for (int i = 0; i < mPages.size(); i++) {
|
||||
mPages.get(i).setSelected(i == currentItem ? selected : false);
|
||||
TilePage page = mPages.get(i);
|
||||
page.setSelected(i == currentItem ? selected : false);
|
||||
if (page.isSelected()) {
|
||||
logVisibleTiles(page);
|
||||
}
|
||||
}
|
||||
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
|
||||
}
|
||||
@@ -419,6 +435,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
||||
mPageListener.onPageChanged(isLayoutRtl() ? position == mPages.size() - 1
|
||||
: position == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.FontSizeUtils;
|
||||
import com.android.systemui.R;
|
||||
@@ -53,6 +54,7 @@ public class QSDetail extends LinearLayout {
|
||||
private static final long FADE_DURATION = 300;
|
||||
|
||||
private final SparseArray<View> mDetailViews = new SparseArray<>();
|
||||
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
|
||||
|
||||
private ViewGroup mDetailContent;
|
||||
protected TextView mDetailSettingsButton;
|
||||
@@ -205,6 +207,7 @@ public class QSDetail extends LinearLayout {
|
||||
mDetailContent.addView(detailView);
|
||||
mDetailViews.put(viewCacheIndex, detailView);
|
||||
Dependency.get(MetricsLogger.class).visible(adapter.getMetricsCategory());
|
||||
mUiEventLogger.log(adapter.openDetailEvent());
|
||||
announceForAccessibility(mContext.getString(
|
||||
R.string.accessibility_quick_settings_detail,
|
||||
adapter.getTitle()));
|
||||
@@ -214,6 +217,7 @@ public class QSDetail extends LinearLayout {
|
||||
} else {
|
||||
if (mDetailAdapter != null) {
|
||||
Dependency.get(MetricsLogger.class).hidden(mDetailAdapter.getMetricsCategory());
|
||||
mUiEventLogger.log(mDetailAdapter.closeDetailEvent());
|
||||
}
|
||||
mClosingDetail = true;
|
||||
mDetailAdapter = null;
|
||||
@@ -249,6 +253,7 @@ public class QSDetail extends LinearLayout {
|
||||
mDetailSettingsButton.setOnClickListener(v -> {
|
||||
Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
|
||||
adapter.getMetricsCategory());
|
||||
mUiEventLogger.log(adapter.moreSettingsEvent());
|
||||
Dependency.get(ActivityStarter.class)
|
||||
.postStartActivityDismissingKeyguard(settingsIntent, 0);
|
||||
});
|
||||
|
||||
124
packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
Normal file
124
packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.qs
|
||||
|
||||
import com.android.internal.logging.UiEvent
|
||||
import com.android.internal.logging.UiEventLogger
|
||||
import com.android.internal.logging.UiEventLoggerImpl
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake
|
||||
|
||||
object QSEvents {
|
||||
|
||||
var qsUiEventsLogger: UiEventLogger = UiEventLoggerImpl()
|
||||
private set
|
||||
|
||||
fun setLoggerForTesting(): UiEventLoggerFake {
|
||||
return UiEventLoggerFake().also {
|
||||
qsUiEventsLogger = it
|
||||
}
|
||||
}
|
||||
|
||||
fun resetLogger() {
|
||||
qsUiEventsLogger = UiEventLoggerImpl()
|
||||
}
|
||||
}
|
||||
|
||||
enum class QSEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
|
||||
@UiEvent(doc = "Tile clicked. It has an instance id and a spec (or packageName)")
|
||||
QS_ACTION_CLICK(387),
|
||||
|
||||
@UiEvent(doc = "Tile secondary button clicked. " +
|
||||
"It has an instance id and a spec (or packageName)")
|
||||
QS_ACTION_SECONDARY_CLICK(388),
|
||||
|
||||
@UiEvent(doc = "Tile long clicked. It has an instance id and a spec (or packageName)")
|
||||
QS_ACTION_LONG_PRESS(389),
|
||||
|
||||
@UiEvent(doc = "Quick Settings panel expanded")
|
||||
QS_PANEL_EXPANDED(390),
|
||||
|
||||
@UiEvent(doc = "Quick Settings panel collapsed")
|
||||
QS_PANEL_COLLAPSED(391),
|
||||
|
||||
@UiEvent(doc = "Tile visible in Quick Settings panel. The tile may be in a different page. " +
|
||||
"It has an instance id and a spec (or packageName)")
|
||||
QS_TILE_VISIBLE(392),
|
||||
|
||||
@UiEvent(doc = "Quick Quick Settings panel expanded")
|
||||
QQS_PANEL_EXPANDED(393),
|
||||
|
||||
@UiEvent(doc = "Quick Quick Settings panel collapsed")
|
||||
QQS_PANEL_COLLAPSED(394),
|
||||
|
||||
@UiEvent(doc = "Tile visible in Quick Quick Settings panel. " +
|
||||
"It has an instance id and a spec (or packageName)")
|
||||
QQS_TILE_VISIBLE(395);
|
||||
|
||||
override fun getId() = _id
|
||||
}
|
||||
|
||||
enum class QSEditEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
|
||||
|
||||
@UiEvent(doc = "Tile removed from current tiles")
|
||||
QS_EDIT_REMOVE(210),
|
||||
|
||||
@UiEvent(doc = "Tile added to current tiles")
|
||||
QS_EDIT_ADD(211),
|
||||
|
||||
@UiEvent(doc = "Tile moved")
|
||||
QS_EDIT_MOVE(212),
|
||||
|
||||
@UiEvent(doc = "QS customizer open")
|
||||
QS_EDIT_OPEN(213),
|
||||
|
||||
@UiEvent(doc = "QS customizer closed")
|
||||
QS_EDIT_CLOSED(214),
|
||||
|
||||
@UiEvent(doc = "QS tiles reset")
|
||||
QS_EDIT_RESET(215);
|
||||
|
||||
override fun getId() = _id
|
||||
}
|
||||
|
||||
enum class QSDndEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
|
||||
@UiEvent(doc = "TODO(beverlyt)")
|
||||
QS_DND_CONDITION_SELECT(420),
|
||||
|
||||
@UiEvent(doc = "TODO(beverlyt)")
|
||||
QS_DND_TIME_UP(422),
|
||||
|
||||
@UiEvent(doc = "TODO(beverlyt)")
|
||||
QS_DND_TIME_DOWN(423);
|
||||
|
||||
override fun getId() = _id
|
||||
}
|
||||
|
||||
enum class QSUserSwitcherEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
|
||||
@UiEvent(doc = "The current user has been switched in the detail panel")
|
||||
QS_USER_SWITCH(424),
|
||||
|
||||
@UiEvent(doc = "User switcher QS detail panel open")
|
||||
QS_USER_DETAIL_OPEN(425),
|
||||
|
||||
@UiEvent(doc = "User switcher QS detail panel closed")
|
||||
QS_USER_DETAIL_CLOSE(426),
|
||||
|
||||
@UiEvent(doc = "User switcher QS detail panel more settings pressed")
|
||||
QS_USER_MORE_SETTINGS(427);
|
||||
|
||||
override fun getId() = _id
|
||||
}
|
||||
@@ -16,6 +16,8 @@ package com.android.systemui.qs;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.plugins.qs.QSTile;
|
||||
import com.android.systemui.qs.external.TileServices;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
@@ -30,6 +32,7 @@ public interface QSHost {
|
||||
Context getContext();
|
||||
Context getUserContext();
|
||||
QSLogger getQSLogger();
|
||||
UiEventLogger getUiEventLogger();
|
||||
Collection<QSTile> getTiles();
|
||||
void addCallback(Callback callback);
|
||||
void removeCallback(Callback callback);
|
||||
@@ -39,6 +42,8 @@ public interface QSHost {
|
||||
|
||||
int indexOf(String tileSpec);
|
||||
|
||||
InstanceId getNewInstanceId();
|
||||
|
||||
interface Callback {
|
||||
void onTilesChanged();
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ import android.widget.HorizontalScrollView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.settingslib.Utils;
|
||||
@@ -129,6 +130,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
private BrightnessController mBrightnessController;
|
||||
private final DumpManager mDumpManager;
|
||||
private final QSLogger mQSLogger;
|
||||
protected final UiEventLogger mUiEventLogger;
|
||||
protected QSTileHost mHost;
|
||||
|
||||
protected QSSecurityFooter mFooter;
|
||||
@@ -176,7 +178,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
@Background DelayableExecutor backgroundExecutor,
|
||||
@Nullable LocalBluetoothManager localBluetoothManager,
|
||||
ActivityStarter activityStarter,
|
||||
NotificationEntryManager entryManager
|
||||
NotificationEntryManager entryManager,
|
||||
UiEventLogger uiEventLogger
|
||||
) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
@@ -188,6 +191,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mActivityStarter = activityStarter;
|
||||
mNotificationEntryManager = entryManager;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
|
||||
setOrientation(VERTICAL);
|
||||
|
||||
@@ -678,8 +682,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
}
|
||||
mMetricsLogger.visibility(MetricsEvent.QS_PANEL, mExpanded);
|
||||
if (!mExpanded) {
|
||||
mUiEventLogger.log(closePanelEvent());
|
||||
closeDetail();
|
||||
} else {
|
||||
mUiEventLogger.log(openPanelEvent());
|
||||
logTiles();
|
||||
}
|
||||
}
|
||||
@@ -786,6 +792,18 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
|
||||
return mHost.createTileView(tile, collapsedView);
|
||||
}
|
||||
|
||||
protected QSEvent openPanelEvent() {
|
||||
return QSEvent.QS_PANEL_EXPANDED;
|
||||
}
|
||||
|
||||
protected QSEvent closePanelEvent() {
|
||||
return QSEvent.QS_PANEL_COLLAPSED;
|
||||
}
|
||||
|
||||
protected QSEvent tileVisibleEvent() {
|
||||
return QSEvent.QS_TILE_VISIBLE;
|
||||
}
|
||||
|
||||
protected boolean shouldShowDetail() {
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.logging.InstanceIdSequence;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
@@ -73,6 +76,7 @@ import javax.inject.Singleton;
|
||||
public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, Dumpable {
|
||||
private static final String TAG = "QSTileHost";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final int MAX_QS_INSTANCE_ID = 1 << 20;
|
||||
|
||||
public static final String TILES_SETTING = Secure.QS_TILES;
|
||||
|
||||
@@ -85,6 +89,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
|
||||
private final DumpManager mDumpManager;
|
||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||
private final QSLogger mQSLogger;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final InstanceIdSequence mInstanceIdSequence;
|
||||
|
||||
private final List<Callback> mCallbacks = new ArrayList<>();
|
||||
private AutoTileManager mAutoTiles;
|
||||
@@ -106,7 +112,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
|
||||
DumpManager dumpManager,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
Optional<StatusBar> statusBarOptional,
|
||||
QSLogger qsLogger) {
|
||||
QSLogger qsLogger,
|
||||
UiEventLogger uiEventLogger) {
|
||||
mIconController = iconController;
|
||||
mContext = context;
|
||||
mUserContext = context;
|
||||
@@ -114,8 +121,10 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
|
||||
mPluginManager = pluginManager;
|
||||
mDumpManager = dumpManager;
|
||||
mQSLogger = qsLogger;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
|
||||
mInstanceIdSequence = new InstanceIdSequence(MAX_QS_INSTANCE_ID);
|
||||
mServices = new TileServices(this, bgLooper, mBroadcastDispatcher);
|
||||
mStatusBarOptional = statusBarOptional;
|
||||
|
||||
@@ -137,6 +146,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
|
||||
return mIconController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceId getNewInstanceId() {
|
||||
return mInstanceIdSequence.newInstanceId();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
mTiles.values().forEach(tile -> tile.destroy());
|
||||
mAutoTiles.destroy();
|
||||
@@ -169,6 +183,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
|
||||
return mQSLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UiEventLogger getUiEventLogger() {
|
||||
return mUiEventLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCallback(Callback callback) {
|
||||
mCallbacks.add(callback);
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
@@ -88,11 +89,12 @@ public class QuickQSPanel extends QSPanel {
|
||||
@Background DelayableExecutor backgroundExecutor,
|
||||
@Nullable LocalBluetoothManager localBluetoothManager,
|
||||
ActivityStarter activityStarter,
|
||||
NotificationEntryManager entryManager
|
||||
NotificationEntryManager entryManager,
|
||||
UiEventLogger uiEventLogger
|
||||
) {
|
||||
super(context, attrs, dumpManager, broadcastDispatcher, qsLogger,
|
||||
foregroundExecutor, backgroundExecutor, localBluetoothManager, activityStarter,
|
||||
entryManager);
|
||||
entryManager, uiEventLogger);
|
||||
if (mFooter != null) {
|
||||
removeView(mFooter.getView());
|
||||
}
|
||||
@@ -118,9 +120,9 @@ public class QuickQSPanel extends QSPanel {
|
||||
lp2.setMarginStart(0);
|
||||
mHorizontalLinearLayout.addView(mMediaPlayer.getView(), lp2);
|
||||
|
||||
mTileLayout = new DoubleLineTileLayout(context);
|
||||
mTileLayout = new DoubleLineTileLayout(context, mUiEventLogger);
|
||||
mMediaTileLayout = mTileLayout;
|
||||
mRegularTileLayout = new HeaderTileLayout(context);
|
||||
mRegularTileLayout = new HeaderTileLayout(context, mUiEventLogger);
|
||||
LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
|
||||
lp.setMarginEnd(0);
|
||||
lp.setMarginStart(marginSize);
|
||||
@@ -135,7 +137,7 @@ public class QuickQSPanel extends QSPanel {
|
||||
super.setPadding(0, 0, 0, 0);
|
||||
} else {
|
||||
sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
|
||||
mTileLayout = new HeaderTileLayout(context);
|
||||
mTileLayout = new HeaderTileLayout(context, mUiEventLogger);
|
||||
mTileLayout.setListening(mListening);
|
||||
addView((View) mTileLayout, 0 /* Between brightness and footer */);
|
||||
super.setPadding(0, 0, 0, 0);
|
||||
@@ -312,13 +314,30 @@ public class QuickQSPanel extends QSPanel {
|
||||
super.setVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QSEvent openPanelEvent() {
|
||||
return QSEvent.QQS_PANEL_EXPANDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QSEvent closePanelEvent() {
|
||||
return QSEvent.QQS_PANEL_COLLAPSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QSEvent tileVisibleEvent() {
|
||||
return QSEvent.QQS_TILE_VISIBLE;
|
||||
}
|
||||
|
||||
private static class HeaderTileLayout extends TileLayout {
|
||||
|
||||
private boolean mListening;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
private Rect mClippingBounds = new Rect();
|
||||
|
||||
public HeaderTileLayout(Context context) {
|
||||
public HeaderTileLayout(Context context, UiEventLogger uiEventLogger) {
|
||||
super(context);
|
||||
mUiEventLogger = uiEventLogger;
|
||||
setClipChildren(false);
|
||||
setClipToPadding(false);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
|
||||
@@ -443,5 +462,18 @@ public class QuickQSPanel extends QSPanel {
|
||||
}
|
||||
return getPaddingStart() + column * (mCellWidth + mCellMarginHorizontal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListening(boolean listening) {
|
||||
boolean startedListening = !mListening && listening;
|
||||
super.setListening(listening);
|
||||
if (startedListening) {
|
||||
for (int i = 0; i < getNumVisibleTiles(); i++) {
|
||||
QSTile tile = mRecords.get(i).tile;
|
||||
mUiEventLogger.logWithInstanceId(QSEvent.QQS_TILE_VISIBLE, 0,
|
||||
tile.getMetricsSpec(), tile.getInstanceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
||||
|
||||
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
|
||||
private int mCellMarginTop;
|
||||
private boolean mListening;
|
||||
protected boolean mListening;
|
||||
protected int mMaxAllowedRows = 3;
|
||||
|
||||
// Prototyping with less rows
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.android.systemui.keyguard.ScreenLifecycle;
|
||||
import com.android.systemui.plugins.qs.QS;
|
||||
import com.android.systemui.plugins.qs.QSTile;
|
||||
import com.android.systemui.qs.QSDetailClipper;
|
||||
import com.android.systemui.qs.QSEditEvent;
|
||||
import com.android.systemui.qs.QSTileHost;
|
||||
import com.android.systemui.statusbar.phone.LightBarController;
|
||||
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
|
||||
@@ -93,7 +94,8 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
|
||||
LightBarController lightBarController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
ScreenLifecycle screenLifecycle,
|
||||
TileQueryHelper tileQueryHelper) {
|
||||
TileQueryHelper tileQueryHelper,
|
||||
UiEventLogger uiEventLogger) {
|
||||
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
|
||||
|
||||
LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
|
||||
@@ -115,7 +117,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
|
||||
mToolbar.setTitle(R.string.qs_edit);
|
||||
mRecyclerView = findViewById(android.R.id.list);
|
||||
mTransparentView = findViewById(R.id.customizer_transparent_view);
|
||||
mTileAdapter = new TileAdapter(getContext());
|
||||
mTileAdapter = new TileAdapter(getContext(), uiEventLogger);
|
||||
mTileQueryHelper = tileQueryHelper;
|
||||
mTileQueryHelper.setListener(mTileAdapter);
|
||||
mRecyclerView.setAdapter(mTileAdapter);
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.qs.customize
|
||||
|
||||
import com.android.internal.logging.UiEvent
|
||||
import com.android.internal.logging.UiEventLogger
|
||||
|
||||
enum class QSEditEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
|
||||
|
||||
@UiEvent(doc = "Tile removed from current tiles")
|
||||
QS_EDIT_REMOVE(210),
|
||||
@UiEvent(doc = "Tile added to current tiles")
|
||||
QS_EDIT_ADD(211),
|
||||
@UiEvent(doc = "Tile moved")
|
||||
QS_EDIT_MOVE(212),
|
||||
@UiEvent(doc = "QS customizer open")
|
||||
QS_EDIT_OPEN(213),
|
||||
@UiEvent(doc = "QS customizer closed")
|
||||
QS_EDIT_CLOSED(214),
|
||||
@UiEvent(doc = "QS tiles reset")
|
||||
QS_EDIT_RESET(215);
|
||||
|
||||
override fun getId() = _id
|
||||
}
|
||||
@@ -41,8 +41,8 @@ import androidx.recyclerview.widget.RecyclerView.State;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.UiEventLoggerImpl;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.QSEditEvent;
|
||||
import com.android.systemui.qs.QSTileHost;
|
||||
import com.android.systemui.qs.customize.TileAdapter.Holder;
|
||||
import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
|
||||
@@ -92,10 +92,11 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
|
||||
private int mAccessibilityFromIndex;
|
||||
private CharSequence mAccessibilityFromLabel;
|
||||
private QSTileHost mHost;
|
||||
private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
public TileAdapter(Context context) {
|
||||
public TileAdapter(Context context, UiEventLogger uiEventLogger) {
|
||||
mContext = context;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
mItemTouchHelper = new ItemTouchHelper(mCallbacks);
|
||||
mDecoration = new TileItemDecoration(context);
|
||||
|
||||
@@ -371,6 +371,11 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
|
||||
return MetricsEvent.QS_CUSTOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getMetricsSpec() {
|
||||
return mComponent.getPackageName();
|
||||
}
|
||||
|
||||
public void startUnlockAndRun() {
|
||||
Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
|
||||
try {
|
||||
|
||||
@@ -48,7 +48,9 @@ import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.Utils;
|
||||
@@ -62,6 +64,7 @@ import com.android.systemui.plugins.qs.QSTile;
|
||||
import com.android.systemui.plugins.qs.QSTile.State;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.qs.PagedTileLayout.TilePage;
|
||||
import com.android.systemui.qs.QSEvent;
|
||||
import com.android.systemui.qs.QSHost;
|
||||
import com.android.systemui.qs.QuickStatusBarHeader;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
@@ -97,12 +100,14 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
|
||||
private final StatusBarStateController
|
||||
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final QSLogger mQSLogger;
|
||||
|
||||
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
|
||||
private final Object mStaleListener = new Object();
|
||||
protected TState mState;
|
||||
private TState mTmpState;
|
||||
private final InstanceId mInstanceId;
|
||||
private boolean mAnnounceNextStateChange;
|
||||
|
||||
private String mTileSpec;
|
||||
@@ -156,10 +161,12 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
protected QSTileImpl(QSHost host) {
|
||||
mHost = host;
|
||||
mContext = host.getContext();
|
||||
mInstanceId = host.getNewInstanceId();
|
||||
mState = newTileState();
|
||||
mTmpState = newTileState();
|
||||
mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption();
|
||||
mQSLogger = host.getQSLogger();
|
||||
mUiEventLogger = host.getUiEventLogger();
|
||||
}
|
||||
|
||||
protected final void resetStates() {
|
||||
@@ -173,6 +180,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
return mLifecycle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceId getInstanceId() {
|
||||
return mInstanceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or removes a listening client for the tile. If the tile has one or more
|
||||
* listening client it will go into the listening state.
|
||||
@@ -247,6 +259,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
mMetricsLogger.write(populate(new LogMaker(ACTION_QS_CLICK).setType(TYPE_ACTION)
|
||||
.addTaggedData(FIELD_STATUS_BAR_STATE,
|
||||
mStatusBarStateController.getState())));
|
||||
mUiEventLogger.logWithInstanceId(QSEvent.QS_ACTION_CLICK, 0, getMetricsSpec(),
|
||||
getInstanceId());
|
||||
mQSLogger.logTileClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
|
||||
mHandler.sendEmptyMessage(H.CLICK);
|
||||
}
|
||||
@@ -255,6 +269,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
mMetricsLogger.write(populate(new LogMaker(ACTION_QS_SECONDARY_CLICK).setType(TYPE_ACTION)
|
||||
.addTaggedData(FIELD_STATUS_BAR_STATE,
|
||||
mStatusBarStateController.getState())));
|
||||
mUiEventLogger.logWithInstanceId(QSEvent.QS_ACTION_SECONDARY_CLICK, 0, getMetricsSpec(),
|
||||
getInstanceId());
|
||||
mQSLogger.logTileSecondaryClick(mTileSpec, mStatusBarStateController.getState(),
|
||||
mState.state);
|
||||
mHandler.sendEmptyMessage(H.SECONDARY_CLICK);
|
||||
@@ -264,6 +280,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
mMetricsLogger.write(populate(new LogMaker(ACTION_QS_LONG_PRESS).setType(TYPE_ACTION)
|
||||
.addTaggedData(FIELD_STATUS_BAR_STATE,
|
||||
mStatusBarStateController.getState())));
|
||||
mUiEventLogger.logWithInstanceId(QSEvent.QS_ACTION_LONG_PRESS, 0, getMetricsSpec(),
|
||||
getInstanceId());
|
||||
mQSLogger.logTileLongClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
|
||||
mHandler.sendEmptyMessage(H.LONG_CLICK);
|
||||
|
||||
@@ -483,6 +501,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMetricsSpec() {
|
||||
return mTileSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a default label for the tile.
|
||||
* @return default label for the tile.
|
||||
|
||||
@@ -26,10 +26,12 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.PseudoGridView;
|
||||
import com.android.systemui.qs.QSUserSwitcherEvent;
|
||||
import com.android.systemui.statusbar.policy.UserSwitcherController;
|
||||
|
||||
/**
|
||||
@@ -48,8 +50,9 @@ public class UserDetailView extends PseudoGridView {
|
||||
R.layout.qs_user_detail, parent, attach);
|
||||
}
|
||||
|
||||
public void createAndSetAdapter(UserSwitcherController controller) {
|
||||
mAdapter = new Adapter(mContext, controller);
|
||||
public void createAndSetAdapter(UserSwitcherController controller,
|
||||
UiEventLogger uiEventLogger) {
|
||||
mAdapter = new Adapter(mContext, controller, uiEventLogger);
|
||||
ViewGroupAdapterBridge.link(this, mAdapter);
|
||||
}
|
||||
|
||||
@@ -63,11 +66,14 @@ public class UserDetailView extends PseudoGridView {
|
||||
private final Context mContext;
|
||||
protected UserSwitcherController mController;
|
||||
private View mCurrentUserView;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
public Adapter(Context context, UserSwitcherController controller) {
|
||||
public Adapter(Context context, UserSwitcherController controller,
|
||||
UiEventLogger uiEventLogger) {
|
||||
super(controller);
|
||||
mContext = context;
|
||||
mController = controller;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,6 +133,7 @@ public class UserDetailView extends PseudoGridView {
|
||||
mController.startActivity(intent);
|
||||
} else if (tag.isSwitchToEnabled) {
|
||||
MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
|
||||
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_SWITCH);
|
||||
if (!tag.isAddUser && !tag.isRestricted && !tag.isDisabledByAdmin) {
|
||||
if (mCurrentUserView != null) {
|
||||
mCurrentUserView.setActivated(false);
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.util.Log;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.DejankUtils;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.Interpolators;
|
||||
@@ -69,6 +70,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
|
||||
};
|
||||
|
||||
private final ArrayList<RankedListener> mListeners = new ArrayList<>();
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private int mState;
|
||||
private int mLastState;
|
||||
private boolean mLeaveOpenOnKeyguardHide;
|
||||
@@ -119,7 +121,8 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
|
||||
private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
|
||||
|
||||
@Inject
|
||||
public StatusBarStateControllerImpl() {
|
||||
public StatusBarStateControllerImpl(UiEventLogger uiEventLogger) {
|
||||
mUiEventLogger = uiEventLogger;
|
||||
for (int i = 0; i < HISTORY_SIZE; i++) {
|
||||
mHistoricalRecords[i] = new HistoricalState();
|
||||
}
|
||||
@@ -155,6 +158,7 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
|
||||
}
|
||||
mLastState = mState;
|
||||
mState = state;
|
||||
mUiEventLogger.log(StatusBarStateEvent.fromState(mState));
|
||||
for (RankedListener rl : new ArrayList<>(mListeners)) {
|
||||
rl.mListener.onStateChanged(mState);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.android.internal.logging.UiEvent;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
|
||||
/**
|
||||
* Events for changes in the {@link StatusBarState}.
|
||||
*/
|
||||
public enum StatusBarStateEvent implements UiEventLogger.UiEventEnum {
|
||||
|
||||
@UiEvent(doc = "StatusBarState changed to unknown state")
|
||||
STATUS_BAR_STATE_UNKNOWN(428),
|
||||
|
||||
@UiEvent(doc = "StatusBarState changed to SHADE state")
|
||||
STATUS_BAR_STATE_SHADE(429),
|
||||
|
||||
@UiEvent(doc = "StatusBarState changed to KEYGUARD state")
|
||||
STATUS_BAR_STATE_KEYGUARD(430),
|
||||
|
||||
@UiEvent(doc = "StatusBarState changed to SHADE_LOCKED state")
|
||||
STATUS_BAR_STATE_SHADE_LOCKED(431),
|
||||
|
||||
@UiEvent(doc = "StatusBarState changed to FULLSCREEN_USER_SWITCHER state")
|
||||
STATUS_BAR_STATE_FULLSCREEN_USER_SWITCHER(432);
|
||||
|
||||
private int mId;
|
||||
StatusBarStateEvent(int id) {
|
||||
mId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the event associated with the state.
|
||||
*/
|
||||
public static StatusBarStateEvent fromState(int state) {
|
||||
switch(state) {
|
||||
case StatusBarState.SHADE:
|
||||
return STATUS_BAR_STATE_SHADE;
|
||||
case StatusBarState.KEYGUARD:
|
||||
return STATUS_BAR_STATE_KEYGUARD;
|
||||
case StatusBarState.SHADE_LOCKED:
|
||||
return STATUS_BAR_STATE_SHADE_LOCKED;
|
||||
case StatusBarState.FULLSCREEN_USER_SWITCHER:
|
||||
return STATUS_BAR_STATE_FULLSCREEN_USER_SWITCHER;
|
||||
default:
|
||||
return STATUS_BAR_STATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,6 @@ import android.os.Handler;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.UiEventLoggerImpl;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dagger.qualifiers.UiBackground;
|
||||
@@ -161,13 +159,6 @@ public interface NotificationsModule {
|
||||
return new NotificationPanelLoggerImpl();
|
||||
}
|
||||
|
||||
/** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */
|
||||
@Singleton
|
||||
@Provides
|
||||
static UiEventLogger provideUiEventLogger() {
|
||||
return new UiEventLoggerImpl();
|
||||
}
|
||||
|
||||
/** Provides an instance of {@link NotificationBlockingHelperManager} */
|
||||
@Singleton
|
||||
@Provides
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.UserIcons;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
@@ -61,6 +62,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.qs.DetailAdapter;
|
||||
import com.android.systemui.qs.QSUserSwitcherEvent;
|
||||
import com.android.systemui.qs.tiles.UserDetailView;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||
|
||||
@@ -108,13 +110,15 @@ public class UserSwitcherController implements Dumpable {
|
||||
private int mSecondaryUser = UserHandle.USER_NULL;
|
||||
private Intent mSecondaryUserServiceIntent;
|
||||
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
@Inject
|
||||
public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
|
||||
@Main Handler handler, ActivityStarter activityStarter,
|
||||
BroadcastDispatcher broadcastDispatcher) {
|
||||
BroadcastDispatcher broadcastDispatcher, UiEventLogger uiEventLogger) {
|
||||
mContext = context;
|
||||
mBroadcastDispatcher = broadcastDispatcher;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
if (!UserManager.isGuestUserEphemeral()) {
|
||||
mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
|
||||
}
|
||||
@@ -801,7 +805,7 @@ public class UserSwitcherController implements Dumpable {
|
||||
UserDetailView v;
|
||||
if (!(convertView instanceof UserDetailView)) {
|
||||
v = UserDetailView.inflate(context, parent, false);
|
||||
v.createAndSetAdapter(UserSwitcherController.this);
|
||||
v.createAndSetAdapter(UserSwitcherController.this, mUiEventLogger);
|
||||
} else {
|
||||
v = (UserDetailView) convertView;
|
||||
}
|
||||
@@ -827,6 +831,21 @@ public class UserSwitcherController implements Dumpable {
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.QS_USERDETAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UiEventLogger.UiEventEnum openDetailEvent() {
|
||||
return QSUserSwitcherEvent.QS_USER_DETAIL_OPEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UiEventLogger.UiEventEnum closeDetailEvent() {
|
||||
return QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UiEventLogger.UiEventEnum moreSettingsEvent() {
|
||||
return QSUserSwitcherEvent.QS_USER_MORE_SETTINGS;
|
||||
}
|
||||
};
|
||||
|
||||
private final KeyguardStateController.Callback mCallback =
|
||||
|
||||
@@ -56,9 +56,12 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.systemui.Prefs;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.QSDndEvent;
|
||||
import com.android.systemui.qs.QSEvents;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -103,6 +106,7 @@ public class ZenModePanel extends FrameLayout {
|
||||
private final TransitionHelper mTransitionHelper = new TransitionHelper();
|
||||
private final Uri mForeverId;
|
||||
private final ConfigurableTexts mConfigurableTexts;
|
||||
private final UiEventLogger mUiEventLogger = QSEvents.INSTANCE.getQsUiEventsLogger();
|
||||
|
||||
private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
|
||||
|
||||
@@ -662,6 +666,7 @@ public class ZenModePanel extends FrameLayout {
|
||||
tag.rb.setChecked(true);
|
||||
if (DEBUG) Log.d(mTag, "onCheckedChanged " + conditionId);
|
||||
MetricsLogger.action(mContext, MetricsEvent.QS_DND_CONDITION_SELECT);
|
||||
mUiEventLogger.log(QSDndEvent.QS_DND_CONDITION_SELECT);
|
||||
select(tag.condition);
|
||||
announceConditionSelection(tag);
|
||||
}
|
||||
@@ -767,6 +772,7 @@ public class ZenModePanel extends FrameLayout {
|
||||
|
||||
private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
|
||||
MetricsLogger.action(mContext, MetricsEvent.QS_DND_TIME, up);
|
||||
mUiEventLogger.log(up ? QSDndEvent.QS_DND_TIME_UP : QSDndEvent.QS_DND_TIME_DOWN);
|
||||
Condition newCondition = null;
|
||||
final int N = MINUTE_BUCKETS.length;
|
||||
if (mBucketIndex == -1) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.util.DisplayMetrics;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
|
||||
@@ -65,7 +66,8 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
|
||||
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private DockManager mDockManager = new DockManagerFake();
|
||||
private StatusBarStateController mStatusBarStateController = new StatusBarStateControllerImpl();
|
||||
private StatusBarStateController mStatusBarStateController =
|
||||
new StatusBarStateControllerImpl(new UiEventLoggerFake());
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
@@ -67,7 +68,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
|
||||
FalsingDataProvider falsingDataProvider = new FalsingDataProvider(dm);
|
||||
DeviceConfigProxy deviceConfigProxy = new DeviceConfigProxyFake();
|
||||
DockManager dockManager = new DockManagerFake();
|
||||
mStatusBarStateController = new StatusBarStateControllerImpl();
|
||||
mStatusBarStateController = new StatusBarStateControllerImpl(new UiEventLoggerFake());
|
||||
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
||||
mFalsingManager = new BrightLineFalsingManager(falsingDataProvider,
|
||||
mKeyguardUpdateMonitor, mProximitySensor, deviceConfigProxy, dockManager,
|
||||
|
||||
@@ -16,6 +16,7 @@ package com.android.systemui.qs;
|
||||
|
||||
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_MORE_SETTINGS;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.eq;
|
||||
@@ -33,11 +34,13 @@ import android.view.View;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.qs.DetailAdapter;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -54,10 +57,13 @@ public class QSDetailTest extends SysuiTestCase {
|
||||
private ActivityStarter mActivityStarter;
|
||||
private DetailAdapter mMockDetailAdapter;
|
||||
private TestableLooper mTestableLooper;
|
||||
private UiEventLoggerFake mUiEventLogger;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
mUiEventLogger = QSEvents.INSTANCE.setLoggerForTesting();
|
||||
|
||||
mTestableLooper.runWithLooper(() -> {
|
||||
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
|
||||
mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class);
|
||||
@@ -70,6 +76,19 @@ public class QSDetailTest extends SysuiTestCase {
|
||||
when(mMockDetailAdapter.createDetailView(any(), any(), any()))
|
||||
.thenReturn(mock(View.class));
|
||||
});
|
||||
|
||||
// Only detail in use is the user detail
|
||||
when(mMockDetailAdapter.openDetailEvent())
|
||||
.thenReturn(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN);
|
||||
when(mMockDetailAdapter.closeDetailEvent())
|
||||
.thenReturn(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE);
|
||||
when(mMockDetailAdapter.moreSettingsEvent())
|
||||
.thenReturn(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
QSEvents.INSTANCE.resetLogger();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,9 +98,16 @@ public class QSDetailTest extends SysuiTestCase {
|
||||
|
||||
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
|
||||
verify(mMetricsLogger).visible(eq(mMockDetailAdapter.getMetricsCategory()));
|
||||
assertEquals(1, mUiEventLogger.numLogs());
|
||||
assertEquals(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN.getId(), mUiEventLogger.eventId(0));
|
||||
mUiEventLogger.getLogs().clear();
|
||||
|
||||
mQsDetail.handleShowingDetail(null, 0, 0, false);
|
||||
verify(mMetricsLogger).hidden(eq(mMockDetailAdapter.getMetricsCategory()));
|
||||
|
||||
assertEquals(1, mUiEventLogger.numLogs());
|
||||
assertEquals(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE.getId(), mUiEventLogger.eventId(0));
|
||||
|
||||
ViewUtils.detachView(mQsDetail);
|
||||
mTestableLooper.processAllMessages();
|
||||
}
|
||||
@@ -92,10 +118,13 @@ public class QSDetailTest extends SysuiTestCase {
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
mQsDetail.handleShowingDetail(mMockDetailAdapter, 0, 0, false);
|
||||
mQsDetail.findViewById(android.R.id.button2).performClick();
|
||||
mUiEventLogger.getLogs().clear();
|
||||
mQsDetail.requireViewById(android.R.id.button2).performClick();
|
||||
|
||||
int metricsCategory = mMockDetailAdapter.getMetricsCategory();
|
||||
verify(mMetricsLogger).action(eq(ACTION_QS_MORE_SETTINGS), eq(metricsCategory));
|
||||
assertEquals(1, mUiEventLogger.numLogs());
|
||||
assertEquals(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS.getId(), mUiEventLogger.eventId(0));
|
||||
|
||||
verify(mActivityStarter).postStartActivityDismissingKeyguard(any(), anyInt());
|
||||
|
||||
@@ -105,7 +134,9 @@ public class QSDetailTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testNullAdapterClick() {
|
||||
mQsDetail.setupDetailFooter(mock(DetailAdapter.class));
|
||||
mQsDetail.findViewById(android.R.id.button2).performClick();
|
||||
DetailAdapter mock = mock(DetailAdapter.class);
|
||||
when(mock.moreSettingsEvent()).thenReturn(DetailAdapter.INVALID);
|
||||
mQsDetail.setupDetailFooter(mock);
|
||||
mQsDetail.requireViewById(android.R.id.button2).performClick();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import androidx.test.filters.SmallTest;
|
||||
import androidx.test.filters.Suppress;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.keyguard.CarrierText;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
@@ -106,7 +107,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
|
||||
mock(PluginManager.class), mock(TunerService.class),
|
||||
() -> mock(AutoTileManager.class), mock(DumpManager.class),
|
||||
mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
|
||||
mock(QSLogger.class));
|
||||
mock(QSLogger.class), mock(UiEventLogger.class));
|
||||
qs.setHost(host);
|
||||
|
||||
qs.setListening(true);
|
||||
|
||||
@@ -35,6 +35,7 @@ import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
@@ -94,17 +95,19 @@ public class QSPanelTest extends SysuiTestCase {
|
||||
private ActivityStarter mActivityStarter;
|
||||
@Mock
|
||||
private NotificationEntryManager mEntryManager;
|
||||
private UiEventLoggerFake mUiEventLogger;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
mUiEventLogger = new UiEventLoggerFake();
|
||||
mTestableLooper.runWithLooper(() -> {
|
||||
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
|
||||
mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
|
||||
mQSLogger, mForegroundExecutor, mBackgroundExecutor,
|
||||
mLocalBluetoothManager, mActivityStarter, mEntryManager);
|
||||
mLocalBluetoothManager, mActivityStarter, mEntryManager, mUiEventLogger);
|
||||
// Provides a parent with non-zero size for QSPanel
|
||||
mParentView = new FrameLayout(mContext);
|
||||
mParentView.addView(mQsPanel);
|
||||
@@ -124,9 +127,17 @@ public class QSPanelTest extends SysuiTestCase {
|
||||
mQsPanel.setExpanded(true);
|
||||
verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
|
||||
verify(mQSLogger).logPanelExpanded(true, mQsPanel.getDumpableTag());
|
||||
assertEquals(1, mUiEventLogger.numLogs());
|
||||
assertEquals(QSEvent.QS_PANEL_EXPANDED.getId(), mUiEventLogger.eventId(0));
|
||||
mUiEventLogger.getLogs().clear();
|
||||
|
||||
mQsPanel.setExpanded(false);
|
||||
verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
|
||||
verify(mQSLogger).logPanelExpanded(false, mQsPanel.getDumpableTag());
|
||||
assertEquals(1, mUiEventLogger.numLogs());
|
||||
assertEquals(QSEvent.QS_PANEL_COLLAPSED.getId(), mUiEventLogger.eventId(0));
|
||||
mUiEventLogger.getLogs().clear();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.util.CollectionUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
@@ -50,7 +51,6 @@ import com.android.systemui.plugins.qs.QSFactory;
|
||||
import com.android.systemui.plugins.qs.QSTile;
|
||||
import com.android.systemui.qs.external.CustomTile;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
|
||||
import com.android.systemui.qs.tileimpl.QSTileImpl;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.phone.AutoTileManager;
|
||||
@@ -105,6 +105,8 @@ public class QSTileHostTest extends SysuiTestCase {
|
||||
private QSLogger mQSLogger;
|
||||
@Mock
|
||||
private CustomTile mCustomTile;
|
||||
@Mock
|
||||
private UiEventLogger mUiEventLogger;
|
||||
|
||||
private Handler mHandler;
|
||||
private TestableLooper mLooper;
|
||||
@@ -117,7 +119,7 @@ public class QSTileHostTest extends SysuiTestCase {
|
||||
mHandler = new Handler(mLooper.getLooper());
|
||||
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
|
||||
mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
|
||||
mBroadcastDispatcher, mStatusBar, mQSLogger);
|
||||
mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger);
|
||||
setUpTileFactory();
|
||||
|
||||
// Override this config so there are no unexpected tiles
|
||||
@@ -298,10 +300,11 @@ public class QSTileHostTest extends SysuiTestCase {
|
||||
QSFactory defaultFactory, Handler mainHandler, Looper bgLooper,
|
||||
PluginManager pluginManager, TunerService tunerService,
|
||||
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
|
||||
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger) {
|
||||
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger,
|
||||
UiEventLogger uiEventLogger) {
|
||||
super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
|
||||
tunerService, autoTiles, dumpManager, broadcastDispatcher,
|
||||
Optional.of(statusBar), qsLogger);
|
||||
Optional.of(statusBar), qsLogger, uiEventLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.qs.QSTileHost;
|
||||
|
||||
@@ -42,7 +43,8 @@ public class TileAdapterTest extends SysuiTestCase {
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
TestableLooper.get(this).runWithLooper(() -> mTileAdapter = new TileAdapter(mContext));
|
||||
TestableLooper.get(this).runWithLooper(() -> mTileAdapter =
|
||||
new TileAdapter(mContext, new UiEventLoggerFake()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
@@ -81,6 +82,8 @@ public class TileServicesTest extends SysuiTestCase {
|
||||
private StatusBar mStatusBar;
|
||||
@Mock
|
||||
private QSLogger mQSLogger;
|
||||
@Mock
|
||||
private UiEventLogger mUiEventLogger;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -98,7 +101,8 @@ public class TileServicesTest extends SysuiTestCase {
|
||||
mDumpManager,
|
||||
mBroadcastDispatcher,
|
||||
Optional.of(mStatusBar),
|
||||
mQSLogger);
|
||||
mQSLogger,
|
||||
mUiEventLogger);
|
||||
mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,16 @@ import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.qs.QSTile;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.qs.QSEvent;
|
||||
import com.android.systemui.qs.QSHost;
|
||||
import com.android.systemui.qs.QSTileHost;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
@@ -83,6 +87,8 @@ public class QSTileImplTest extends SysuiTestCase {
|
||||
private QSTileHost mHost;
|
||||
private MetricsLogger mMetricsLogger;
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
private UiEventLoggerFake mUiEventLoggerFake;
|
||||
private InstanceId mInstanceId = InstanceId.fakeInstanceId(5);
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<LogMaker> mLogCaptor;
|
||||
@@ -94,12 +100,15 @@ public class QSTileImplTest extends SysuiTestCase {
|
||||
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
|
||||
mDependency.injectMockDependency(ActivityStarter.class);
|
||||
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
|
||||
mUiEventLoggerFake = new UiEventLoggerFake();
|
||||
mStatusBarStateController =
|
||||
mDependency.injectMockDependency(StatusBarStateController.class);
|
||||
mHost = mock(QSTileHost.class);
|
||||
when(mHost.indexOf(SPEC)).thenReturn(POSITION);
|
||||
when(mHost.getContext()).thenReturn(mContext.getBaseContext());
|
||||
when(mHost.getQSLogger()).thenReturn(mQsLogger);
|
||||
when(mHost.getUiEventLogger()).thenReturn(mUiEventLoggerFake);
|
||||
when(mHost.getNewInstanceId()).thenReturn(mInstanceId);
|
||||
|
||||
mTile = spy(new TileImpl(mHost));
|
||||
mTile.mHandler = mTile.new H(mTestableLooper.getLooper());
|
||||
@@ -110,6 +119,9 @@ public class QSTileImplTest extends SysuiTestCase {
|
||||
public void testClick_Metrics() {
|
||||
mTile.click();
|
||||
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_CLICK)));
|
||||
assertEquals(1, mUiEventLoggerFake.numLogs());
|
||||
UiEventLoggerFake.FakeUiEvent event = mUiEventLoggerFake.get(0);
|
||||
assertEvent(QSEvent.QS_ACTION_CLICK, event);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,6 +145,9 @@ public class QSTileImplTest extends SysuiTestCase {
|
||||
public void testSecondaryClick_Metrics() {
|
||||
mTile.secondaryClick();
|
||||
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_SECONDARY_CLICK)));
|
||||
assertEquals(1, mUiEventLoggerFake.numLogs());
|
||||
UiEventLoggerFake.FakeUiEvent event = mUiEventLoggerFake.get(0);
|
||||
assertEvent(QSEvent.QS_ACTION_SECONDARY_CLICK, event);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,6 +171,9 @@ public class QSTileImplTest extends SysuiTestCase {
|
||||
public void testLongClick_Metrics() {
|
||||
mTile.longClick();
|
||||
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_LONG_PRESS)));
|
||||
assertEquals(1, mUiEventLoggerFake.numLogs());
|
||||
UiEventLoggerFake.FakeUiEvent event = mUiEventLoggerFake.get(0);
|
||||
assertEvent(QSEvent.QS_ACTION_LONG_PRESS, event);
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +267,13 @@ public class QSTileImplTest extends SysuiTestCase {
|
||||
verify(mQsLogger).logTileChangeListening(SPEC, false);
|
||||
}
|
||||
|
||||
private void assertEvent(UiEventLogger.UiEventEnum eventType,
|
||||
UiEventLoggerFake.FakeUiEvent fakeEvent) {
|
||||
assertEquals(eventType.getId(), fakeEvent.eventId);
|
||||
assertEquals(SPEC, fakeEvent.packageName);
|
||||
assertEquals(mInstanceId, fakeEvent.instanceId);
|
||||
}
|
||||
|
||||
private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
|
||||
|
||||
private final int mCategory;
|
||||
|
||||
@@ -24,8 +24,11 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.qs.QSUserSwitcherEvent
|
||||
import com.android.systemui.statusbar.policy.UserSwitcherController
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -50,15 +53,17 @@ class UserDetailViewAdapterTest : SysuiTestCase() {
|
||||
@Mock private lateinit var mPicture: Bitmap
|
||||
@Mock private lateinit var mLayoutInflater: LayoutInflater
|
||||
private lateinit var adapter: UserDetailView.Adapter
|
||||
private lateinit var uiEventLogger: UiEventLoggerFake
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
uiEventLogger = UiEventLoggerFake()
|
||||
|
||||
mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater)
|
||||
`when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
|
||||
.thenReturn(mInflatedUserDetailItemView)
|
||||
adapter = UserDetailView.Adapter(mContext, mUserSwitcherController)
|
||||
adapter = UserDetailView.Adapter(mContext, mUserSwitcherController, uiEventLogger)
|
||||
}
|
||||
|
||||
private fun clickableTest(
|
||||
@@ -76,6 +81,17 @@ class UserDetailViewAdapterTest : SysuiTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserSwitchLog() {
|
||||
val user = createUserRecord(false /* current */, false /* guest */)
|
||||
val v = adapter.createUserDetailItemView(View(mContext), mParent, user)
|
||||
`when`(v.tag).thenReturn(user)
|
||||
adapter.onClick(v)
|
||||
|
||||
assertEquals(1, uiEventLogger.numLogs())
|
||||
assertEquals(QSUserSwitcherEvent.QS_USER_SWITCH.id, uiEventLogger.eventId(0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGuestIsClickable_differentViews_notCurrent() {
|
||||
clickableTest(false, true, mOtherView, true)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class StatusBarStateControllerImplTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var controller: StatusBarStateControllerImpl
|
||||
private lateinit var uiEventLogger: UiEventLoggerFake
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
uiEventLogger = UiEventLoggerFake()
|
||||
controller = StatusBarStateControllerImpl(uiEventLogger)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testChangeState_logged() {
|
||||
TestableLooper.get(this).runWithLooper {
|
||||
controller.state = StatusBarState.FULLSCREEN_USER_SWITCHER
|
||||
controller.state = StatusBarState.KEYGUARD
|
||||
controller.state = StatusBarState.SHADE
|
||||
controller.state = StatusBarState.SHADE_LOCKED
|
||||
}
|
||||
|
||||
val logs = uiEventLogger.logs
|
||||
assertEquals(4, logs.size)
|
||||
val ids = logs.map(UiEventLoggerFake.FakeUiEvent::eventId)
|
||||
assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_FULLSCREEN_USER_SWITCHER.id, ids[0])
|
||||
assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_KEYGUARD.id, ids[1])
|
||||
assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_SHADE.id, ids[2])
|
||||
assertEquals(StatusBarStateEvent.STATUS_BAR_STATE_SHADE_LOCKED.id, ids[3])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class StatusBarStateEventTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun testFromState() {
|
||||
val events = listOf(
|
||||
StatusBarStateEvent.STATUS_BAR_STATE_SHADE,
|
||||
StatusBarStateEvent.STATUS_BAR_STATE_SHADE_LOCKED,
|
||||
StatusBarStateEvent.STATUS_BAR_STATE_KEYGUARD,
|
||||
StatusBarStateEvent.STATUS_BAR_STATE_FULLSCREEN_USER_SWITCHER,
|
||||
StatusBarStateEvent.STATUS_BAR_STATE_UNKNOWN
|
||||
)
|
||||
val states = listOf(
|
||||
StatusBarState.SHADE,
|
||||
StatusBarState.SHADE_LOCKED,
|
||||
StatusBarState.KEYGUARD,
|
||||
StatusBarState.FULLSCREEN_USER_SWITCHER,
|
||||
-1
|
||||
)
|
||||
events.zip(states).forEach { (event, state) ->
|
||||
assertEquals(event, StatusBarStateEvent.fromState(state))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ import android.view.accessibility.AccessibilityManager;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake;
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.keyguard.KeyguardClockSwitch;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
@@ -207,7 +208,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
NotificationWakeUpCoordinator coordinator =
|
||||
new NotificationWakeUpCoordinator(
|
||||
mock(HeadsUpManagerPhone.class),
|
||||
new StatusBarStateControllerImpl(),
|
||||
new StatusBarStateControllerImpl(new UiEventLoggerFake()),
|
||||
mKeyguardBypassController,
|
||||
mDozeParameters);
|
||||
PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
|
||||
|
||||
Reference in New Issue
Block a user