Add QSLogs using new loggers

Test: manual using DumpController
Test: atest

Change-Id: Id665ff047d60ddfa5f8f2fe907b7e20f84bd0013
This commit is contained in:
Fabian Kozynski
2019-10-24 10:01:04 -04:00
parent 753216ebc7
commit ca30f57095
35 changed files with 392 additions and 81 deletions

View File

@@ -14,6 +14,7 @@
package com.android.systemui.plugins.qs;
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.metrics.LogMaker;
@@ -107,6 +108,12 @@ public interface QSTile {
public int getPadding() {
return 0;
}
@Override
@NonNull
public String toString() {
return "Icon";
}
}
@ProvidesInterface(version = State.VERSION)

View File

@@ -61,6 +61,18 @@ public class LogModule {
return buffer;
}
/** Provides a logging buffer for all logs related to Quick Settings. */
@Provides
@Singleton
@QSLog
public static LogBuffer provideQuickSettingsLogBuffer(
LogcatEchoTracker bufferFilter,
DumpController dumpController) {
LogBuffer buffer = new LogBuffer("QSLog", 500, 10, bufferFilter);
buffer.attach(dumpController);
return buffer;
}
/** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
@Provides
@Singleton

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2019 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 QS-related messages. */
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface QSLog {
}

View File

@@ -18,6 +18,7 @@ import android.content.Context;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.logging.QSLogger;
import java.util.Collection;
@@ -27,6 +28,7 @@ public interface QSHost {
void forceCollapsePanels();
void openPanels();
Context getContext();
QSLogger getQSLogger();
Collection<QSTile> getTiles();
void addCallback(Callback callback);
void removeCallback(Callback callback);

View File

@@ -57,6 +57,7 @@ import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.QSHost.Callback;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSliderView;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -69,6 +70,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
@@ -84,6 +86,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
protected final Context mContext;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
private String mCachedSpecs = "";
protected final View mBrightnessView;
private final H mHandler = new H();
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -101,6 +104,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
private QSDetail.Callback mCallback;
private BrightnessController mBrightnessController;
private DumpController mDumpController;
private final QSLogger mQSLogger;
protected QSTileHost mHost;
protected QSSecurityFooter mFooter;
@@ -140,23 +144,17 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
};
public QSPanel(Context context) {
this(context, null);
}
public QSPanel(Context context, AttributeSet attrs) {
this(context, attrs, null);
}
public QSPanel(Context context, AttributeSet attrs, DumpController dumpController) {
this(context, attrs, dumpController, Dependency.get(BroadcastDispatcher.class));
}
@Inject
public QSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
DumpController dumpController, BroadcastDispatcher broadcastDispatcher) {
public QSPanel(
@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
DumpController dumpController,
BroadcastDispatcher broadcastDispatcher,
QSLogger qsLogger
) {
super(context, attrs);
mContext = context;
mQSLogger = qsLogger;
setOrientation(VERTICAL);
@@ -166,6 +164,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
R.layout.qs_paged_tile_layout, this, false);
mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), mCachedSpecs);
mTileLayout.setListening(mListening);
addView((View) mTileLayout);
@@ -521,6 +520,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mQSLogger.logPanelExpanded(expanded, getDumpableTag());
mExpanded = expanded;
if (!mExpanded && mTileLayout instanceof PagedTileLayout) {
((PagedTileLayout) mTileLayout).setCurrentItem(0, false);
@@ -547,6 +547,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
if (mListening == listening) return;
mListening = listening;
if (mTileLayout != null) {
mQSLogger.logAllTilesChangeListening(listening, getDumpableTag(), mCachedSpecs);
mTileLayout.setListening(listening);
}
if (mListening) {
@@ -554,6 +555,12 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
private String getTilesSpecs() {
return mRecords.stream()
.map(tileRecord -> tileRecord.tile.getTileSpec())
.collect(Collectors.joining(","));
}
public void setListening(boolean listening, boolean expanded) {
setListening(listening && expanded);
getFooter().setListening(listening);
@@ -611,6 +618,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
record.tile.removeCallback(record.callback);
}
mRecords.clear();
mCachedSpecs = "";
for (QSTile tile : tiles) {
addTile(tile, collapsedView);
}
@@ -675,6 +683,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
r.tileView.init(r.tile);
r.tile.refreshState();
mRecords.add(r);
mCachedSpecs = getTilesSpecs();
if (mTileLayout != null) {
mTileLayout.addTile(r);

View File

@@ -43,6 +43,7 @@ import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.external.TileLifecycleManager;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.AutoTileManager;
@@ -82,6 +83,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
private final PluginManager mPluginManager;
private final DumpController mDumpController;
private final BroadcastDispatcher mBroadcastDispatcher;
private final QSLogger mQSLogger;
private final List<Callback> mCallbacks = new ArrayList<>();
private AutoTileManager mAutoTiles;
@@ -101,12 +103,14 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
Provider<AutoTileManager> autoTiles,
DumpController dumpController,
BroadcastDispatcher broadcastDispatcher,
Optional<StatusBar> statusBarOptional) {
Optional<StatusBar> statusBarOptional,
QSLogger qsLogger) {
mIconController = iconController;
mContext = context;
mTunerService = tunerService;
mPluginManager = pluginManager;
mDumpController = dumpController;
mQSLogger = qsLogger;
mBroadcastDispatcher = broadcastDispatcher;
mServices = new TileServices(this, bgLooper, mBroadcastDispatcher);
@@ -159,6 +163,10 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
onTuningChanged(TILES_SETTING, value);
}
public QSLogger getQSLogger() {
return mQSLogger;
}
@Override
public void addCallback(Callback callback) {
mCallbacks.add(callback);
@@ -223,6 +231,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach(
tile -> {
Log.d(TAG, "Destroying tile: " + tile.getKey());
mQSLogger.logTileDestroyed(tile.getKey(), "Tile removed");
tile.getValue().destroy();
});
final LinkedHashMap<String, QSTile> newTiles = new LinkedHashMap<>();
@@ -237,9 +246,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
tile.userSwitch(currentUser);
}
newTiles.put(tileSpec, tile);
mQSLogger.logTileAdded(tileSpec);
} else {
tile.destroy();
Log.d(TAG, "Destroying not available tile: " + tileSpec);
mQSLogger.logTileDestroyed(tileSpec, "Tile not available");
}
} else {
Log.d(TAG, "Creating tile: " + tileSpec);
@@ -249,9 +260,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
if (tile.isAvailable()) {
tile.setTileSpec(tileSpec);
newTiles.put(tileSpec, tile);
mQSLogger.logTileAdded(tileSpec);
} else {
tile.destroy();
Log.d(TAG, "Destroying not available tile: " + tileSpec);
mQSLogger.logTileDestroyed(tileSpec, "Tile not available");
}
}
} catch (Throwable t) {

View File

@@ -29,10 +29,12 @@ import android.widget.LinearLayout;
import com.android.systemui.Dependency;
import com.android.systemui.DumpController;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.Utils;
@@ -65,9 +67,14 @@ public class QuickQSPanel extends QSPanel {
private QSTileLayout mRegularTileLayout;
@Inject
public QuickQSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
DumpController dumpController) {
super(context, attrs, dumpController);
public QuickQSPanel(
@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
DumpController dumpController,
BroadcastDispatcher broadcastDispatcher,
QSLogger qsLogger
) {
super(context, attrs, dumpController, broadcastDispatcher, qsLogger);
if (mFooter != null) {
removeView(mFooter.getView());
}

View File

@@ -210,8 +210,10 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (mListening == listening) return;
mListening = listening;
try {
if (listening) {
updateDefaultTileAndIcon();

View File

@@ -0,0 +1,147 @@
/*
* Copyright (C) 2019 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.logging
import android.service.quicksettings.Tile
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.VERBOSE
import com.android.systemui.log.LogMessage
import com.android.systemui.log.dagger.QSLog
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.statusbar.StatusBarState
import javax.inject.Inject
private const val TAG = "QSLog"
class QSLogger @Inject constructor(
@QSLog private val buffer: LogBuffer
) {
fun logTileAdded(tileSpec: String) {
log(DEBUG, {
str1 = tileSpec
}, {
"[$str1] Tile added"
})
}
fun logTileDestroyed(tileSpec: String, reason: String) {
log(DEBUG, {
str1 = tileSpec
str2 = reason
}, {
"[$str1] Tile destroyed. Reason: $str2"
})
}
fun logTileChangeListening(tileSpec: String, listening: Boolean) {
log(VERBOSE, {
bool1 = listening
str1 = tileSpec
}, {
"[$str1] Tile listening=$bool1"
})
}
fun logAllTilesChangeListening(listening: Boolean, containerName: String, allSpecs: String) {
log(DEBUG, {
bool1 = listening
str1 = containerName
str2 = allSpecs
}, {
"Tiles listening=$bool1 in $str1. $str2"
})
}
fun logTileClick(tileSpec: String, statusBarState: Int, state: Int) {
log(DEBUG, {
str1 = tileSpec
int1 = statusBarState
str2 = StatusBarState.toShortString(statusBarState)
str3 = toStateString(state)
}, {
"[$str1] Tile clicked. StatusBarState=$str2. TileState=$str3"
})
}
fun logTileSecondaryClick(tileSpec: String, statusBarState: Int, state: Int) {
log(DEBUG, {
str1 = tileSpec
int1 = statusBarState
str2 = StatusBarState.toShortString(statusBarState)
str3 = toStateString(state)
}, {
"[$str1] Tile long clicked. StatusBarState=$str2. TileState=$str3"
})
}
fun logTileLongClick(tileSpec: String, statusBarState: Int, state: Int) {
log(DEBUG, {
str1 = tileSpec
int1 = statusBarState
str2 = StatusBarState.toShortString(statusBarState)
str3 = toStateString(state)
}, {
"[$str1] Tile long clicked. StatusBarState=$str2. TileState=$str3"
})
}
fun logTileUpdated(tileSpec: String, state: QSTile.State) {
log(VERBOSE, {
str1 = tileSpec
str2 = state.label.toString()
str3 = state.icon.toString()
int1 = state.state
if (state is QSTile.SignalState) {
bool1 = true
bool2 = state.activityIn
bool3 = state.activityOut
}
}, {
"[$str1] Tile updated. Label=$str2. State=$int1. Icon=$str3." +
if (bool1) " Activity in/out=$bool2/$bool3" else ""
})
}
fun logPanelExpanded(expanded: Boolean, containerName: String) {
log(DEBUG, {
str1 = containerName
bool1 = expanded
}, {
"$str1 expanded=$bool1"
})
}
private fun toStateString(state: Int): String {
return when (state) {
Tile.STATE_ACTIVE -> "active"
Tile.STATE_INACTIVE -> "inactive"
Tile.STATE_UNAVAILABLE -> "unavailable"
else -> "wrong state"
}
}
private inline fun log(
logLevel: LogLevel,
initializer: LogMessage.() -> Unit,
noinline printer: LogMessage.() -> String
) {
buffer.log(TAG, logLevel, initializer, printer)
}
}

View File

@@ -27,6 +27,8 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -41,7 +43,6 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
@@ -63,6 +64,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.PagedTileLayout.TilePage;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tiles.QSSettingsControllerKt;
import com.android.systemui.qs.tiles.QSSettingsPanel;
@@ -95,6 +97,7 @@ 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 QSLogger mQSLogger;
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private final Object mStaleListener = new Object();
@@ -156,6 +159,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
mState = newTileState();
mTmpState = newTileState();
mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption();
mQSLogger = host.getQSLogger();
}
protected final void resetStates() {
@@ -243,6 +247,7 @@ 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())));
mQSLogger.logTileClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
mHandler.sendEmptyMessage(H.CLICK);
}
@@ -250,6 +255,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())));
mQSLogger.logTileSecondaryClick(mTileSpec, mStatusBarStateController.getState(),
mState.state);
mHandler.sendEmptyMessage(H.SECONDARY_CLICK);
}
@@ -257,6 +264,7 @@ 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())));
mQSLogger.logTileLongClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
mHandler.sendEmptyMessage(H.LONG_CLICK);
Prefs.putInt(
@@ -359,6 +367,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
handleUpdateState(mTmpState, arg);
final boolean changed = mTmpState.copyTo(mState);
if (changed) {
mQSLogger.logTileUpdated(mTileSpec, mState);
handleStateChanged();
}
mHandler.removeMessages(H.STALE);
@@ -445,9 +454,15 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
mIsFullQs = 0;
}
protected abstract void handleSetListening(boolean listening);
@CallSuper
protected void handleSetListening(boolean listening) {
if (mTileSpec != null) {
mQSLogger.logTileChangeListening(mTileSpec, listening);
}
}
protected void handleDestroy() {
mQSLogger.logTileDestroyed(mTileSpec, "Handle destroy");
if (mListeners.size() != 0) {
handleSetListening(false);
}
@@ -592,6 +607,12 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
public Drawable getInvisibleDrawable(Context context) {
return mInvisibleDrawable;
}
@Override
@NonNull
public String toString() {
return "DrawableIcon";
}
}
public static class DrawableIconWithRes extends DrawableIcon {
@@ -606,6 +627,12 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
public boolean equals(Object o) {
return o instanceof DrawableIconWithRes && ((DrawableIconWithRes) o).mId == mId;
}
@Override
@NonNull
public String toString() {
return String.format("DrawableIconWithRes[resId=0x%08x]", mId);
}
}
public static class ResourceIcon extends Icon {
@@ -642,6 +669,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
}
@Override
@NonNull
public String toString() {
return String.format("ResourceIcon[resId=0x%08x]", mResId);
}
@@ -660,6 +688,12 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
// workaround: get a clean state for every new AVD
return context.getDrawable(mAnimatedResId).getConstantState().newDrawable();
}
@Override
@NonNull
public String toString() {
return String.format("AnimationIcon[resId=0x%08x]", mResId);
}
}
/**

View File

@@ -130,6 +130,7 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> {
}
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (mListening == listening) return;
mListening = listening;
if (listening) {

View File

@@ -74,6 +74,7 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
mSetting.setListening(listening);
}

View File

@@ -81,10 +81,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
return new BooleanState();
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
protected void handleClick() {
// Secondary clicks are header clicks, just toggle.

View File

@@ -97,6 +97,7 @@ public class CastTile extends QSTileImpl<BooleanState> {
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (DEBUG) Log.d(TAG, "handleSetListening " + listening);
if (!listening) {
mController.setDiscovering(false);

View File

@@ -89,10 +89,6 @@ public class CellularTile extends QSTileImpl<SignalState> {
return mDetailAdapter;
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
public Intent getLongClickIntent() {
if (getState().state == Tile.STATE_UNAVAILABLE) {

View File

@@ -66,6 +66,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> {
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
mSetting.setListening(listening);
}

View File

@@ -49,10 +49,6 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements
return new BooleanState();
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
public Intent getLongClickIntent() {
return new Intent(Settings.ACTION_DATA_SAVER_SETTINGS);

View File

@@ -289,6 +289,7 @@ public class DndTile extends QSTileImpl<BooleanState> {
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (mListening == listening) return;
mListening = listening;
if (mListening) {

View File

@@ -57,10 +57,6 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
return state;
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
protected void handleUserSwitch(int newUserId) {
}

View File

@@ -69,6 +69,7 @@ public class HotspotTile extends QSTileImpl<BooleanState> {
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (mListening == listening) return;
mListening = listening;
if (listening) {

View File

@@ -60,10 +60,6 @@ public class LocationTile extends QSTileImpl<BooleanState> {
return new BooleanState();
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
public Intent getLongClickIntent() {
return new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);

View File

@@ -57,6 +57,7 @@ public class NfcTile extends QSTileImpl<BooleanState> {
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
mListening = listening;
if (mListening) {
mBroadcastDispatcher.registerReceiver(mNfcReceiver,

View File

@@ -190,6 +190,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements
@Override
protected void handleSetListening(boolean listening) {
super.handleSetListening(listening);
mIsListening = listening;
if (listening) {
mListener.setCallback(this);

View File

@@ -51,9 +51,6 @@ public class RotationLockTile extends QSTileImpl<BooleanState> {
return new BooleanState();
}
public void handleSetListening(boolean listening) {
}
@Override
public Intent getLongClickIntent() {
return new Intent(Settings.ACTION_DISPLAY_SETTINGS);

View File

@@ -104,10 +104,6 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> {
return null;
}
@Override
protected void handleSetListening(boolean listening) {
}
@Override
public CharSequence getTileLabel() {
return mContext.getString(R.string.quick_settings_screen_record_label);

View File

@@ -32,10 +32,11 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import javax.inject.Inject;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import javax.inject.Inject;
/**
* Quick Settings tile for: Night Mode / Dark Theme / Dark Mode.
*
@@ -140,10 +141,6 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
return new Intent(Settings.ACTION_DARK_THEME_SETTINGS);
}
@Override
protected void handleSetListening(boolean listening) {
}
@Override
public CharSequence getTileLabel() {
return getState().label;

View File

@@ -72,10 +72,6 @@ public class UserTile extends QSTileImpl<State> implements UserInfoController.On
return MetricsEvent.QS_USER_TILE;
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
public CharSequence getTileLabel() {
return getState().label;

View File

@@ -83,10 +83,6 @@ public class WifiTile extends QSTileImpl<SignalState> {
return new SignalState();
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
public void setDetailListening(boolean listening) {
if (listening) {

View File

@@ -49,10 +49,6 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements
return new BooleanState();
}
@Override
public void handleSetListening(boolean listening) {
}
@Override
public Intent getLongClickIntent() {
return new Intent(Settings.ACTION_MANAGED_PROFILE_SETTINGS);

View File

@@ -434,6 +434,7 @@ public class GarbageMonitor implements Dumpable {
@Override
public void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (gm != null) gm.setTile(listening ? this : null);
final ActivityManager am = mContext.getSystemService(ActivityManager.class);

View File

@@ -42,6 +42,7 @@ import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
@@ -104,7 +105,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mock(QSFactoryImpl.class), new Handler(), Looper.myLooper(),
mock(PluginManager.class), mock(TunerService.class),
() -> mock(AutoTileManager.class), mock(DumpController.class),
mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)));
mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
mock(QSLogger.class));
qs.setHost(host);
qs.setListening(true);

View File

@@ -35,9 +35,12 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import org.junit.Before;
@@ -65,6 +68,12 @@ public class QSPanelTest extends SysuiTestCase {
private QSCustomizer mCustomizer;
@Mock
private QSTileImpl dndTile;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
@Mock
private DumpController mDumpController;
@Mock
private QSLogger mQSLogger;
private ViewGroup mParentView;
@Mock
private QSDetail.Callback mCallback;
@@ -78,7 +87,8 @@ public class QSPanelTest extends SysuiTestCase {
mTestableLooper = TestableLooper.get(this);
mTestableLooper.runWithLooper(() -> {
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
mQsPanel = new QSPanel(mContext, null);
mQsPanel = new QSPanel(mContext, null, mDumpController, mBroadcastDispatcher,
mQSLogger);
// Provides a parent with non-zero size for QSPanel
mParentView = new FrameLayout(mContext);
mParentView.addView(mQsPanel);
@@ -97,8 +107,10 @@ public class QSPanelTest extends SysuiTestCase {
public void testSetExpanded_Metrics() {
mQsPanel.setExpanded(true);
verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
verify(mQSLogger).logPanelExpanded(true, mQsPanel.getDumpableTag());
mQsPanel.setExpanded(false);
verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
verify(mQSLogger).logPanelExpanded(false, mQsPanel.getDumpableTag());
}
@Test
@@ -110,6 +122,14 @@ public class QSPanelTest extends SysuiTestCase {
verify(mCallback).onShowingDetail(any(), anyInt(), anyInt());
}
@Test
public void setListening() {
when(dndTile.getTileSpec()).thenReturn("dnd");
mQsPanel.setListening(true);
verify(mQSLogger).logAllTilesChangeListening(true, mQsPanel.getDumpableTag(), "dnd");
}
/* @Test
public void testOpenDetailsWithNullParameter_NoException() {
mTestableLooper.processAllMessages();

View File

@@ -23,6 +23,7 @@ import static junit.framework.TestCase.assertFalse;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -45,6 +46,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
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;
@@ -95,6 +97,8 @@ public class QSTileHostTest extends SysuiTestCase {
@Mock
private StatusBar mStatusBar;
@Mock
private QSLogger mQSLogger;
@Mock
private CustomTile mCustomTile;
private Handler mHandler;
@@ -108,7 +112,7 @@ public class QSTileHostTest extends SysuiTestCase {
mHandler = new Handler(mLooper.getLooper());
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpController,
mBroadcastDispatcher, mStatusBar);
mBroadcastDispatcher, mStatusBar, mQSLogger);
setUpTileFactory();
Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING,
"", ActivityManager.getCurrentUser());
@@ -187,6 +191,7 @@ public class QSTileHostTest extends SysuiTestCase {
assertEquals(1, mQSTileHost.getTiles().size());
QSTile element = CollectionUtils.firstOrNull(mQSTileHost.getTiles());
assertTrue(element instanceof TestTile1);
verify(mQSLogger).logTileAdded("spec1");
}
@Test
@@ -200,6 +205,9 @@ public class QSTileHostTest extends SysuiTestCase {
QSTile[] elements = mQSTileHost.getTiles().toArray(new QSTile[0]);
assertTrue(elements[0] instanceof TestTile1);
assertTrue(elements[1] instanceof TestTile2);
verify(mQSLogger).logTileAdded("spec1");
verify(mQSLogger).logTileAdded("spec2");
}
@Test
@@ -210,6 +218,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "default");
assertEquals(1, mQSTileHost.getTiles().size());
assertEquals(mCustomTile, CollectionUtils.firstOrNull(mQSTileHost.getTiles()));
verify(mQSLogger).logTileAdded(CUSTOM_TILE_SPEC);
}
private static class TestQSTileHost extends QSTileHost {
@@ -217,10 +227,10 @@ public class QSTileHostTest extends SysuiTestCase {
QSFactoryImpl defaultFactory, Handler mainHandler, Looper bgLooper,
PluginManager pluginManager, TunerService tunerService,
Provider<AutoTileManager> autoTiles, DumpController dumpController,
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar) {
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger) {
super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
tunerService, autoTiles, dumpController, broadcastDispatcher,
Optional.of(statusBar));
Optional.of(statusBar), qsLogger);
}
@Override
@@ -279,9 +289,6 @@ public class QSTileHostTest extends SysuiTestCase {
return null;
}
@Override
protected void handleSetListening(boolean listening) {}
@Override
public CharSequence getTileLabel() {
return null;

View File

@@ -34,6 +34,7 @@ import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.AutoTileManager;
@@ -78,6 +79,8 @@ public class TileServicesTest extends SysuiTestCase {
private DumpController mDumpController;
@Mock
private StatusBar mStatusBar;
@Mock
private QSLogger mQSLogger;
@Before
public void setUp() throws Exception {
@@ -94,7 +97,8 @@ public class TileServicesTest extends SysuiTestCase {
() -> mAutoTileManager,
mDumpController,
mBroadcastDispatcher,
Optional.of(mStatusBar));
Optional.of(mStatusBar),
mQSLogger);
mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher);
}

View File

@@ -25,6 +25,7 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_A
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.clearInvocations;
@@ -38,6 +39,7 @@ import static java.lang.Thread.sleep;
import android.content.Intent;
import android.metrics.LogMaker;
import android.service.quicksettings.Tile;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -52,6 +54,7 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.statusbar.StatusBarState;
import org.junit.Before;
@@ -61,6 +64,7 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@@ -69,6 +73,11 @@ import org.mockito.MockitoAnnotations;
public class QSTileImplTest extends SysuiTestCase {
public static final int POSITION = 14;
private static final String SPEC = "spec";
@Mock
private QSLogger mQsLogger;
private TestableLooper mTestableLooper;
private TileImpl mTile;
private QSTileHost mHost;
@@ -81,7 +90,6 @@ public class QSTileImplTest extends SysuiTestCase {
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
String spec = "spec";
mTestableLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
mDependency.injectMockDependency(ActivityStarter.class);
@@ -89,12 +97,13 @@ public class QSTileImplTest extends SysuiTestCase {
mStatusBarStateController =
mDependency.injectMockDependency(StatusBarStateController.class);
mHost = mock(QSTileHost.class);
when(mHost.indexOf(spec)).thenReturn(POSITION);
when(mHost.indexOf(SPEC)).thenReturn(POSITION);
when(mHost.getContext()).thenReturn(mContext.getBaseContext());
when(mHost.getQSLogger()).thenReturn(mQsLogger);
mTile = spy(new TileImpl(mHost));
mTile.mHandler = mTile.new H(mTestableLooper.getLooper());
mTile.setTileSpec(spec);
mTile.setTileSpec(SPEC);
}
@Test
@@ -103,6 +112,14 @@ public class QSTileImplTest extends SysuiTestCase {
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_CLICK)));
}
@Test
public void testClick_log() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
mTile.click();
verify(mQsLogger).logTileClick(SPEC, StatusBarState.SHADE, Tile.STATE_ACTIVE);
}
@Test
public void testClick_Metrics_Status_Bar_Status() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
@@ -118,6 +135,14 @@ public class QSTileImplTest extends SysuiTestCase {
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_SECONDARY_CLICK)));
}
@Test
public void testSecondaryClick_log() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
mTile.secondaryClick();
verify(mQsLogger).logTileSecondaryClick(SPEC, StatusBarState.SHADE, Tile.STATE_ACTIVE);
}
@Test
public void testSecondaryClick_Metrics_Status_Bar_Status() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
@@ -133,6 +158,15 @@ public class QSTileImplTest extends SysuiTestCase {
verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_LONG_PRESS)));
}
@Test
public void testLongClick_log() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
mTile.longClick();
verify(mQsLogger).logTileLongClick(SPEC, StatusBarState.SHADE, Tile.STATE_ACTIVE);
}
@Test
public void testLongClick_Metrics_Status_Bar_Status() {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
@@ -200,6 +234,21 @@ public class QSTileImplTest extends SysuiTestCase {
verify(mTile, never()).handleStale();
}
@Test
public void testHandleDestroy_log() {
mTile.handleDestroy();
verify(mQsLogger).logTileDestroyed(eq(SPEC), anyString());
}
@Test
public void testListening_log() {
mTile.handleSetListening(true);
verify(mQsLogger).logTileChangeListening(SPEC, true);
mTile.handleSetListening(false);
verify(mQsLogger).logTileChangeListening(SPEC, false);
}
private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
private final int mCategory;
@@ -236,6 +285,7 @@ public class QSTileImplTest extends SysuiTestCase {
private static class TileImpl extends QSTileImpl<QSTile.BooleanState> {
protected TileImpl(QSHost host) {
super(host);
getState().state = Tile.STATE_ACTIVE;
}
@Override
@@ -263,11 +313,6 @@ public class QSTileImplTest extends SysuiTestCase {
return null;
}
@Override
protected void handleSetListening(boolean listening) {
}
@Override
public CharSequence getTileLabel() {
return null;