Merge "Break VolumeDialogControllerImpl' dependency on StatusBar" into sc-dev
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index afda2a4..e9c5653 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -236,7 +236,7 @@
             Log.i(TAG, "ScreenDecorations is disabled");
             return;
         }
-        mHandler = mThreadFactory.builderHandlerOnNewThread("ScreenDecorations");
+        mHandler = mThreadFactory.buildHandlerOnNewThread("ScreenDecorations");
         mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler);
         mExecutor.execute(this::startOnScreenDecorationsThread);
         mDotViewController.setUiExecutor(mExecutor);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 26db33d..053d75d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -46,6 +46,7 @@
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.media.AudioManager;
+import android.media.IAudioService;
 import android.media.MediaRouter2Manager;
 import android.media.session.MediaSessionManager;
 import android.net.ConnectivityManager;
@@ -77,6 +78,8 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.shared.system.PackageManagerWrapper;
 
+import java.util.Optional;
+
 import javax.inject.Singleton;
 
 import dagger.Module;
@@ -167,6 +170,13 @@
 
     @Provides
     @Singleton
+    static IAudioService provideIAudioService() {
+        return IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE));
+    }
+
+
+    @Provides
+    @Singleton
     static IBatteryStats provideIBatteryStats() {
         return IBatteryStats.Stub.asInterface(
                 ServiceManager.getService(BatteryStats.SERVICE_NAME));
@@ -362,6 +372,12 @@
 
     @Provides
     @Singleton
+    static Optional<Vibrator> provideOptionalVibrator(Context context) {
+        return Optional.ofNullable(context.getSystemService(Vibrator.class));
+    }
+
+    @Provides
+    @Singleton
     static ViewConfiguration provideViewConfiguration(Context context) {
         return ViewConfiguration.get(context);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index ebf2465..b10e841 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -23,7 +23,6 @@
 import android.util.Log;
 
 import com.android.settingslib.mobile.TelephonyIcons;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.policy.NetworkController;
@@ -63,6 +62,7 @@
     private final SecurityController mSecurityController;
     private final Handler mHandler = Handler.getMain();
     private final CarrierConfigTracker mCarrierConfigTracker;
+    private final TunerService mTunerService;
 
     private boolean mHideAirplane;
     private boolean mHideMobile;
@@ -83,9 +83,16 @@
 
     @Inject
     public StatusBarSignalPolicy(Context context, StatusBarIconController iconController,
-            CarrierConfigTracker carrierConfigTracker) {
+            CarrierConfigTracker carrierConfigTracker, NetworkController networkController,
+            SecurityController securityController, TunerService tunerService) {
         mContext = context;
 
+        mIconController = iconController;
+        mCarrierConfigTracker = carrierConfigTracker;
+        mNetworkController = networkController;
+        mSecurityController = securityController;
+        mTunerService = tunerService;
+
         mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane);
         mSlotMobile   = mContext.getString(com.android.internal.R.string.status_bar_mobile);
         mSlotWifi     = mContext.getString(com.android.internal.R.string.status_bar_wifi);
@@ -96,18 +103,14 @@
                 mContext.getString(com.android.internal.R.string.status_bar_call_strength);
         mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
 
-        mIconController = iconController;
-        mCarrierConfigTracker = carrierConfigTracker;
-        mNetworkController = Dependency.get(NetworkController.class);
-        mSecurityController = Dependency.get(SecurityController.class);
 
-        Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
+        tunerService.addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
         mNetworkController.addCallback(this);
         mSecurityController.addCallback(this);
     }
 
     public void destroy() {
-        Dependency.get(TunerService.class).removeTunable(this);
+        mTunerService.removeTunable(this);
         mNetworkController.removeCallback(this);
         mSecurityController.removeCallback(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactory.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactory.java
index 7a5ceb5..fbec9e7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactory.java
@@ -30,12 +30,20 @@
  */
 public interface ThreadFactory {
     /**
+     * Returns a {@link Looper} running on a named thread.
+     *
+     * The thread is implicitly started and may be left running indefinitely, depending on the
+     * implementation. Assume this is the case and use responsibly.
+     */
+    Looper buildLooperOnNewThread(String threadName);
+
+    /**
      * Returns a {@link Handler} running on a named thread.
      *
      * The thread is implicitly started and may be left running indefinitely, depending on the
      * implementation. Assume this is the case and use responsibly.
      */
-    Handler builderHandlerOnNewThread(String threadName);
+    Handler buildHandlerOnNewThread(String threadName);
 
     /**
      * Return an {@link java.util.concurrent.Executor} running on a named thread.
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactoryImpl.java
index 184b831..051f433 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ThreadFactoryImpl.java
@@ -29,10 +29,15 @@
     ThreadFactoryImpl() {}
 
     @Override
-    public Handler builderHandlerOnNewThread(String threadName) {
+    public Looper buildLooperOnNewThread(String threadName) {
         HandlerThread handlerThread = new HandlerThread(threadName);
         handlerThread.start();
-        return new Handler(handlerThread.getLooper());
+        return handlerThread.getLooper();
+    }
+
+    @Override
+    public Handler buildHandlerOnNewThread(String threadName) {
+        return new Handler(buildLooperOnNewThread(threadName));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 3aba7ca..a5ccc47 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -38,11 +38,9 @@
 import android.media.session.MediaSession.Token;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
@@ -66,9 +64,9 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.RingerModeLiveData;
 import com.android.systemui.util.RingerModeTracker;
+import com.android.systemui.util.concurrency.ThreadFactory;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -80,8 +78,6 @@
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 /**
  *  Source of truth for all state / events related to the volume dialog.  No presentation.
  *
@@ -118,12 +114,13 @@
         STREAMS.put(AudioSystem.STREAM_VOICE_CALL, R.string.stream_voice_call);
     }
 
-    private final HandlerThread mWorkerThread;
     private final W mWorker;
     private final Context mContext;
+    private final Looper mWorkerLooper;
+    private final PackageManager mPackageManager;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
     private AudioManager mAudio;
     private IAudioService mAudioService;
-    private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
     private final NotificationManager mNoMan;
     private final SettingObserver mObserver;
     private final Receiver mReceiver = new Receiver();
@@ -132,13 +129,13 @@
     protected C mCallbacks = new C();
     private final State mState = new State();
     protected final MediaSessionsCallbacks mMediaSessionsCallbacksW = new MediaSessionsCallbacks();
-    private final Vibrator mVibrator;
+    private final Optional<Vibrator> mVibrator;
     private final boolean mHasVibrator;
     private boolean mShowA11yStream;
     private boolean mShowVolumeDialog;
     private boolean mShowSafetyWarning;
     private long mLastToggledRingerOn;
-    private final NotificationManager mNotificationManager;
+    private boolean mDeviceInteractive;
 
     private boolean mDestroyed;
     private VolumePolicy mVolumePolicy;
@@ -149,26 +146,42 @@
     protected final VC mVolumeController = new VC();
     protected final BroadcastDispatcher mBroadcastDispatcher;
 
-    @Inject
-    public VolumeDialogControllerImpl(Context context, BroadcastDispatcher broadcastDispatcher,
-            Optional<Lazy<StatusBar>> statusBarOptionalLazy, RingerModeTracker ringerModeTracker) {
-        mContext = context.getApplicationContext();
-        // TODO(b/150663459): remove this TV workaround once StatusBar is "unbound" on TVs
-        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
-            mStatusBarOptionalLazy = Optional.empty();
-        } else {
-            mStatusBarOptionalLazy = statusBarOptionalLazy;
+    private final WakefulnessLifecycle.Observer mWakefullnessLifecycleObserver =
+            new WakefulnessLifecycle.Observer() {
+        @Override
+        public void onStartedWakingUp() {
+            mDeviceInteractive = true;
         }
-        mNotificationManager = (NotificationManager) mContext.getSystemService(
-                Context.NOTIFICATION_SERVICE);
+
+        @Override
+        public void onFinishedGoingToSleep() {
+            mDeviceInteractive = false;
+        }
+    };
+
+    @Inject
+    public VolumeDialogControllerImpl(
+            Context context,
+            BroadcastDispatcher broadcastDispatcher,
+            RingerModeTracker ringerModeTracker,
+            ThreadFactory theadFactory,
+            AudioManager audioManager,
+            NotificationManager notificationManager,
+            Optional<Vibrator> optionalVibrator,
+            IAudioService iAudioService,
+            AccessibilityManager accessibilityManager,
+            PackageManager packageManager,
+            WakefulnessLifecycle wakefulnessLifecycle) {
+        mContext = context.getApplicationContext();
+        mPackageManager = packageManager;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
         Events.writeEvent(Events.EVENT_COLLECTION_STARTED);
-        mWorkerThread = new HandlerThread(VolumeDialogControllerImpl.class.getSimpleName());
-        mWorkerThread.start();
-        mWorker = new W(mWorkerThread.getLooper());
-        mMediaSessions = createMediaSessions(mContext, mWorkerThread.getLooper(),
-                mMediaSessionsCallbacksW);
-        mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        mWorkerLooper = theadFactory.buildLooperOnNewThread(
+                VolumeDialogControllerImpl.class.getSimpleName());
+        mWorker = new W(mWorkerLooper);
+        mMediaSessions = createMediaSessions(mContext, mWorkerLooper, mMediaSessionsCallbacksW);
+        mAudio = audioManager;
+        mNoMan = notificationManager;
         mObserver = new SettingObserver(mWorker);
         mRingerModeObservers = new RingerModeObservers(
                 (RingerModeLiveData) ringerModeTracker.getRingerMode(),
@@ -178,16 +191,17 @@
         mBroadcastDispatcher = broadcastDispatcher;
         mObserver.init();
         mReceiver.init();
-        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
-        mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
-        mAudioService = IAudioService.Stub.asInterface(
-                ServiceManager.getService(Context.AUDIO_SERVICE));
+        mVibrator = optionalVibrator;
+        mHasVibrator = mVibrator.isPresent() && mVibrator.get().hasVibrator();
+        mAudioService = iAudioService;
 
-        boolean accessibilityVolumeStreamActive = context.getSystemService(
-                AccessibilityManager.class).isAccessibilityVolumeStreamActive();
+        boolean accessibilityVolumeStreamActive = accessibilityManager
+                .isAccessibilityVolumeStreamActive();
         mVolumeController.setA11yMode(accessibilityVolumeStreamActive ?
                     VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
                         VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
+
+        mWakefulnessLifecycle.addObserver(mWakefullnessLifecycleObserver);
     }
 
     public AudioManager getAudioManager() {
@@ -203,7 +217,6 @@
             mAudio.setVolumeController(mVolumeController);
         } catch (SecurityException e) {
             Log.w(TAG, "Unable to set the volume controller", e);
-            return;
         }
     }
 
@@ -249,18 +262,6 @@
         return new MediaSessions(context, looper, callbacks);
     }
 
-    public void destroy() {
-        if (D.BUG) Log.d(TAG, "destroy");
-        if (mDestroyed) return;
-        mDestroyed = true;
-        Events.writeEvent(Events.EVENT_COLLECTION_STOPPED);
-        mMediaSessions.destroy();
-        mObserver.destroy();
-        mReceiver.destroy();
-        mRingerModeObservers.destroy();
-        mWorkerThread.quitSafely();
-    }
-
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(VolumeDialogControllerImpl.class.getSimpleName() + " state:");
         pw.print("  mDestroyed: "); pw.println(mDestroyed);
@@ -383,9 +384,8 @@
     }
 
     public void vibrate(VibrationEffect effect) {
-        if (mHasVibrator) {
-            mVibrator.vibrate(effect, SONIFICIATION_VIBRATION_ATTRIBUTES);
-        }
+        mVibrator.ifPresent(
+                vibrator -> vibrator.vibrate(effect, SONIFICIATION_VIBRATION_ATTRIBUTES));
     }
 
     public boolean hasVibrator() {
@@ -437,9 +437,8 @@
                 return;
             }
 
-            PackageManager packageManager = mContext.getPackageManager();
             mCallbacks.onCaptionComponentStateChanged(
-                    packageManager.getComponentEnabledSetting(componentName)
+                    mPackageManager.getComponentEnabledSetting(componentName)
                     == PackageManager.COMPONENT_ENABLED_STATE_ENABLED, fromTooltip);
         } catch (Exception ex) {
             Log.e(TAG,
@@ -466,17 +465,11 @@
     }
 
     private boolean shouldShowUI(int flags) {
-        // if status bar isn't null, check if phone is in AOD, else check flags
-        // since we could be using a different status bar
-        return mStatusBarOptionalLazy.map(statusBarLazy -> {
-            StatusBar statusBar = statusBarLazy.get();
-            return statusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-                    && statusBar.getWakefulnessState()
-                    != WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP
-                    && statusBar.isDeviceInteractive() && (flags & AudioManager.FLAG_SHOW_UI) != 0
-                    && mShowVolumeDialog;
-        }).orElse(
-                mShowVolumeDialog && (flags & AudioManager.FLAG_SHOW_UI) != 0);
+        int wakefulness = mWakefulnessLifecycle.getWakefulness();
+        return wakefulness != WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+                && wakefulness != WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP
+                && mDeviceInteractive && (flags & AudioManager.FLAG_SHOW_UI) != 0
+                && mShowVolumeDialog;
     }
 
     boolean onVolumeChangedW(int stream, int flags) {
@@ -600,15 +593,15 @@
     private boolean updateEffectsSuppressorW(ComponentName effectsSuppressor) {
         if (Objects.equals(mState.effectsSuppressor, effectsSuppressor)) return false;
         mState.effectsSuppressor = effectsSuppressor;
-        mState.effectsSuppressorName = getApplicationName(mContext, mState.effectsSuppressor);
+        mState.effectsSuppressorName =
+                getApplicationName(mPackageManager, mState.effectsSuppressor);
         Events.writeEvent(Events.EVENT_SUPPRESSOR_CHANGED, mState.effectsSuppressor,
                 mState.effectsSuppressorName);
         return true;
     }
 
-    private static String getApplicationName(Context context, ComponentName component) {
+    private static String getApplicationName(PackageManager pm, ComponentName component) {
         if (component == null) return null;
-        final PackageManager pm = context.getPackageManager();
         final String pkg = component.getPackageName();
         try {
             final ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
@@ -630,8 +623,7 @@
     }
 
     private boolean updateZenConfig() {
-        final NotificationManager.Policy policy =
-                mNotificationManager.getConsolidatedNotificationPolicy();
+        final NotificationManager.Policy policy = mNoMan.getConsolidatedNotificationPolicy();
         boolean disallowAlarms = (policy.priorityCategories & NotificationManager.Policy
                 .PRIORITY_CATEGORY_ALARMS) == 0;
         boolean disallowMedia = (policy.priorityCategories & NotificationManager.Policy
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeThreadFactory.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeThreadFactory.java
index 570e1d8..301a157 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeThreadFactory.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeThreadFactory.java
@@ -27,6 +27,7 @@
 public class FakeThreadFactory implements ThreadFactory {
     private final FakeExecutor mFakeExecutor;
     private Handler mHandler;
+    private Looper mLooper;
 
     public FakeThreadFactory(FakeExecutor fakeExecutor) {
         mFakeExecutor = fakeExecutor;
@@ -36,8 +37,17 @@
         mHandler = handler;
     }
 
+    public void setLooper(Looper looper) {
+        mLooper = looper;
+    }
+
     @Override
-    public Handler builderHandlerOnNewThread(String threadName) {
+    public Looper buildLooperOnNewThread(String threadName) {
+        return mLooper;
+    }
+
+    @Override
+    public Handler buildHandlerOnNewThread(String threadName) {
         return mHandler;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
index 6166cd7..5c0efd3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
@@ -23,29 +23,37 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.media.AudioManager;
+import android.media.IAudioService;
 import android.media.session.MediaSession;
 import android.os.Handler;
 import android.os.Process;
+import android.os.Vibrator;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.RingerModeLiveData;
 import com.android.systemui.util.RingerModeTracker;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.concurrency.FakeThreadFactory;
+import com.android.systemui.util.concurrency.ThreadFactory;
+import com.android.systemui.util.time.FakeSystemClock;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -58,7 +66,6 @@
 
     TestableVolumeDialogControllerImpl mVolumeController;
     VolumeDialogControllerImpl.C mCallback;
-    StatusBar mStatusBar;
     @Mock
     private BroadcastDispatcher mBroadcastDispatcher;
     @Mock
@@ -67,6 +74,23 @@
     private RingerModeLiveData mRingerModeLiveData;
     @Mock
     private RingerModeLiveData mRingerModeInternalLiveData;
+    private final FakeThreadFactory mThreadFactory = new FakeThreadFactory(
+            new FakeExecutor(new FakeSystemClock()));
+    @Mock
+    private AudioManager mAudioManager;
+    @Mock
+    private NotificationManager mNotificationManager;
+    @Mock
+    private Vibrator mVibrator;
+    @Mock
+    private IAudioService mIAudioService;
+    @Mock
+    private AccessibilityManager mAccessibilityManager;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private WakefulnessLifecycle mWakefullnessLifcycle;
+
 
     @Before
     public void setup() throws Exception {
@@ -77,19 +101,15 @@
         // Initial non-set value
         when(mRingerModeLiveData.getValue()).thenReturn(-1);
         when(mRingerModeInternalLiveData.getValue()).thenReturn(-1);
-
         mCallback = mock(VolumeDialogControllerImpl.C.class);
-        mStatusBar = mock(StatusBar.class);
-        mVolumeController = new TestableVolumeDialogControllerImpl(mContext, mCallback, mStatusBar,
-                mBroadcastDispatcher, mRingerModeTracker);
+        mThreadFactory.setLooper(TestableLooper.get(this).getLooper());
+        mVolumeController = new TestableVolumeDialogControllerImpl(mContext,
+                mBroadcastDispatcher, mRingerModeTracker, mThreadFactory, mAudioManager,
+                mNotificationManager, Optional.of(mVibrator), mIAudioService, mAccessibilityManager,
+                mPackageManager, mWakefullnessLifcycle, mCallback);
         mVolumeController.setEnableDialogs(true, true);
     }
 
-    @After
-    public void tearDown() {
-        mVolumeController.destroy();
-    }
-
     @Test
     public void testRegisteredWithDispatcher() {
         verify(mBroadcastDispatcher).registerReceiverWithHandler(any(BroadcastReceiver.class),
@@ -99,45 +119,36 @@
 
     @Test
     public void testVolumeChangeW_deviceNotInteractiveAOD() {
-        when(mStatusBar.isDeviceInteractive()).thenReturn(false);
-        when(mStatusBar.getWakefulnessState()).thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
+        mVolumeController.setDeviceInteractive(false);
+        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
+                WakefulnessLifecycle.WAKEFULNESS_AWAKE);
         mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
         verify(mCallback, never()).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
     }
 
     @Test
     public void testVolumeChangeW_deviceInteractive() {
-        when(mStatusBar.isDeviceInteractive()).thenReturn(true);
-        when(mStatusBar.getWakefulnessState()).thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
+        mVolumeController.setDeviceInteractive(true);
+        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
+                WakefulnessLifecycle.WAKEFULNESS_AWAKE);
         mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
         verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
     }
 
     @Test
     public void testVolumeChangeW_deviceInteractive_StartedSleeping() {
-        when(mStatusBar.isDeviceInteractive()).thenReturn(true);
-        when(mStatusBar.getWakefulnessState()).thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
+        mVolumeController.setDeviceInteractive(true);
+        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
+                WakefulnessLifecycle.WAKEFULNESS_AWAKE);
         mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
-        when(mStatusBar.isDeviceInteractive()).thenReturn(false);
-        when(mStatusBar.getWakefulnessState()).thenReturn(
+        mVolumeController.setDeviceInteractive(false);
+        when(mWakefullnessLifcycle.getWakefulness()).thenReturn(
                 WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
         mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
         verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
     }
 
     @Test
-    public void testVolumeChangeW_nullStatusBar() {
-        VolumeDialogControllerImpl.C callback = mock(VolumeDialogControllerImpl.C.class);
-        TestableVolumeDialogControllerImpl
-                nullStatusBarTestableDialog =
-                new TestableVolumeDialogControllerImpl(
-                        mContext, callback, null, mBroadcastDispatcher, mRingerModeTracker);
-        nullStatusBarTestableDialog.setEnableDialogs(true, true);
-        nullStatusBarTestableDialog.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
-        verify(callback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
-    }
-
-    @Test
     public void testOnRemoteVolumeChanged_newStream_noNullPointer() {
         MediaSession.Token token = new MediaSession.Token(Process.myUid(), null);
         mVolumeController.mMediaSessionsCallbacksW.onRemoteVolumeChanged(token, 0);
@@ -155,22 +166,51 @@
         verify(mRingerModeInternalLiveData).observeForever(any());
     }
 
-    @Test
-    public void testRingerModeOnDestroy_observersRemoved() {
-        mVolumeController.destroy();
-
-        verify(mRingerModeLiveData).removeObserver(any());
-        verify(mRingerModeInternalLiveData).removeObserver(any());
-    }
-
     static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl {
-        TestableVolumeDialogControllerImpl(Context context, C callback, StatusBar s,
-                BroadcastDispatcher broadcastDispatcher, RingerModeTracker ringerModeTracker) {
-            super(
-                    context, broadcastDispatcher,
-                    s == null ? Optional.empty() : Optional.of(() -> s), ringerModeTracker);
+        private final WakefulnessLifecycle.Observer mWakefullessLifecycleObserver;
+
+        TestableVolumeDialogControllerImpl(
+                Context context,
+                BroadcastDispatcher broadcastDispatcher,
+                RingerModeTracker ringerModeTracker,
+                ThreadFactory theadFactory,
+                AudioManager audioManager,
+                NotificationManager notificationManager,
+                Optional<Vibrator> optionalVibrator,
+                IAudioService iAudioService,
+                AccessibilityManager accessibilityManager,
+                PackageManager packageManager,
+                WakefulnessLifecycle wakefulnessLifecycle,
+                C callback) {
+            super(context, broadcastDispatcher, ringerModeTracker, theadFactory, audioManager,
+                    notificationManager, optionalVibrator, iAudioService, accessibilityManager,
+                    packageManager, wakefulnessLifecycle);
             mCallbacks = callback;
+
+            ArgumentCaptor<WakefulnessLifecycle.Observer> observerCaptor =
+                    ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
+            verify(wakefulnessLifecycle).addObserver(observerCaptor.capture());
+            mWakefullessLifecycleObserver = observerCaptor.getValue();
+        }
+
+        public void setDeviceInteractive(boolean interactive) {
+            if (interactive) {
+                mWakefullessLifecycleObserver.onStartedWakingUp();
+            } else {
+                mWakefullessLifecycleObserver.onFinishedGoingToSleep();
+            }
         }
     }
 
+//    static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl {
+//        TestableVolumeDialogControllerImpl(Context context, C callback,
+//                BroadcastDispatcher broadcastDispatcher, RingerModeTracker ringerModeTracker,
+//                ThreadFactory threadFactory) {
+//            super(
+//                    context, broadcastDispatcher,
+//                    s == null ? Optional.empty() : Optional.of(() -> s), ringerModeTracker);
+//            mCallbacks = callback;
+//        }
+//    }
+
 }