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:
@@ -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);
|
||||
|
||||
@@ -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() { }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user