Fix leaks in sysui

Add support for testing for PluginManager and TunerService leaks
and add tests for the known leaks and fix them. Also port PluginManager
and TunerService to Dependency to make them easier to handle in
tests.

Test: runtest systemui
Change-Id: I5642539ee24dd72f802905106decd0c87b41b4eb
Fixes: 34846972
This commit is contained in:
Jason Monk
2017-02-01 19:26:30 -05:00
parent 3355950785
commit de850bbcaa
42 changed files with 373 additions and 114 deletions

View File

@@ -70,7 +70,7 @@ public class PluginManager extends BroadcastReceiver {
private boolean mListening;
private boolean mHasOneShot;
private PluginManager(Context context) {
public PluginManager(Context context) {
this(context, new PluginInstanceManagerFactory(),
Build.IS_DEBUGGABLE, Thread.getDefaultUncaughtExceptionHandler());
}
@@ -252,13 +252,6 @@ public class PluginManager extends BroadcastReceiver {
return new PluginContextWrapper(mContext.createApplicationContext(info, 0), classLoader);
}
public static PluginManager getInstance(Context context) {
if (sInstance == null) {
sInstance = new PluginManager(context.getApplicationContext());
}
return sInstance;
}
private class AllPluginClassLoader extends ClassLoader {
public AllPluginClassLoader(ClassLoader classLoader) {
super(classLoader);

View File

@@ -32,6 +32,8 @@ public interface NavGesture extends Plugin {
public boolean onInterceptTouchEvent(MotionEvent event);
public void setBarState(boolean vertical, boolean isRtl);
public default void destroy() { }
}
}

View File

@@ -76,7 +76,7 @@ public class BatteryMeterView extends ImageView implements
mDrawable.setBatteryController(mBatteryController);
mBatteryController.addCallback(this);
mDrawable.startListening();
TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
}
@Override
@@ -84,7 +84,7 @@ public class BatteryMeterView extends ImageView implements
super.onDetachedFromWindow();
mBatteryController.removeCallback(this);
mDrawable.stopListening();
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
}
@Override

View File

@@ -14,6 +14,7 @@
package com.android.systemui;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.HandlerThread;
@@ -23,6 +24,7 @@ import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -56,9 +58,11 @@ import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import com.android.systemui.tuner.TunerService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
/**
* Class to handle ugly dependencies throughout sysui until we determine the
@@ -167,12 +171,18 @@ public class Dependency extends SystemUI {
mProviders.put(DeviceProvisionedController.class.getName(), () ->
new DeviceProvisionedControllerImpl(mContext));
mProviders.put(PluginManager.class.getName(), () ->
new PluginManager(mContext));
mProviders.put(AssistManager.class.getName(), () ->
new AssistManager(getDependency(DeviceProvisionedController.class), mContext));
mProviders.put(SecurityController.class.getName(), () ->
new SecurityControllerImpl(mContext));
mProviders.put(TunerService.class.getName(), () ->
new TunerService(mContext));
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
@@ -220,6 +230,17 @@ public class Dependency extends SystemUI {
T createDependency();
}
/**
* Used in separate processes (like tuner settings) to init the dependencies.
*/
public static void initDependencies(Context context) {
if (sDependency != null) return;
Dependency d = new Dependency();
d.mContext = context.getApplicationContext();
d.mComponents = new HashMap<>();
d.start();
}
public static <T> T get(Class<T> cls) {
return sDependency.getDependency(cls.getName());
}

View File

@@ -76,7 +76,7 @@ public class PluginInflateContainer extends AutoReinflateContainer
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mAction != null) {
PluginManager.getInstance(getContext()).addPluginListener(mAction, this, mVersion);
Dependency.get(PluginManager.class).addPluginListener(mAction, this, mVersion);
}
}
@@ -84,7 +84,7 @@ public class PluginInflateContainer extends AutoReinflateContainer
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAction != null) {
PluginManager.getInstance(getContext()).removePluginListener(this);
Dependency.get(PluginManager.class).removePluginListener(this);
}
}

View File

@@ -65,7 +65,6 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
private final Class<?>[] SERVICES = new Class[] {
Dependency.class,
FragmentService.class,
TunerService.class,
NotificationChannels.class,
CommandQueue.CommandQueueStart.class,
KeyguardViewMediator.class,
@@ -205,7 +204,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
mServices[i].onBootCompleted();
}
}
PluginManager.getInstance(this).addPluginListener(OverlayPlugin.ACTION,
Dependency.get(PluginManager.class).addPluginListener(OverlayPlugin.ACTION,
new PluginListener<OverlayPlugin>() {
@Override
public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {

View File

@@ -19,6 +19,7 @@ package com.android.systemui.doze;
import android.service.dreams.DreamService;
import android.util.Log;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.doze.DozeProvider;
@@ -47,7 +48,7 @@ public class DozeService extends DreamService implements DozeMachine.Service {
return;
}
DozeProvider provider = PluginManager.getInstance(this)
DozeProvider provider = Dependency.get(PluginManager.class)
.getOneShotPlugin(DozeProvider.ACTION, DozeProvider.VERSION);
mDozeMachine = new DozeFactory(provider).assembleMachine(this);
}

View File

@@ -19,6 +19,7 @@ import android.content.Context;
import android.util.Log;
import android.view.View;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.FragmentBase;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
@@ -38,7 +39,7 @@ public class PluginFragmentListener implements PluginListener<Plugin> {
Class<? extends FragmentBase> expectedInterface) {
mTag = tag;
mFragmentHostManager = FragmentHostManager.get(view);
mPluginManager = PluginManager.getInstance(view.getContext());
mPluginManager = Dependency.get(PluginManager.class);
mExpectedInterface = expectedInterface;
mDefaultClass = defaultFragment;
}

View File

@@ -49,6 +49,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BackgroundThread;
import com.android.internal.policy.PipMotionHelper;
import com.android.internal.policy.PipSnapAlgorithm;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.tuner.TunerService;
@@ -200,7 +201,7 @@ public class PipTouchHandler implements TunerService.Tunable {
setSnapToEdge(true);
// Register any tuner settings changes
TunerService.get(context).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS,
Dependency.get(TunerService.class).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS,
TUNER_KEY_ALLOW_MINIMIZE);
}

View File

@@ -20,6 +20,7 @@ import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnLayoutChangeListener;
import android.widget.TextView;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.PagedTileLayout.PageListener;
import com.android.systemui.qs.QSPanel.QSTileLayout;
@@ -105,7 +106,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
@Override
public void onViewAttachedToWindow(View v) {
TunerService.get(mQs.getContext()).addTunable(this, ALLOW_FANCY_ANIMATION,
Dependency.get(TunerService.class).addTunable(this, ALLOW_FANCY_ANIMATION,
MOVE_FULL_ROWS, QuickQSPanel.NUM_QUICK_TILES);
}
@@ -114,7 +115,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mHost != null) {
mHost.removeCallback(this);
}
TunerService.get(mQs.getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
}
@Override

View File

@@ -29,6 +29,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QS.DetailAdapter;
@@ -126,7 +127,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
TunerService.get(mContext).addTunable(this, QS_SHOW_BRIGHTNESS);
Dependency.get(TunerService.class).addTunable(this, QS_SHOW_BRIGHTNESS);
if (mHost != null) {
setTiles(mHost.getTiles());
}
@@ -134,8 +135,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
@Override
protected void onDetachedFromWindow() {
TunerService.get(mContext).removeTunable(this);
mHost.removeCallback(this);
Dependency.get(TunerService.class).removeTunable(this);
if (mHost != null) {
mHost.removeCallback(this);
}
for (TileRecord record : mRecords) {
record.tile.removeCallbacks();
}

View File

@@ -24,6 +24,7 @@ import android.view.View;
import android.widget.LinearLayout;
import android.widget.Space;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile.SignalState;
import com.android.systemui.qs.QSTile.State;
@@ -62,13 +63,13 @@ public class QuickQSPanel extends QSPanel {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
TunerService.get(mContext).addTunable(mNumTiles, NUM_QUICK_TILES);
Dependency.get(TunerService.class).addTunable(mNumTiles, NUM_QUICK_TILES);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
TunerService.get(mContext).removeTunable(mNumTiles);
Dependency.get(TunerService.class).removeTunable(mNumTiles);
}
public void setQSPanelAndHeader(QSPanel fullPanel, View header) {
@@ -141,7 +142,7 @@ public class QuickQSPanel extends QSPanel {
};
public int getNumQuickTiles(Context context) {
return TunerService.get(context).getValue(NUM_QUICK_TILES, 6);
return Dependency.get(TunerService.class).getValue(NUM_QUICK_TILES, 6);
}
private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {

View File

@@ -30,6 +30,7 @@ import android.widget.FrameLayout;
import java.util.ArrayList;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
@@ -82,10 +83,21 @@ public class NotificationMenuRow extends FrameLayout
public NotificationMenuRow(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs);
PluginManager.getInstance(getContext()).addPluginListener(
mMenuItems.addAll(getDefaultNotificationMenuItems());
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Dependency.get(PluginManager.class).addPluginListener(
NotificationMenuRowProvider.ACTION, this,
NotificationMenuRowProvider.VERSION, false /* Allow multiple */);
mMenuItems.addAll(getDefaultNotificationMenuItems());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Dependency.get(PluginManager.class).removePluginListener(this);
}
@Override

View File

@@ -220,7 +220,7 @@ public class SignalClusterView
int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0;
mMobileSignalGroup.setPaddingRelative(0, 0, endPadding, 0);
TunerService.get(mContext).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
apply();
applyIconTint();
@@ -231,7 +231,7 @@ public class SignalClusterView
@Override
protected void onDetachedFromWindow() {
mMobileSignalGroup.removeAllViews();
TunerService.get(mContext).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
mSecurityController.removeCallback(this);
mNetworkController.removeCallback(this);

View File

@@ -257,11 +257,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mAccessibilityController.addStateChangedCallback(this);
PluginManager.getInstance(getContext()).addPluginListener(RIGHT_BUTTON_PLUGIN,
Dependency.get(PluginManager.class).addPluginListener(RIGHT_BUTTON_PLUGIN,
mRightListener, IntentButtonProvider.VERSION, false /* Only allow one */);
PluginManager.getInstance(getContext()).addPluginListener(LEFT_BUTTON_PLUGIN,
Dependency.get(PluginManager.class).addPluginListener(LEFT_BUTTON_PLUGIN,
mLeftListener, IntentButtonProvider.VERSION, false /* Only allow one */);
TunerService.get(getContext()).addTunable(this, LockscreenFragment.LOCKSCREEN_LEFT_BUTTON,
Dependency.get(TunerService.class).addTunable(this, LockscreenFragment.LOCKSCREEN_LEFT_BUTTON,
LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON);
}
@@ -269,9 +269,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mAccessibilityController.removeStateChangedCallback(this);
PluginManager.getInstance(getContext()).removePluginListener(mRightListener);
PluginManager.getInstance(getContext()).removePluginListener(mLeftListener);
TunerService.get(getContext()).removeTunable(this);
Dependency.get(PluginManager.class).removePluginListener(mRightListener);
Dependency.get(PluginManager.class).removePluginListener(mLeftListener);
Dependency.get(TunerService.class).removeTunable(this);
}
private void initAccessibility() {
@@ -573,7 +573,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
AsyncTask.execute(runnable);
} else {
boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
&& TunerService.get(getContext()).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
&& Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
mStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
dismissShade, false /* afterKeyguardGone */, true /* deferred */);
}
@@ -594,7 +594,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
});
} else {
boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr)
&& TunerService.get(getContext()).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
&& Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade);
}
}

View File

@@ -29,6 +29,7 @@ import android.view.ViewConfiguration;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
@@ -87,7 +88,11 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL
mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
mTaskSwitcherDetector = new GestureDetector(context, this);
TunerService.get(context).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
}
public void destroy() {
Dependency.get(TunerService.class).removeTunable(this);
}
public void setComponents(RecentsComponent recentsComponent, Divider divider,

View File

@@ -30,6 +30,7 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
@@ -135,15 +136,16 @@ public class NavigationBarInflaterView extends FrameLayout
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS, NAV_BAR_LEFT,
Dependency.get(TunerService.class).addTunable(this, NAV_BAR_VIEWS, NAV_BAR_LEFT,
NAV_BAR_RIGHT);
PluginManager.getInstance(getContext()).addPluginListener(NavBarButtonProvider.ACTION, this,
Dependency.get(PluginManager.class).addPluginListener(NavBarButtonProvider.ACTION, this,
NavBarButtonProvider.VERSION, true /* Allow multiple */);
}
@Override
protected void onDetachedFromWindow() {
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
Dependency.get(PluginManager.class).removePluginListener(this);
super.onDetachedFromWindow();
}
@@ -278,10 +280,10 @@ public class NavigationBarInflaterView extends FrameLayout
View v = null;
String button = extractButton(buttonSpec);
if (LEFT.equals(button)) {
buttonSpec = TunerService.get(mContext).getValue(NAV_BAR_LEFT, NAVSPACE);
buttonSpec = Dependency.get(TunerService.class).getValue(NAV_BAR_LEFT, NAVSPACE);
button = extractButton(buttonSpec);
} else if (RIGHT.equals(button)) {
buttonSpec = TunerService.get(mContext).getValue(NAV_BAR_RIGHT, MENU_IME);
buttonSpec = Dependency.get(TunerService.class).getValue(NAV_BAR_RIGHT, MENU_IME);
button = extractButton(buttonSpec);
}
// Let plugins go first so they can override a standard view if they want.

View File

@@ -46,6 +46,7 @@ import android.view.WindowManagerGlobal;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.plugins.PluginListener;
@@ -200,7 +201,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
mVertical = false;
mShowMenu = false;
mGestureHelper = new NavigationBarGestureHelper(context);
mConfiguration = new Configuration();
mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -633,6 +633,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
}
private void updateTaskSwitchHelper() {
if (mGestureHelper == null) return;
boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
mGestureHelper.setBarState(mVertical, isRtl);
}
@@ -752,14 +753,18 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
PluginManager.getInstance(getContext()).addPluginListener(NavGesture.ACTION, this,
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(NavGesture.ACTION, this,
NavGesture.VERSION, false /* Only one */);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
PluginManager.getInstance(getContext()).removePluginListener(this);
Dependency.get(PluginManager.class).removePluginListener(this);
if (mGestureHelper != null) {
mGestureHelper.destroy();
}
}
@Override
@@ -772,6 +777,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
public void onPluginDisconnected(NavGesture plugin) {
NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
defaultHelper.setComponents(mRecentsComponent, mDivider, this);
if (mGestureHelper != null) {
mGestureHelper.destroy();
}
mGestureHelper = defaultHelper;
updateTaskSwitchHelper();
}

View File

@@ -89,7 +89,7 @@ public class QSTileHost implements QSTile.Host, Tunable {
mServices = new TileServices(this, Dependency.get(Dependency.BG_LOOPER));
TunerService.get(mContext).addTunable(this, TILES_SETTING);
Dependency.get(TunerService.class).addTunable(this, TILES_SETTING);
// AutoTileManager can modify mTiles so make sure mTiles has already been initialized.
mAutoTiles = new AutoTileManager(context, this);
}
@@ -101,7 +101,7 @@ public class QSTileHost implements QSTile.Host, Tunable {
public void destroy() {
mTiles.values().forEach(tile -> tile.destroy());
mAutoTiles.destroy();
TunerService.get(mContext).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
mServices.destroy();
}

View File

@@ -36,6 +36,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -127,7 +128,7 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
loadDimens();
TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
mTransitionsController = new LightBarTransitionsController(this::setIconTintInternal);
}

View File

@@ -108,7 +108,7 @@ public class Clock extends TextView implements DemoMode, Tunable {
getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter,
null, Dependency.get(Dependency.TIME_TICK_HANDLER));
TunerService.get(getContext()).addTunable(this, CLOCK_SECONDS,
Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
StatusBarIconController.ICON_BLACKLIST);
}
@@ -129,7 +129,7 @@ public class Clock extends TextView implements DemoMode, Tunable {
if (mAttached) {
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
}
}

View File

@@ -22,6 +22,7 @@ import android.util.ArraySet;
import android.util.AttributeSet;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
@@ -49,12 +50,12 @@ public class BatteryPreference extends DropDownPreference implements TunerServic
super.onAttached();
mHasPercentage = Settings.System.getInt(getContext().getContentResolver(),
SHOW_PERCENT_SETTING, 0) != 0;
TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
}
@Override
public void onDetached() {
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
super.onDetached();
}
@@ -89,7 +90,7 @@ public class BatteryPreference extends DropDownPreference implements TunerServic
} else {
mBlacklist.remove(mBattery);
}
TunerService.get(getContext()).setValue(StatusBarIconController.ICON_BLACKLIST,
Dependency.get(TunerService.class).setValue(StatusBarIconController.ICON_BLACKLIST,
TextUtils.join(",", mBlacklist));
return true;
}

View File

@@ -18,6 +18,8 @@ import android.support.v7.preference.DropDownPreference;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.Clock;
@@ -44,13 +46,13 @@ public class ClockPreference extends DropDownPreference implements TunerService.
@Override
public void onAttached() {
super.onAttached();
TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST,
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST,
Clock.CLOCK_SECONDS);
}
@Override
public void onDetached() {
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
super.onDetached();
}
@@ -81,13 +83,14 @@ public class ClockPreference extends DropDownPreference implements TunerService.
@Override
protected boolean persistString(String value) {
TunerService.get(getContext()).setValue(Clock.CLOCK_SECONDS, SECONDS.equals(value) ? 1 : 0);
Dependency.get(TunerService.class).setValue(Clock.CLOCK_SECONDS, SECONDS.equals(value) ? 1
: 0);
if (DISABLED.equals(value)) {
mBlacklist.add(mClock);
} else {
mBlacklist.remove(mClock);
}
TunerService.get(getContext()).setValue(StatusBarIconController.ICON_BLACKLIST,
Dependency.get(TunerService.class).setValue(StatusBarIconController.ICON_BLACKLIST,
TextUtils.join(",", mBlacklist));
return true;
}

View File

@@ -43,6 +43,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
import com.android.systemui.statusbar.phone.ExpandableIndicator;
@@ -71,7 +72,7 @@ public class LockscreenFragment extends PreferenceFragment {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
mTunerService = TunerService.get(getContext());
mTunerService = Dependency.get(TunerService.class);
mHandler = new Handler();
addPreferencesFromResource(R.xml.lockscreen_settings);
setupGroup((PreferenceGroup) findPreference(KEY_LEFT), LOCKSCREEN_LEFT_BUTTON,

View File

@@ -51,6 +51,7 @@ import android.util.TypedValue;
import android.view.KeyEvent;
import android.widget.EditText;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -104,12 +105,12 @@ public class NavBarTuner extends PreferenceFragment {
@Override
public void onDestroy() {
super.onDestroy();
mTunables.forEach(t -> TunerService.get(getContext()).removeTunable(t));
mTunables.forEach(t -> Dependency.get(TunerService.class).removeTunable(t));
}
private void addTunable(Tunable tunable, String... keys) {
mTunables.add(tunable);
TunerService.get(getContext()).addTunable(tunable, keys);
Dependency.get(TunerService.class).addTunable(tunable, keys);
}
private void bindLayout(ListPreference preference) {
@@ -123,7 +124,7 @@ public class NavBarTuner extends PreferenceFragment {
preference.setOnPreferenceChangeListener((preference1, newValue) -> {
String val = (String) newValue;
if ("default".equals(val)) val = null;
TunerService.get(getContext()).setValue(NAV_BAR_VIEWS, val);
Dependency.get(TunerService.class).setValue(NAV_BAR_VIEWS, val);
return true;
});
}
@@ -215,7 +216,7 @@ public class NavBarTuner extends PreferenceFragment {
}
button = button + KEY_CODE_START + code + KEY_IMAGE_DELIM + uri + KEY_CODE_END;
}
TunerService.get(getContext()).setValue(setting, button);
Dependency.get(TunerService.class).setValue(setting, button);
}
private void setupIcons(ListPreference icon) {

View File

@@ -18,6 +18,7 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
public class PreviewNavInflater extends NavigationBarInflaterView {
@@ -31,7 +32,7 @@ public class PreviewNavInflater extends NavigationBarInflaterView {
super.onAttachedToWindow();
// Immediately remove tuner listening, since this is a preview, all values will be injected
// manually.
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
}
@Override

View File

@@ -25,6 +25,7 @@ import android.util.AttributeSet;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -41,12 +42,12 @@ public class StatusBarSwitch extends SwitchPreference implements Tunable {
@Override
public void onAttached() {
super.onAttached();
TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
}
@Override
public void onDetached() {
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
super.onDetached();
}

View File

@@ -24,6 +24,7 @@ import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.systemui.Dependency;
import com.android.systemui.R;
public class TunerActivity extends SettingsDrawerActivity implements
@@ -36,6 +37,7 @@ public class TunerActivity extends SettingsDrawerActivity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Dependency.initDependencies(this);
if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) {
final String action = getIntent().getAction();

View File

@@ -40,6 +40,7 @@ import android.util.ArraySet;
import com.android.systemui.BatteryMeterDrawable;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
@@ -51,7 +52,7 @@ import java.util.HashMap;
import java.util.Set;
public class TunerService extends SystemUI {
public class TunerService {
public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER";
@@ -64,13 +65,14 @@ public class TunerService extends SystemUI {
private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
// Map of settings keys to the listener.
private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
private final Context mContext;
private ContentResolver mContentResolver;
private int mCurrentUser;
private CurrentUserTracker mUserTracker;
@Override
public void start() {
public TunerService(Context context) {
mContext = context;
mContentResolver = mContext.getContentResolver();
for (UserInfo user : UserManager.get(mContext).getUsers()) {
@@ -79,7 +81,6 @@ public class TunerService extends SystemUI {
upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION);
}
}
putComponent(TunerService.class, this);
mCurrentUser = ActivityManager.getCurrentUser();
mUserTracker = new CurrentUserTracker(mContext) {
@@ -209,32 +210,6 @@ public class TunerService extends SystemUI {
}
}
// Only used in other processes, such as the tuner.
private static TunerService sInstance;
public static TunerService get(Context context) {
TunerService service = null;
if (context.getApplicationContext() instanceof SystemUIApplication) {
SystemUIApplication sysUi = (SystemUIApplication) context.getApplicationContext();
service = sysUi.getComponent(TunerService.class);
}
if (service == null) {
// Can't get it as a component, must in the tuner, lets just create one for now.
return getStaticService(context);
}
return service;
}
private static TunerService getStaticService(Context context) {
if (sInstance == null) {
sInstance = new TunerService();
sInstance.mContext = context.getApplicationContext();
sInstance.mComponents = new HashMap<>();
sInstance.start();
}
return sInstance;
}
public static final void showResetRequest(final Context context, final Runnable onDisabled) {
SystemUIDialog dialog = new SystemUIDialog(context);
dialog.setShowForAllUsers(true);
@@ -310,7 +285,7 @@ public class TunerService extends SystemUI {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_CLEAR.equals(intent.getAction())) {
get(context).clearAll();
Dependency.get(TunerService.class).clearAll();
}
}
}

View File

@@ -7,6 +7,7 @@ import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -26,12 +27,12 @@ public class TunerSwitch extends SwitchPreference implements Tunable {
@Override
public void onAttached() {
super.onAttached();
TunerService.get(getContext()).addTunable(this, getKey().split(","));
Dependency.get(TunerService.class).addTunable(this, getKey().split(","));
}
@Override
public void onDetached() {
TunerService.get(getContext()).removeTunable(this);
Dependency.get(TunerService.class).removeTunable(this);
super.onDetached();
}

View File

@@ -69,6 +69,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -165,7 +166,7 @@ public class VolumeDialog implements TunerService.Tunable {
controller.addCallback(mControllerCallbackH, mHandler);
controller.getState();
TunerService.get(mContext).addTunable(this, SHOW_FULL_ZEN);
Dependency.get(TunerService.class).addTunable(this, SHOW_FULL_ZEN);
final Configuration currentConfig = mContext.getResources().getConfiguration();
mDensity = currentConfig.densityDpi;

View File

@@ -72,7 +72,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
mDialog = new VolumeDialog(context, WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY,
mController, mZenModeController, mVolumeDialogCallback);
applyConfiguration();
TunerService.get(mContext).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
Dependency.get(TunerService.class).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
VOLUME_SILENT_DO_NOT_DISTURB);
}

View File

@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.systemui.tests">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

View File

@@ -19,13 +19,17 @@ import android.app.Fragment;
import android.app.FragmentController;
import android.app.FragmentHostCallback;
import android.app.FragmentManagerNonConfig;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import com.android.systemui.utils.ViewUtils;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.After;
@@ -45,7 +49,6 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
private static final int VIEW_ID = 42;
private final Class<? extends Fragment> mCls;
private HandlerThread mHandlerThread;
private Handler mHandler;
private FrameLayout mView;
protected FragmentController mFragments;
@@ -59,9 +62,7 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
public void setupFragment() throws IllegalAccessException, InstantiationException {
mView = new FrameLayout(mContext);
mView.setId(VIEW_ID);
mHandlerThread = new HandlerThread("FragmentTestThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mHandler = new Handler(Looper.getMainLooper());
mFragment = mCls.newInstance();
postAndWait(() -> {
mFragments = FragmentController.createController(new HostCallbacks());
@@ -78,7 +79,6 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
// Set mFragments to null to let it know not to destroy.
postAndWait(() -> mFragments.dispatchDestroy());
}
mHandlerThread.quit();
}
@Test
@@ -99,6 +99,26 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
postAndWait(() -> mFragments.dispatchPause());
}
@Test
public void testAttachDetach() {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
LayoutParams.TYPE_SYSTEM_ALERT,
0, PixelFormat.TRANSLUCENT);
postAndWait(() -> mFragments.dispatchResume());
attachFragmentToWindow();
detachFragmentToWindow();
postAndWait(() -> mFragments.dispatchPause());
}
protected void attachFragmentToWindow() {
ViewUtils.attachView(mView);
}
protected void detachFragmentToWindow() {
ViewUtils.detachView(mView);
}
@Test
public void testRecreate() {
postAndWait(() -> mFragments.dispatchResume());

View File

@@ -65,7 +65,7 @@ public abstract class SysuiTestCase {
waitForIdleSync(mHandler);
}
protected void waitForIdleSync(Handler h) {
public static void waitForIdleSync(Handler h) {
validateThread(h.getLooper());
Idler idler = new Idler(null);
h.getLooper().getQueue().addIdleHandler(idler);

View File

@@ -42,6 +42,7 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.Before;
import org.junit.Test;
@@ -60,11 +61,7 @@ public class QSFragmentTest extends FragmentTestCase {
public void addLeakCheckDependencies() {
injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
injectMockDependency(UserSwitcherController.class);
injectLeakCheckedDependencies(BluetoothController.class, LocationController.class,
RotationLockController.class, NetworkController.class, ZenModeController.class,
HotspotController.class, CastController.class, FlashlightController.class,
UserInfoController.class, KeyguardMonitor.class, SecurityController.class,
BatteryController.class, NextAlarmController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
}
@Test
@@ -88,6 +85,6 @@ public class QSFragmentTest extends FragmentTestCase {
host.destroy();
// Ensure the tuner cleans up its persistent listeners.
TunerService.get(mContext).destroy();
Dependency.get(TunerService.class).destroy();
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.statusbar;
import com.android.systemui.utils.ViewUtils;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.Before;
import org.junit.Test;
public class NotificationMenuRowTest extends LeakCheckedTest {
@Before
public void setup() {
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
}
@Test
public void testAttachDetach() {
NotificationMenuRow row = new NotificationMenuRow(mContext);
ViewUtils.attachView(row);
ViewUtils.detachView(row);
}
}

View File

@@ -40,6 +40,7 @@ public class NavigationBarFragmentTest extends FragmentTestCase {
mContext.putComponent(Recents.class, mock(Recents.class));
mContext.putComponent(Divider.class, mock(Divider.class));
mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
}
@Test

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.utils;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.support.test.InstrumentationRegistry;
import com.android.systemui.SysuiTestCase;
public class ViewUtils {
public static void attachView(View view) {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
LayoutParams.TYPE_SYSTEM_ALERT,
0, PixelFormat.TRANSLUCENT);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> InstrumentationRegistry.getContext()
.getSystemService(WindowManager.class).addView(view, lp));
SysuiTestCase.waitForIdleSync(handler);
}
public static void detachView(View view) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> InstrumentationRegistry.getContext()
.getSystemService(WindowManager.class).removeView(view));
SysuiTestCase.waitForIdleSync(handler);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.utils.leaks;
import android.content.Context;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
public class FakePluginManager extends PluginManager {
private final BaseLeakChecker<PluginListener> mLeakChecker;
public FakePluginManager(Context context, LeakCheckedTest test) {
super(context);
mLeakChecker = new BaseLeakChecker<>(test, "Plugin");
}
@Override
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
int version) {
mLeakChecker.addCallback(listener);
}
@Override
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
int version, boolean allowMultiple) {
mLeakChecker.addCallback(listener);
}
@Override
public void removePluginListener(PluginListener<?> listener) {
mLeakChecker.removeCallback(listener);
}
@Override
public <T extends Plugin> T getOneShotPlugin(String action, int version) {
return null;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.systemui.utils.leaks;
import android.content.Context;
import com.android.systemui.tuner.TunerService;
public class FakeTunerService extends TunerService {
private final BaseLeakChecker<Tunable> mBaseLeakChecker;
public FakeTunerService(Context context, LeakCheckedTest test) {
super(context);
mBaseLeakChecker = new BaseLeakChecker<>(test, "tunable");
}
@Override
public void addTunable(Tunable tunable, String... keys) {
for (String key : keys) {
tunable.onTuningChanged(key, null);
}
mBaseLeakChecker.addCallback(tunable);
}
@Override
public void removeTunable(Tunable tunable) {
mBaseLeakChecker.removeCallback(tunable);
}
}

View File

@@ -20,6 +20,7 @@ import static org.mockito.Mockito.doAnswer;
import android.util.ArrayMap;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -35,6 +36,7 @@ import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import org.junit.Assert;
import org.junit.Rule;
@@ -56,6 +58,25 @@ public abstract class LeakCheckedTest extends SysuiTestCase {
private final Map<String, Tracker> mTrackers = new HashMap<>();
private final Map<Class, Object> mLeakCheckers = new ArrayMap<>();
public static final Class<?>[] ALL_SUPPORTED_CLASSES = new Class[] {
BluetoothController.class,
LocationController.class,
RotationLockController.class,
ZenModeController.class,
CastController.class,
HotspotController.class,
FlashlightController.class,
UserInfoController.class,
KeyguardMonitor.class,
BatteryController.class,
SecurityController.class,
ManagedProfileController.class,
NextAlarmController.class,
NetworkController.class,
PluginManager.class,
TunerService.class,
};
@Rule
public TestWatcher successWatcher = new TestWatcher() {
@Override
@@ -96,6 +117,10 @@ public abstract class LeakCheckedTest extends SysuiTestCase {
obj = new FakeNextAlarmController(this);
} else if (cls == NetworkController.class) {
obj = new FakeNetworkController(this);
} else if (cls == PluginManager.class) {
obj = new FakePluginManager(mContext, this);
} else if (cls == TunerService.class) {
obj = new FakeTunerService(mContext, this);
} else {
Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
}