From c529168031a44f353fcc4ed98d539d80e03afc10 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Mon, 6 Jul 2020 14:33:44 -0400 Subject: [PATCH 1/4] QSTileImpl is set to DESTROYED when handleDestroy This will guarantee that there are no remaining references in the CallbackController. Test: atest QSTileImplTest CallbackControllerTest Bug: 160160246 Change-Id: I308ea00b2d24febf9ad0ab1c533c4f3d2f34c675 Merged-In: I308ea00b2d24febf9ad0ab1c533c4f3d2f34c675 (cherry picked from commit c6db4059da7964dbfa7f4d4149313b318e5ddec5) --- .../systemui/qs/tileimpl/QSTileImpl.java | 3 ++ .../systemui/qs/tileimpl/QSTileImplTest.java | 8 +++++ .../policy/CallbackControllerTest.java | 30 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 795d0627c4474..d11079294a85d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -14,6 +14,7 @@ package com.android.systemui.qs.tileimpl; +import static androidx.lifecycle.Lifecycle.State.DESTROYED; import static androidx.lifecycle.Lifecycle.State.RESUMED; import static androidx.lifecycle.Lifecycle.State.STARTED; @@ -475,6 +476,8 @@ public abstract class QSTileImpl implements QSTile, Lifecy } mCallbacks.clear(); mHandler.removeCallbacksAndMessages(null); + // This will force it to be removed from all controllers that may have it registered. + mLifecycle.setCurrentState(DESTROYED); } protected void checkIfRestrictionEnforcedByAdminOnly(State state, String userRestriction) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java index 438de99015a4c..20f13bb024351 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java @@ -259,6 +259,14 @@ public class QSTileImplTest extends SysuiTestCase { verify(mTile, never()).handleStale(); } + @Test + public void testHandleDestroyLifecycle() { + assertNotEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); + mTile.handleDestroy(); + + assertEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); + } + @Test public void testHandleDestroy_log() { mTile.handleDestroy(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackControllerTest.java index fa711f1cf9a2e..a16fb5e8dc179 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackControllerTest.java @@ -23,10 +23,12 @@ import static org.mockito.Mockito.verify; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; +import androidx.annotation.NonNull; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle.Event; import androidx.lifecycle.LifecycleEventObserver; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LifecycleRegistry; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; @@ -76,6 +78,34 @@ public class CallbackControllerTest extends SysuiTestCase { verify(controller).removeCallback(eq(callback)); } + @Test + public void testCallbackIsRemovedOnDestroy() { + SimpleLifecycleOwner owner = new SimpleLifecycleOwner(); + + Object callback = new Object(); + Controller controller = mock(Controller.class); + controller.observe(owner, callback); + + owner.setState(Lifecycle.State.RESUMED); + verify(controller).addCallback(callback); + + owner.setState(Lifecycle.State.DESTROYED); + verify(controller).removeCallback(callback); + } + + private static class SimpleLifecycleOwner implements LifecycleOwner { + LifecycleRegistry mLifecycle = new LifecycleRegistry(this); + @NonNull + @Override + public Lifecycle getLifecycle() { + return mLifecycle; + } + + public void setState(Lifecycle.State state) { + mLifecycle.setCurrentState(state); + } + } + private static class Controller implements CallbackController { @Override public void addCallback(Object listener) { From e839d9dd73f1a7801a8ef1fff76dcee9cf367e0f Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 15 Jul 2020 09:57:50 -0400 Subject: [PATCH 2/4] Refactor QSTileImpl and remove Dependency.get Dependencies to QSTileImpl are now clearly indicated in the constructor and fed in by its subclasses. Test: SystemUITests Change-Id: Idf70d205613cb31865895f2d11fa02b52fb9a408 Merged-In: Idf70d205613cb31865895f2d11fa02b52fb9a408 (cherry picked from commit 037d3b9563bfeecb6b56ba83d13e5db1c9ddedc1) --- .../systemui/dagger/SystemServicesModule.java | 7 ++ .../src/com/android/systemui/qs/QSHost.java | 2 - .../com/android/systemui/qs/QSTileHost.java | 4 - .../systemui/qs/external/CustomTile.java | 107 +++++++++++++++++- .../systemui/qs/tileimpl/QSFactoryImpl.java | 11 +- .../systemui/qs/tileimpl/QSTileImpl.java | 41 ++++--- .../systemui/qs/tiles/AirplaneModeTile.java | 33 ++++-- .../systemui/qs/tiles/BatterySaverTile.java | 23 +++- .../systemui/qs/tiles/BluetoothTile.java | 24 +++- .../android/systemui/qs/tiles/CastTile.java | 26 ++++- .../systemui/qs/tiles/CellularTile.java | 23 +++- .../systemui/qs/tiles/ColorInversionTile.java | 24 +++- .../systemui/qs/tiles/DataSaverTile.java | 25 +++- .../android/systemui/qs/tiles/DndTile.java | 25 +++- .../systemui/qs/tiles/FlashlightTile.java | 22 +++- .../systemui/qs/tiles/HotspotTile.java | 24 +++- .../systemui/qs/tiles/LocationTile.java | 25 +++- .../android/systemui/qs/tiles/NfcTile.java | 22 +++- .../systemui/qs/tiles/NightDisplayTile.java | 25 +++- .../systemui/qs/tiles/RotationLockTile.java | 22 +++- .../systemui/qs/tiles/ScreenRecordTile.java | 23 +++- .../systemui/qs/tiles/UiModeNightTile.java | 25 +++- .../android/systemui/qs/tiles/UserTile.java | 24 +++- .../android/systemui/qs/tiles/WifiTile.java | 23 +++- .../systemui/qs/tiles/WorkModeTile.java | 22 +++- .../systemui/util/leak/GarbageMonitor.java | 20 +++- .../android/systemui/qs/QSTileHostTest.java | 13 ++- .../systemui/qs/external/CustomTileTest.kt | 86 +++++++++----- .../systemui/qs/tileimpl/QSTileImplTest.java | 63 +++++------ .../systemui/qs/tiles/BatterySaverTileTest.kt | 25 +++- .../systemui/qs/tiles/CastTileTest.java | 31 +++-- .../qs/tiles/ScreenRecordTileTest.java | 30 ++++- 32 files changed, 709 insertions(+), 191 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java index 8472b1b54c489..4a5d142c35e89 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java @@ -39,6 +39,7 @@ import android.content.pm.ShortcutManager; import android.content.res.Resources; import android.hardware.SensorManager; import android.hardware.SensorPrivacyManager; +import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.media.AudioManager; import android.media.MediaRouter2Manager; @@ -105,6 +106,12 @@ public class SystemServicesModule { return context.getSystemService(AudioManager.class); } + @Provides + @Singleton + static ColorDisplayManager provideColorDisplayManager(Context context) { + return context.getSystemService(ColorDisplayManager.class); + } + @Provides @Singleton static ConnectivityManager provideConnectivityManagager(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java index 1e8c4d86da36b..290ab8594fc0f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java @@ -20,7 +20,6 @@ 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; import java.util.Collection; @@ -31,7 +30,6 @@ public interface QSHost { void openPanels(); Context getContext(); Context getUserContext(); - QSLogger getQSLogger(); UiEventLogger getUiEventLogger(); Collection getTiles(); void addCallback(Callback callback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 1f3967c03a41c..3b16a4ec1c38e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -179,10 +179,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener, D onTuningChanged(TILES_SETTING, value); } - public QSLogger getQSLogger() { - return mQSLogger; - } - @Override public UiEventLogger getUiEventLogger() { return mUiEventLogger; diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index 30e0a766de371..19c7b6cefc5d1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -29,7 +29,9 @@ import android.graphics.drawable.Drawable; import android.metrics.LogMaker; import android.net.Uri; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.provider.Settings; import android.service.quicksettings.IQSTileService; @@ -42,16 +44,27 @@ import android.view.IWindowManager; import android.view.WindowManagerGlobal; import android.widget.Switch; +import androidx.annotation.NonNull; + +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.State; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import java.util.Objects; +import javax.inject.Inject; + +import dagger.Lazy; + public class CustomTile extends QSTileImpl implements TileChangeListener { public static final String PREFIX = "custom("; @@ -79,8 +92,19 @@ public class CustomTile extends QSTileImpl implements TileChangeListener private boolean mIsTokenGranted; private boolean mIsShowingDialog; - private CustomTile(QSHost host, String action, Context userContext) { - super(host); + private CustomTile( + QSHost host, + Looper backgroundLooper, + Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + String action, + Context userContext + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mWindowManager = WindowManagerGlobal.getWindowManagerService(); mComponent = ComponentName.unflattenFromString(action); mTile = new Tile(); @@ -397,7 +421,7 @@ public class CustomTile extends QSTileImpl implements TileChangeListener return ComponentName.unflattenFromString(action); } - public static CustomTile create(QSHost host, String spec, Context userContext) { + private static String getAction(String spec) { if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) { throw new IllegalArgumentException("Bad custom tile spec: " + spec); } @@ -405,6 +429,81 @@ public class CustomTile extends QSTileImpl implements TileChangeListener if (action.isEmpty()) { throw new IllegalArgumentException("Empty custom tile spec action"); } - return new CustomTile(host, action, userContext); + return action; + } + + /** + * Create a {@link CustomTile} for a given spec and user. + * + * @param builder including injected common dependencies. + * @param spec as provided by {@link CustomTile#toSpec} + * @param userContext context for the user that is creating this tile. + * @return a new {@link CustomTile} + */ + public static CustomTile create(Builder builder, String spec, Context userContext) { + return builder + .setSpec(spec) + .setUserContext(userContext) + .build(); + } + + public static class Builder { + final Lazy mQSHostLazy; + final Looper mBackgroundLooper; + final Handler mMainHandler; + final MetricsLogger mMetricsLogger; + final StatusBarStateController mStatusBarStateController; + final ActivityStarter mActivityStarter; + final QSLogger mQSLogger; + + Context mUserContext; + String mSpec = ""; + + @Inject + public Builder( + Lazy hostLazy, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger + ) { + mQSHostLazy = hostLazy; + mBackgroundLooper = backgroundLooper; + mMainHandler = mainHandler; + mMetricsLogger = metricsLogger; + mStatusBarStateController = statusBarStateController; + mActivityStarter = activityStarter; + mQSLogger = qsLogger; + } + + Builder setSpec(@NonNull String spec) { + mSpec = spec; + return this; + } + + Builder setUserContext(@NonNull Context userContext) { + mUserContext = userContext; + return this; + } + + CustomTile build() { + if (mUserContext == null) { + throw new NullPointerException("UserContext cannot be null"); + } + String action = getAction(mSpec); + return new CustomTile( + mQSHostLazy.get(), + mBackgroundLooper, + mMainHandler, + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQSLogger, + action, + mUserContext + ); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index c182a58a28c48..69a6fe1075c20 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -80,9 +80,12 @@ public class QSFactoryImpl implements QSFactory { private final Provider mScreenRecordTileProvider; private final Lazy mQsHostLazy; + private final Provider mCustomTileBuilderProvider; @Inject - public QSFactoryImpl(Lazy qsHostLazy, + public QSFactoryImpl( + Lazy qsHostLazy, + Provider customTileBuilderProvider, Provider wifiTileProvider, Provider bluetoothTileProvider, Provider cellularTileProvider, @@ -104,6 +107,8 @@ public class QSFactoryImpl implements QSFactory { Provider uiModeNightTileProvider, Provider screenRecordTileProvider) { mQsHostLazy = qsHostLazy; + mCustomTileBuilderProvider = customTileBuilderProvider; + mWifiTileProvider = wifiTileProvider; mBluetoothTileProvider = bluetoothTileProvider; mCellularTileProvider = cellularTileProvider; @@ -179,8 +184,8 @@ public class QSFactoryImpl implements QSFactory { // Custom tiles if (tileSpec.startsWith(CustomTile.PREFIX)) { - return CustomTile.create(mQsHostLazy.get(), tileSpec, - mQsHostLazy.get().getUserContext()); + return CustomTile.create( + mCustomTileBuilderProvider.get(), tileSpec, mQsHostLazy.get().getUserContext()); } // Debug tiles. diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index d11079294a85d..8c485a6a950f7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -55,7 +55,6 @@ import com.android.internal.logging.UiEventLogger; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; -import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.Prefs; import com.android.systemui.plugins.ActivityStarter; @@ -93,12 +92,12 @@ public abstract class QSTileImpl implements QSTile, Lifecy protected final QSHost mHost; protected final Context mContext; // @NonFinalForTesting - protected H mHandler = new H(Dependency.get(Dependency.BG_LOOPER)); - protected final Handler mUiHandler = new Handler(Looper.getMainLooper()); + protected final H mHandler; + protected final Handler mUiHandler; private final ArraySet mListeners = new ArraySet<>(); - private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); - private final StatusBarStateController - mStatusBarStateController = Dependency.get(StatusBarStateController.class); + private final MetricsLogger mMetricsLogger; + private final StatusBarStateController mStatusBarStateController; + protected final ActivityStarter mActivityStarter; private final UiEventLogger mUiEventLogger; private final QSLogger mQSLogger; @@ -151,14 +150,29 @@ public abstract class QSTileImpl implements QSTile, Lifecy */ abstract public int getMetricsCategory(); - protected QSTileImpl(QSHost host) { + protected QSTileImpl( + QSHost host, + Looper backgroundLooper, + Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger + ) { mHost = host; mContext = host.getContext(); mInstanceId = host.getNewInstanceId(); + mUiEventLogger = host.getUiEventLogger(); + + mUiHandler = mainHandler; + mHandler = new H(backgroundLooper); + mQSLogger = qsLogger; + mMetricsLogger = metricsLogger; + mStatusBarStateController = statusBarStateController; + mActivityStarter = activityStarter; + mState = newTileState(); mTmpState = newTileState(); - mQSLogger = host.getQSLogger(); - mUiEventLogger = host.getUiEventLogger(); } protected final void resetStates() { @@ -358,8 +372,7 @@ public abstract class QSTileImpl implements QSTile, Lifecy * {@link QSTileImpl#getLongClickIntent} */ protected void handleLongClick() { - Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard( - getLongClickIntent(), 0); + mActivityStarter.postStartActivityDismissingKeyguard(getLongClickIntent(), 0); } /** @@ -533,7 +546,8 @@ public abstract class QSTileImpl implements QSTile, Lifecy private static final int REMOVE_CALLBACKS = 11; private static final int REMOVE_CALLBACK = 12; private static final int SET_LISTENING = 13; - private static final int STALE = 14; + @VisibleForTesting + protected static final int STALE = 14; @VisibleForTesting protected H(Looper looper) { @@ -558,8 +572,7 @@ public abstract class QSTileImpl implements QSTile, Lifecy if (mState.disabledByPolicy) { Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent( mContext, mEnforcedAdmin); - Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard( - intent, 0); + mActivityStarter.postStartActivityDismissingKeyguard(intent, 0); } else { handleClick(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index b24fdbfc562f3..b8485907c5199 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -21,6 +21,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.Looper; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Global; @@ -33,33 +35,50 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.GlobalSetting; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import javax.inject.Inject; +import dagger.Lazy; + /** Quick settings tile: Airplane mode **/ public class AirplaneModeTile extends QSTileImpl { private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_airplane); private final GlobalSetting mSetting; - private final ActivityStarter mActivityStarter; private final BroadcastDispatcher mBroadcastDispatcher; + private final Lazy mLazyConnectivityManager; private boolean mListening; @Inject - public AirplaneModeTile(QSHost host, ActivityStarter activityStarter, - BroadcastDispatcher broadcastDispatcher) { - super(host); - mActivityStarter = activityStarter; + public AirplaneModeTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + BroadcastDispatcher broadcastDispatcher, + Lazy lazyConnectivityManager + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mBroadcastDispatcher = broadcastDispatcher; + mLazyConnectivityManager = lazyConnectivityManager; mSetting = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) { @Override protected void handleValueChanged(int value) { + // mHandler is the background handler so calling this is OK handleRefreshState(value); } }; @@ -83,9 +102,7 @@ public class AirplaneModeTile extends QSTileImpl { } private void setEnabled(boolean enabled) { - final ConnectivityManager mgr = - (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - mgr.setAirplaneMode(enabled); + mLazyConnectivityManager.get().setAirplaneMode(enabled); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index 7150e43503049..c64fc50b82370 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -16,16 +16,24 @@ package com.android.systemui.qs.tiles; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings.Secure; import android.service.quicksettings.Tile; import android.widget.Switch; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -46,8 +54,18 @@ public class BatterySaverTile extends QSTileImpl implements private Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_battery_saver); @Inject - public BatterySaverTile(QSHost host, BatteryController batteryController) { - super(host); + public BatterySaverTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + BatteryController batteryController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mBatteryController = batteryController; mBatteryController.observe(getLifecycle(), this); int currentUser = host.getUserContext().getUserId(); @@ -55,6 +73,7 @@ public class BatterySaverTile extends QSTileImpl implements currentUser) { @Override protected void handleValueChanged(int value, boolean observedChange) { + // mHandler is the background handler so calling this is OK handleRefreshState(null); } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 888c7ab2c312d..56083c43e1b6c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -24,6 +24,8 @@ import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.text.TextUtils; @@ -37,12 +39,16 @@ import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.graph.BluetoothDeviceLayerDrawable; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSDetailItems; import com.android.systemui.qs.QSDetailItems.Item; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BluetoothController; @@ -58,15 +64,21 @@ public class BluetoothTile extends QSTileImpl { private final BluetoothController mController; private final BluetoothDetailAdapter mDetailAdapter; - private final ActivityStarter mActivityStarter; @Inject - public BluetoothTile(QSHost host, - BluetoothController bluetoothController, - ActivityStarter activityStarter) { - super(host); + public BluetoothTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + BluetoothController bluetoothController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = bluetoothController; - mActivityStarter = activityStarter; mDetailAdapter = (BluetoothDetailAdapter) createDetailAdapter(); mController.observe(getLifecycle(), mCallback); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 4b53ae2c63796..56b939df383f2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -22,6 +22,8 @@ import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.media.MediaRouter.RouteInfo; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.util.Log; @@ -35,12 +37,16 @@ import com.android.internal.app.MediaRouteDialogPresenter; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSDetailItems; import com.android.systemui.qs.QSDetailItems.Item; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.CastController; @@ -64,20 +70,28 @@ public class CastTile extends QSTileImpl { private final KeyguardStateController mKeyguard; private final NetworkController mNetworkController; private final Callback mCallback = new Callback(); - private final ActivityStarter mActivityStarter; private Dialog mDialog; private boolean mWifiConnected; @Inject - public CastTile(QSHost host, CastController castController, - KeyguardStateController keyguardStateController, NetworkController networkController, - ActivityStarter activityStarter) { - super(host); + public CastTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + CastController castController, + KeyguardStateController keyguardStateController, + NetworkController networkController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = castController; mDetailAdapter = new CastDetailAdapter(); mKeyguard = keyguardStateController; mNetworkController = networkController; - mActivityStarter = activityStarter; mController.observe(this, mCallback); mKeyguard.observe(this, mCallback); mNetworkController.observe(this, mSignalCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 33e98d836d940..f742752d80be9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -23,6 +23,8 @@ import android.app.AlertDialog.Builder; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.os.Handler; +import android.os.Looper; import android.os.UserHandle; import android.provider.Settings; import android.service.quicksettings.Tile; @@ -40,12 +42,16 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settingslib.net.DataUsageController; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSIconView; import com.android.systemui.plugins.qs.QSTile.SignalState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.SignalTileView; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.NetworkController; @@ -63,14 +69,21 @@ public class CellularTile extends QSTileImpl { private final CellularDetailAdapter mDetailAdapter; private final CellSignalCallback mSignalCallback = new CellSignalCallback(); - private final ActivityStarter mActivityStarter; @Inject - public CellularTile(QSHost host, NetworkController networkController, - ActivityStarter activityStarter) { - super(host); + public CellularTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + NetworkController networkController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = networkController; - mActivityStarter = activityStarter; mDataController = mController.getMobileDataController(); mDetailAdapter = new CellularDetailAdapter(); mController.observe(getLifecycle(), mSignalCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 9c0030d528e7e..131e285359112 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -17,17 +17,25 @@ package com.android.systemui.qs.tiles; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.provider.Settings.Secure; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.R.drawable; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.SecureSetting; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import javax.inject.Inject; @@ -41,13 +49,23 @@ public class ColorInversionTile extends QSTileImpl { private boolean mListening; @Inject - public ColorInversionTile(QSHost host) { - super(host); + public ColorInversionTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); - mSetting = new SecureSetting(mContext, mHandler, + mSetting = new SecureSetting(mContext, mainHandler, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) { @Override protected void handleValueChanged(int value, boolean observedChange) { + // mHandler is the background handler so calling this is OK handleRefreshState(value); } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index 7ae8fbc928a62..85f12458c33a5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -16,19 +16,26 @@ package com.android.systemui.qs.tiles; import android.content.DialogInterface.OnClickListener; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Prefs; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.statusbar.policy.NetworkController; import javax.inject.Inject; @@ -38,9 +45,19 @@ public class DataSaverTile extends QSTileImpl implements private final DataSaverController mDataSaverController; @Inject - public DataSaverTile(QSHost host, NetworkController networkController) { - super(host); - mDataSaverController = networkController.getDataSaverController(); + public DataSaverTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + DataSaverController dataSaverController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); + mDataSaverController = dataSaverController; mDataSaverController.observe(getLifecycle(), this); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 9f7b84aa62c13..ec8b1435e2012 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -30,6 +30,8 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Handler; +import android.os.Looper; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Global; @@ -53,11 +55,14 @@ import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.SysUIToast; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.ZenModeController; @@ -79,7 +84,6 @@ public class DndTile extends QSTileImpl { private final ZenModeController mController; private final DndDetailAdapter mDetailAdapter; - private final ActivityStarter mActivityStarter; private final SharedPreferences mSharedPreferences; private final BroadcastDispatcher mBroadcastDispatcher; @@ -88,12 +92,21 @@ public class DndTile extends QSTileImpl { private boolean mReceiverRegistered; @Inject - public DndTile(QSHost host, ZenModeController zenModeController, - ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher, - @Main SharedPreferences sharedPreferences) { - super(host); + public DndTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + ZenModeController zenModeController, + BroadcastDispatcher broadcastDispatcher, + @Main SharedPreferences sharedPreferences + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = zenModeController; - mActivityStarter = activityStarter; mSharedPreferences = sharedPreferences; mDetailAdapter = new DndDetailAdapter(); mBroadcastDispatcher = broadcastDispatcher; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index 27ccd7cab2263..cd45082458f2f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -18,14 +18,22 @@ package com.android.systemui.qs.tiles; import android.app.ActivityManager; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.provider.MediaStore; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.FlashlightController; @@ -39,8 +47,18 @@ public class FlashlightTile extends QSTileImpl implements private final FlashlightController mFlashlightController; @Inject - public FlashlightTile(QSHost host, FlashlightController flashlightController) { - super(host); + public FlashlightTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + FlashlightController flashlightController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mFlashlightController = flashlightController; mFlashlightController.observe(getLifecycle(), this); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 1ab77f3f75244..a45d94ace4253 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -18,16 +18,24 @@ package com.android.systemui.qs.tiles; import android.annotation.Nullable; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.os.UserManager; import android.provider.Settings; import android.service.quicksettings.Tile; import android.util.Log; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.HotspotController; @@ -45,9 +53,19 @@ public class HotspotTile extends QSTileImpl { private boolean mListening; @Inject - public HotspotTile(QSHost host, HotspotController hotspotController, - DataSaverController dataSaverController) { - super(host); + public HotspotTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + HotspotController hotspotController, + DataSaverController dataSaverController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mHotspotController = hotspotController; mDataSaverController = dataSaverController; mHotspotController.observe(this, mCallbacks); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index 02f364bd3a7e0..d502d06efcebb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -17,16 +17,23 @@ package com.android.systemui.qs.tiles; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.os.UserManager; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.LocationController; @@ -41,16 +48,24 @@ public class LocationTile extends QSTileImpl { private final LocationController mController; private final KeyguardStateController mKeyguard; - private final ActivityStarter mActivityStarter; private final Callback mCallback = new Callback(); @Inject - public LocationTile(QSHost host, LocationController locationController, - KeyguardStateController keyguardStateController, ActivityStarter activityStarter) { - super(host); + public LocationTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + LocationController locationController, + KeyguardStateController keyguardStateController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = locationController; mKeyguard = keyguardStateController; - mActivityStarter = activityStarter; mController.observe(this, mCallback); mKeyguard.observe(this, mCallback); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java index 7da9135922861..fb281169b2f16 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java @@ -23,15 +23,23 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.nfc.NfcAdapter; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import javax.inject.Inject; @@ -47,8 +55,18 @@ public class NfcTile extends QSTileImpl { private boolean mListening; @Inject - public NfcTile(QSHost host, BroadcastDispatcher broadcastDispatcher) { - super(host); + public NfcTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + BroadcastDispatcher broadcastDispatcher + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mBroadcastDispatcher = broadcastDispatcher; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index acd2846fef3c5..f628f7b30bd06 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -33,10 +33,16 @@ import android.widget.Switch; import androidx.annotation.StringRes; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.LocationController; @@ -66,11 +72,22 @@ public class NightDisplayTile extends QSTileImpl implements private boolean mIsListening; @Inject - public NightDisplayTile(QSHost host, LocationController locationController) { - super(host); + public NightDisplayTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + LocationController locationController, + ColorDisplayManager colorDisplayManager + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mLocationController = locationController; - mManager = mContext.getSystemService(ColorDisplayManager.class); - mListener = new NightDisplayListener(mContext, new Handler(Looper.myLooper())); + mManager = colorDisplayManager; + mListener = new NightDisplayListener(mContext, mainHandler); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 5dcb4e3b1fb99..4bf27e2aa4b88 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -19,14 +19,22 @@ package com.android.systemui.qs.tiles; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback; @@ -40,8 +48,18 @@ public class RotationLockTile extends QSTileImpl { private final RotationLockController mController; @Inject - public RotationLockTile(QSHost host, RotationLockController rotationLockController) { - super(host); + public RotationLockTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + RotationLockController rotationLockController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = rotationLockController; mController.observe(this, mCallback); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index 0c34b27d348e6..d7a2975a4b04a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -17,15 +17,22 @@ package com.android.systemui.qs.tiles; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.service.quicksettings.Tile; import android.text.TextUtils; import android.util.Log; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; 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.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; @@ -44,9 +51,19 @@ public class ScreenRecordTile extends QSTileImpl private Callback mCallback = new Callback(); @Inject - public ScreenRecordTile(QSHost host, RecordingController controller, - KeyguardDismissUtil keyguardDismissUtil) { - super(host); + public ScreenRecordTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + RecordingController controller, + KeyguardDismissUtil keyguardDismissUtil + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = controller; mController.observe(this, mCallback); mKeyguardDismissUtil = keyguardDismissUtil; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java index f777553bb5fe9..78975a4798ce7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -19,15 +19,23 @@ package com.android.systemui.qs.tiles; import android.app.UiModeManager; import android.content.Intent; import android.content.res.Configuration; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.text.TextUtils; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +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.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -54,9 +62,20 @@ public class UiModeNightTile extends QSTileImpl implements private final BatteryController mBatteryController; private final LocationController mLocationController; @Inject - public UiModeNightTile(QSHost host, ConfigurationController configurationController, - BatteryController batteryController, LocationController locationController) { - super(host); + public UiModeNightTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + ConfigurationController configurationController, + BatteryController batteryController, + LocationController locationController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mBatteryController = batteryController; mUiModeManager = host.getUserContext().getSystemService(UiModeManager.class); mLocationController = locationController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java index aab30d499e08c..26adfdcd8539d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java @@ -18,14 +18,22 @@ package com.android.systemui.qs.tiles; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.util.Pair; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; 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.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -39,9 +47,19 @@ public class UserTile extends QSTileImpl implements UserInfoController.On private Pair mLastUpdate; @Inject - public UserTile(QSHost host, UserSwitcherController userSwitcherController, - UserInfoController userInfoController) { - super(host); + public UserTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + UserSwitcherController userSwitcherController, + UserInfoController userInfoController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mUserSwitcherController = userSwitcherController; mUserInfoController = userInfoController; mUserInfoController.observe(getLifecycle(), this); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 1279d42eb64d2..4d89dea7cb708 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -20,6 +20,8 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.text.TextUtils; @@ -32,15 +34,19 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settingslib.wifi.AccessPoint; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSIconView; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTile.SignalState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.AlphaControlledSignalTileView; import com.android.systemui.qs.QSDetailItems; import com.android.systemui.qs.QSDetailItems.Item; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSIconViewImpl; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.NetworkController; @@ -63,17 +69,24 @@ public class WifiTile extends QSTileImpl { private final QSTile.SignalState mStateBeforeClick = newTileState(); protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback(); - private final ActivityStarter mActivityStarter; private boolean mExpectDisabled; @Inject - public WifiTile(QSHost host, NetworkController networkController, - ActivityStarter activityStarter) { - super(host); + public WifiTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + NetworkController networkController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mController = networkController; mWifiController = mController.getAccessPointController(); mDetailAdapter = (WifiDetailAdapter) createDetailAdapter(); - mActivityStarter = activityStarter; mController.observe(getLifecycle(), mSignalCallback); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 318c0c4660cb9..5235b6d5a0bb8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -17,14 +17,22 @@ package com.android.systemui.qs.tiles; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile.BooleanState; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.ManagedProfileController; @@ -38,8 +46,18 @@ public class WorkModeTile extends QSTileImpl implements private final ManagedProfileController mProfileController; @Inject - public WorkModeTile(QSHost host, ManagedProfileController managedProfileController) { - super(host); + public WorkModeTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + ManagedProfileController managedProfileController + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); mProfileController = managedProfileController; mProfileController.observe(getLifecycle(), this); } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java index b12224bf583d1..d1805af064349 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java @@ -44,13 +44,17 @@ import android.text.format.DateUtils; import android.util.Log; import android.util.LongSparseArray; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; 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.QSHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import java.io.FileDescriptor; @@ -396,15 +400,23 @@ public class GarbageMonitor implements Dumpable { public static final String TILE_SPEC = "dbg:mem"; private final GarbageMonitor gm; - private final ActivityStarter mActivityStarter; private ProcessMemInfo pmi; private boolean dumpInProgress; @Inject - public MemoryTile(QSHost host, GarbageMonitor monitor, ActivityStarter starter) { - super(host); + public MemoryTile( + QSHost host, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + GarbageMonitor monitor + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); gm = monitor; - mActivityStarter = starter; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java index 5d4ef550b36c6..bdb7166f5db16 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java @@ -41,14 +41,17 @@ import android.testing.TestableLooper.RunWithLooper; import androidx.test.filters.SmallTest; +import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.internal.util.CollectionUtils; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSTile; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -331,7 +334,15 @@ public class QSTileHostTest extends SysuiTestCase { private class TestTile extends QSTileImpl { protected TestTile(QSHost host) { - super(host); + super( + host, + mLooper.getLooper(), + new Handler(mLooper.getLooper()), + mock(MetricsLogger.class), + mock(StatusBarStateController.class), + mock(ActivityStarter.class), + mQSLogger + ); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt index 953198c42d664..c2579dd46e789 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt @@ -23,17 +23,23 @@ import android.content.pm.PackageManager import android.content.pm.ServiceInfo import android.graphics.drawable.Drawable import android.graphics.drawable.Icon +import android.os.Handler import android.service.quicksettings.IQSTileService import android.service.quicksettings.Tile import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper import android.view.IWindowManager -import androidx.test.runner.AndroidJUnit4 +import com.android.internal.logging.MetricsLogger 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.QSHost -import junit.framework.Assert.assertFalse -import junit.framework.Assert.assertTrue +import com.android.systemui.qs.logging.QSLogger import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -46,7 +52,8 @@ import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations @SmallTest -@RunWith(AndroidJUnit4::class) +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper class CustomTileTest : SysuiTestCase() { companion object { @@ -56,36 +63,53 @@ class CustomTileTest : SysuiTestCase() { val TILE_SPEC = CustomTile.toSpec(componentName) } - @Mock private lateinit var mTileHost: QSHost - @Mock private lateinit var mTileService: IQSTileService - @Mock private lateinit var mTileServices: TileServices - @Mock private lateinit var mTileServiceManager: TileServiceManager - @Mock private lateinit var mWindowService: IWindowManager - @Mock private lateinit var mPackageManager: PackageManager - @Mock private lateinit var mApplicationInfo: ApplicationInfo - @Mock private lateinit var mServiceInfo: ServiceInfo + @Mock private lateinit var tileHost: QSHost + @Mock private lateinit var metricsLogger: MetricsLogger + @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var qsLogger: QSLogger + @Mock private lateinit var tileService: IQSTileService + @Mock private lateinit var tileServices: TileServices + @Mock private lateinit var tileServiceManager: TileServiceManager + @Mock private lateinit var windowService: IWindowManager + @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var applicationInfo: ApplicationInfo + @Mock private lateinit var serviceInfo: ServiceInfo private lateinit var customTile: CustomTile + private lateinit var testableLooper: TestableLooper + private lateinit var customTileBuilder: CustomTile.Builder @Before fun setUp() { MockitoAnnotations.initMocks(this) + testableLooper = TestableLooper.get(this) - mContext.addMockSystemService("window", mWindowService) - mContext.setMockPackageManager(mPackageManager) - `when`(mTileHost.tileServices).thenReturn(mTileServices) - `when`(mTileHost.context).thenReturn(mContext) - `when`(mTileServices.getTileWrapper(any(CustomTile::class.java))) - .thenReturn(mTileServiceManager) - `when`(mTileServiceManager.tileService).thenReturn(mTileService) - `when`(mPackageManager.getApplicationInfo(anyString(), anyInt())) - .thenReturn(mApplicationInfo) + mContext.addMockSystemService("window", windowService) + mContext.setMockPackageManager(packageManager) + `when`(tileHost.tileServices).thenReturn(tileServices) + `when`(tileHost.context).thenReturn(mContext) + `when`(tileServices.getTileWrapper(any(CustomTile::class.java))) + .thenReturn(tileServiceManager) + `when`(tileServiceManager.tileService).thenReturn(tileService) + `when`(packageManager.getApplicationInfo(anyString(), anyInt())) + .thenReturn(applicationInfo) - `when`(mPackageManager.getServiceInfo(any(ComponentName::class.java), anyInt())) - .thenReturn(mServiceInfo) - mServiceInfo.applicationInfo = mApplicationInfo + `when`(packageManager.getServiceInfo(any(ComponentName::class.java), anyInt())) + .thenReturn(serviceInfo) + serviceInfo.applicationInfo = applicationInfo - customTile = CustomTile.create(mTileHost, TILE_SPEC, mContext) + customTileBuilder = CustomTile.Builder( + { tileHost }, + testableLooper.looper, + Handler(testableLooper.looper), + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger + ) + + customTile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext) } @Test @@ -93,18 +117,18 @@ class CustomTileTest : SysuiTestCase() { assertEquals(0, customTile.user) val userContext = mock(Context::class.java) - `when`(userContext.packageManager).thenReturn(mPackageManager) + `when`(userContext.packageManager).thenReturn(packageManager) `when`(userContext.userId).thenReturn(10) - val tile = CustomTile.create(mTileHost, TILE_SPEC, userContext) + val tile = CustomTile.create(customTileBuilder, TILE_SPEC, userContext) assertEquals(10, tile.user) } @Test fun testToggleableTileHasBooleanState() { - `when`(mTileServiceManager.isToggleableTile).thenReturn(true) - customTile = CustomTile.create(mTileHost, TILE_SPEC, mContext) + `when`(tileServiceManager.isToggleableTile).thenReturn(true) + customTile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext) assertTrue(customTile.state is QSTile.BooleanState) assertTrue(customTile.newTileState() is QSTile.BooleanState) @@ -118,8 +142,8 @@ class CustomTileTest : SysuiTestCase() { @Test fun testValueUpdatedInBooleanTile() { - `when`(mTileServiceManager.isToggleableTile).thenReturn(true) - customTile = CustomTile.create(mTileHost, TILE_SPEC, mContext) + `when`(tileServiceManager.isToggleableTile).thenReturn(true) + customTile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext) customTile.qsTile.icon = mock(Icon::class.java) `when`(customTile.qsTile.icon.loadDrawable(any(Context::class.java))) .thenReturn(mock(Drawable::class.java)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java index 20f13bb024351..103e5586f395c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java @@ -35,17 +35,14 @@ 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; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static java.lang.Thread.sleep; - import android.content.Intent; import android.metrics.LogMaker; +import android.os.Handler; +import android.os.Looper; import android.service.quicksettings.Tile; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -57,7 +54,6 @@ 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; @@ -69,7 +65,6 @@ import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.statusbar.StatusBarState; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -91,9 +86,14 @@ public class QSTileImplTest extends SysuiTestCase { private TestableLooper mTestableLooper; private TileImpl mTile; + @Mock private QSTileHost mHost; + @Mock private MetricsLogger mMetricsLogger; + @Mock private StatusBarStateController mStatusBarStateController; + @Mock + private ActivityStarter mActivityStarter; private UiEventLoggerFake mUiEventLoggerFake; private InstanceId mInstanceId = InstanceId.fakeInstanceId(5); @@ -104,21 +104,16 @@ public class QSTileImplTest extends SysuiTestCase { public void setup() throws Exception { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); - 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()); + Handler mainHandler = new Handler(mTestableLooper.getLooper()); + + mTile = new TileImpl(mHost, mTestableLooper.getLooper(), mainHandler, + mMetricsLogger, mStatusBarStateController, mActivityStarter, mQsLogger); mTile.setTileSpec(SPEC); } @@ -223,40 +218,25 @@ public class QSTileImplTest extends SysuiTestCase { verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION)); } - @Test - @Ignore("flaky") - public void testStaleTimeout() throws InterruptedException { - when(mTile.getStaleTimeout()).thenReturn(5l); - clearInvocations(mTile); - - mTile.handleRefreshState(null); - mTestableLooper.processAllMessages(); - verify(mTile, never()).handleStale(); - - sleep(10); - mTestableLooper.processAllMessages(); - verify(mTile).handleStale(); - } + //TODO(b/161799397) Bring back testStaleTimeout when we can use FakeExecutor @Test public void testStaleListening() { mTile.handleStale(); mTestableLooper.processAllMessages(); - verify(mTile).handleSetListening(eq(true)); + verify(mQsLogger).logTileChangeListening(SPEC, true); mTile.handleRefreshState(null); mTestableLooper.processAllMessages(); - verify(mTile).handleSetListening(eq(false)); + verify(mQsLogger).logTileChangeListening(SPEC, false); } @Test public void testHandleDestroyClearsHandlerQueue() { - when(mTile.getStaleTimeout()).thenReturn(0L); mTile.handleRefreshState(null); // this will add a delayed H.STALE message mTile.handleDestroy(); - mTestableLooper.processAllMessages(); - verify(mTile, never()).handleStale(); + assertFalse(mTile.mHandler.hasMessages(QSTileImpl.H.STALE)); } @Test @@ -359,8 +339,17 @@ public class QSTileImplTest extends SysuiTestCase { } private static class TileImpl extends QSTileImpl { - protected TileImpl(QSHost host) { - super(host); + protected TileImpl( + QSHost host, + Looper backgroundLooper, + Handler mainHandler, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger + ) { + super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, + activityStarter, qsLogger); getState().state = Tile.STATE_ACTIVE; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt index 31992875df071..f70106a649688 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt @@ -17,13 +17,17 @@ package com.android.systemui.qs.tiles import android.content.Context +import android.os.Handler import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest -import com.android.systemui.Dependency +import com.android.internal.logging.MetricsLogger import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.logging.QSLogger import com.android.systemui.statusbar.policy.BatteryController import org.junit.Assert.assertEquals import org.junit.Before @@ -47,6 +51,14 @@ class BatterySaverTileTest : SysuiTestCase() { @Mock private lateinit var qsHost: QSHost @Mock + private lateinit var metricsLogger: MetricsLogger + @Mock + private lateinit var statusBarStateController: StatusBarStateController + @Mock + private lateinit var activityStarter: ActivityStarter + @Mock + private lateinit var qsLogger: QSLogger + @Mock private lateinit var batteryController: BatteryController private lateinit var testableLooper: TestableLooper private lateinit var tile: BatterySaverTile @@ -55,11 +67,18 @@ class BatterySaverTileTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) - mDependency.injectTestDependency(Dependency.BG_LOOPER, testableLooper.looper) `when`(qsHost.userContext).thenReturn(userContext) `when`(userContext.userId).thenReturn(USER) - tile = BatterySaverTile(qsHost, batteryController) + tile = BatterySaverTile( + qsHost, + testableLooper.looper, + Handler(testableLooper.looper), + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger, + batteryController) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index 853b2dbbc485e..8ece62281f77d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.media.projection.MediaProjectionInfo; +import android.os.Handler; import android.service.quicksettings.Tile; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -34,10 +35,12 @@ import android.testing.TestableLooper; import androidx.lifecycle.LifecycleOwner; import androidx.test.filters.SmallTest; -import com.android.systemui.Dependency; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSTileHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -71,6 +74,12 @@ public class CastTileTest extends SysuiTestCase { private QSTileHost mHost; @Mock NetworkController.SignalCallback mCallback; + @Mock + private MetricsLogger mMetricsLogger; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private QSLogger mQSLogger; private TestableLooper mTestableLooper; private CastTile mCastTile; @@ -80,16 +89,20 @@ public class CastTileTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); - mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper()); - mController = mDependency.injectMockDependency(CastController.class); - mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class); - mKeyguard = mDependency.injectMockDependency(KeyguardStateController.class); - mNetworkController = mDependency.injectMockDependency(NetworkController.class); - when(mHost.getContext()).thenReturn(mContext); - mCastTile = new CastTile(mHost, mController, mKeyguard, mNetworkController, - mActivityStarter); + mCastTile = new CastTile( + mHost, + mTestableLooper.getLooper(), + new Handler(mTestableLooper.getLooper()), + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQSLogger, + mController, + mKeyguard, + mNetworkController + ); // We are not setting the mocks to listening, so we trigger a first refresh state to // set the initial state diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java index 5a68238799423..2d276bb876f34 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java @@ -23,16 +23,20 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.os.Handler; import android.service.quicksettings.Tile; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import androidx.test.filters.SmallTest; -import com.android.systemui.Dependency; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSTileHost; +import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; @@ -43,7 +47,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper(setAsMainLooper = true) +@TestableLooper.RunWithLooper() @SmallTest public class ScreenRecordTileTest extends SysuiTestCase { @@ -53,6 +57,14 @@ public class ScreenRecordTileTest extends SysuiTestCase { private QSTileHost mHost; @Mock private KeyguardDismissUtil mKeyguardDismissUtil; + @Mock + private MetricsLogger mMetricsLogger; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private ActivityStarter mActivityStarter; + @Mock + private QSLogger mQSLogger; private TestableLooper mTestableLooper; private ScreenRecordTile mTile; @@ -62,12 +74,20 @@ public class ScreenRecordTileTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); - mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper()); - mController = mDependency.injectMockDependency(RecordingController.class); when(mHost.getContext()).thenReturn(mContext); - mTile = new ScreenRecordTile(mHost, mController, mKeyguardDismissUtil); + mTile = new ScreenRecordTile( + mHost, + mTestableLooper.getLooper(), + new Handler(mTestableLooper.getLooper()), + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQSLogger, + mController, + mKeyguardDismissUtil + ); } // Test that the tile is inactive and labeled correctly when the controller is neither starting From 6af74807f258bbe6cb60a346594fc930c673196b Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 5 Aug 2020 10:50:35 -0400 Subject: [PATCH 3/4] Enforce setCurrentState calls are on main thread These calls need to be done in main thread. Now that it's enforced by LifecycleRegistry, it should also be enforced here. Fixes: 162923566 Test: manual Change-Id: I569123ca240bec24f805ab87dfab25daf3545844 Merged-In: I569123ca240bec24f805ab87dfab25daf3545844 (cherry picked from commit 033a5ef99c55baec6b370d61823cbc52bdc9fa16) --- .../src/com/android/systemui/qs/tileimpl/QSTileImpl.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 8c485a6a950f7..d2aaaede3f4b3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -451,15 +451,17 @@ public abstract class QSTileImpl implements QSTile, Lifecy if (listening) { if (mListeners.add(listener) && mListeners.size() == 1) { if (DEBUG) Log.d(TAG, "handleSetListening true"); - mLifecycle.setCurrentState(RESUMED); handleSetListening(listening); - refreshState(); // Ensure we get at least one refresh after listening. + mUiHandler.post(() -> { + mLifecycle.setCurrentState(RESUMED); + refreshState(); // Ensure we get at least one refresh after listening. + }); } } else { if (mListeners.remove(listener) && mListeners.size() == 0) { if (DEBUG) Log.d(TAG, "handleSetListening false"); - mLifecycle.setCurrentState(STARTED); handleSetListening(listening); + mUiHandler.post(() -> mLifecycle.setCurrentState(STARTED)); } } updateIsFullQs(); From 8cf0a2a2922ae696bc2127b4d4dd467cafbdc809 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Mon, 10 Aug 2020 12:00:40 -0400 Subject: [PATCH 4/4] setCurrentState(DESTROYED) called from main thread Also address timing issues with bouncing calls between 2 handlers. In particular, make sure that after a tile is DESTROYED, the state doesn't change anymore due to leftover refreshState calls. This sometimes would be caused as the result of an earlier tile added as a callback on something that replies on add. Make sure that tests that instantiate a QSTileImpl use the main looper for the passed handler. Test: atest TileServiceTest BooleanTileServiceTest Test: manual, open QSCustomizer that destroys tiles Test: atest SystemUITests Change-Id: I77c61f743510cdcca54fa37cd26062a3c96bd649 Merged-In: I77c61f743510cdcca54fa37cd26062a3c96bd649 (cherry picked from commit 3744d134add89693e1241abda0de7750ab1f7638) --- .../systemui/qs/tileimpl/QSTileImpl.java | 16 ++++++++++++-- .../android/systemui/qs/QSTileHostTest.java | 2 +- .../systemui/qs/external/CustomTileTest.kt | 2 +- .../systemui/qs/tileimpl/QSTileImplTest.java | 21 +++++++++++++++++++ .../systemui/qs/tiles/BatterySaverTileTest.kt | 2 +- .../systemui/qs/tiles/CastTileTest.java | 2 +- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index d2aaaede3f4b3..255513a31c752 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -14,6 +14,7 @@ package com.android.systemui.qs.tileimpl; +import static androidx.lifecycle.Lifecycle.State.CREATED; import static androidx.lifecycle.Lifecycle.State.DESTROYED; import static androidx.lifecycle.Lifecycle.State.RESUMED; import static androidx.lifecycle.Lifecycle.State.STARTED; @@ -173,6 +174,7 @@ public abstract class QSTileImpl implements QSTile, Lifecy mState = newTileState(); mTmpState = newTileState(); + mUiHandler.post(() -> mLifecycle.setCurrentState(CREATED)); } protected final void resetStates() { @@ -453,6 +455,9 @@ public abstract class QSTileImpl implements QSTile, Lifecy if (DEBUG) Log.d(TAG, "handleSetListening true"); handleSetListening(listening); mUiHandler.post(() -> { + // This tile has been destroyed, the state should not change anymore and we + // should not refresh it anymore. + if (mLifecycle.getCurrentState().equals(DESTROYED)) return; mLifecycle.setCurrentState(RESUMED); refreshState(); // Ensure we get at least one refresh after listening. }); @@ -461,7 +466,11 @@ public abstract class QSTileImpl implements QSTile, Lifecy if (mListeners.remove(listener) && mListeners.size() == 0) { if (DEBUG) Log.d(TAG, "handleSetListening false"); handleSetListening(listening); - mUiHandler.post(() -> mLifecycle.setCurrentState(STARTED)); + mUiHandler.post(() -> { + // This tile has been destroyed, the state should not change anymore. + if (mLifecycle.getCurrentState().equals(DESTROYED)) return; + mLifecycle.setCurrentState(STARTED); + }); } } updateIsFullQs(); @@ -488,11 +497,14 @@ public abstract class QSTileImpl implements QSTile, Lifecy mQSLogger.logTileDestroyed(mTileSpec, "Handle destroy"); if (mListeners.size() != 0) { handleSetListening(false); + mListeners.clear(); } mCallbacks.clear(); mHandler.removeCallbacksAndMessages(null); // This will force it to be removed from all controllers that may have it registered. - mLifecycle.setCurrentState(DESTROYED); + mUiHandler.post(() -> { + mLifecycle.setCurrentState(DESTROYED); + }); } protected void checkIfRestrictionEnforcedByAdminOnly(State state, String userRestriction) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java index bdb7166f5db16..c8e1a74d969fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java @@ -78,7 +78,7 @@ import javax.inject.Provider; @RunWith(AndroidTestingRunner.class) @SmallTest -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) public class QSTileHostTest extends SysuiTestCase { private static String MOCK_STATE_STRING = "MockState"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt index c2579dd46e789..3aa40dec1fad4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt @@ -53,7 +53,7 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper +@TestableLooper.RunWithLooper(setAsMainLooper = true) class CustomTileTest : SysuiTestCase() { companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java index 103e5586f395c..7f74f9f28fad3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java @@ -244,6 +244,8 @@ public class QSTileImplTest extends SysuiTestCase { assertNotEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); mTile.handleDestroy(); + mTestableLooper.processAllMessages(); + assertEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); } @@ -298,6 +300,25 @@ public class QSTileImplTest extends SysuiTestCase { assertNotEquals(DESTROYED, mTile.getLifecycle().getCurrentState()); } + @Test + public void testRefreshStateAfterDestroyedDoesNotCrash() { + mTile.destroy(); + mTile.refreshState(); + + mTestableLooper.processAllMessages(); + } + + @Test + public void testSetListeningAfterDestroyedDoesNotCrash() { + Object o = new Object(); + mTile.destroy(); + + mTile.setListening(o, true); + mTile.setListening(o, false); + + mTestableLooper.processAllMessages(); + } + private void assertEvent(UiEventLogger.UiEventEnum eventType, UiEventLoggerFake.FakeUiEvent fakeEvent) { assertEquals(eventType.getId(), fakeEvent.eventId); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt index f70106a649688..2006a75c0e164 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt @@ -38,7 +38,7 @@ import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) @SmallTest class BatterySaverTileTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index 8ece62281f77d..5d14898cdd2cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -58,7 +58,7 @@ import java.util.List; @RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper +@TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest public class CastTileTest extends SysuiTestCase {