SysUI: Add method for plugins to keep status bar full screen

Lots of things detect overlays these days (installing apps) and the
only way to avoid the problems associated with this is to live in
the status bar window. So allow plugins to hold the window open
when they want to so they can have overlays be in that.

Move StatusBarWindowManager to Dependency to make things easier
as well.

Test: Install the example plugin, test can access QS and interact
      with apps

Change-Id: Ib2288bf56704960847217bad01a480ab407e0ffe
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index e1f3176..7066a1b 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -27,6 +27,7 @@
 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.phone.StatusBarWindowManager;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BatteryControllerImpl;
@@ -183,6 +184,9 @@
         mProviders.put(TunerService.class.getName(), () ->
                 new TunerService(mContext));
 
+        mProviders.put(StatusBarWindowManager.class.getName(), () ->
+                new StatusBarWindowManager(mContext));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 27070ed..e5bda7e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -27,6 +27,7 @@
 import android.os.Process;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.systemui.fragments.FragmentService;
@@ -43,6 +44,7 @@
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.usb.StorageNotification;
 import com.android.systemui.util.NotificationChannels;
@@ -149,7 +151,6 @@
      * Makes sure that all the SystemUI services are running. If they are already running, this is a
      * no-op. This is needed to conditinally start all the services, as we only need to have it in
      * the main process.
-     *
      * <p>This method must only be called from the main thread.</p>
      */
     public void startServicesIfNeeded() {
@@ -160,7 +161,6 @@
      * Ensures that all the Secondary user SystemUI services are running. If they are already
      * running, this is a no-op. This is needed to conditinally start all the services, as we only
      * need to have it in the main process.
-     *
      * <p>This method must only be called from the main thread.</p>
      */
     void startSecondaryUserServicesIfNeeded() {
@@ -184,7 +184,7 @@
         Log.v(TAG, "Starting SystemUI services for user " +
                 Process.myUserHandle().getIdentifier() + ".");
         final int N = services.length;
-        for (int i=0; i<N; i++) {
+        for (int i = 0; i < N; i++) {
             Class<?> cl = services[i];
             if (DEBUG) Log.d(TAG, "loading: " + cl);
             try {
@@ -207,15 +207,34 @@
         }
         Dependency.get(PluginManager.class).addPluginListener(OverlayPlugin.ACTION,
                 new PluginListener<OverlayPlugin>() {
-            @Override
-            public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
-                StatusBar statusBar = getComponent(StatusBar.class);
-                if (statusBar != null) {
-                    plugin.setup(statusBar.getStatusBarWindow(),
-                            statusBar.getNavigationBarView());
-                }
-            }
-        }, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
+                    private ArraySet<OverlayPlugin> mOverlays;
+
+                    @Override
+                    public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
+                        StatusBar statusBar = getComponent(StatusBar.class);
+                        if (statusBar != null) {
+                            plugin.setup(statusBar.getStatusBarWindow(),
+                                    statusBar.getNavigationBarView());
+                        }
+                        // Lazy init.
+                        if (mOverlays == null) mOverlays = new ArraySet<>();
+                        if (plugin.holdStatusBarOpen()) {
+                            mOverlays.add(plugin);
+                            Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
+                                    mOverlays.forEach(o -> o.setCollapseDesired(b)));
+                            Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+                                    mOverlays.size() != 0);
+
+                        }
+                    }
+
+                    @Override
+                    public void onPluginDisconnected(OverlayPlugin plugin) {
+                        mOverlays.remove(plugin);
+                        Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+                                mOverlays.size() != 0);
+                    }
+                }, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
 
         mServicesStarted = true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 99c8c6b..cbe822f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1956,11 +1956,11 @@
     }
 
     public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
-            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
+            ViewGroup container,
             ScrimController scrimController,
             FingerprintUnlockController fingerprintUnlockController) {
         mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container,
-                statusBarWindowManager, scrimController, fingerprintUnlockController,
+                scrimController, fingerprintUnlockController,
                 mDismissCallbackRegistry);
         return mStatusBarKeyguardViewManager;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 66cc15d..7f28c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import com.android.internal.util.Preconditions;
+import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.phone.StatusBarWindowManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -39,8 +40,8 @@
     private final ArrayList<Callback> mCallbacks = new ArrayList<>(3);
     private final HeadsUpManager mHeadsUpManager;
 
-    public RemoteInputController(StatusBarWindowManager sbwm, HeadsUpManager headsUpManager) {
-        addCallback(sbwm);
+    public RemoteInputController(HeadsUpManager headsUpManager) {
+        addCallback(Dependency.get(StatusBarWindowManager.class));
         mHeadsUpManager = headsUpManager;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 0773108..2bb3cbc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -27,6 +27,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.LatencyTracker;
+import com.android.systemui.Dependency;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 
 /**
@@ -101,7 +102,6 @@
     private int mPendingAuthenticatedUserId = -1;
 
     public FingerprintUnlockController(Context context,
-            StatusBarWindowManager statusBarWindowManager,
             DozeScrimController dozeScrimController,
             KeyguardViewMediator keyguardViewMediator,
             ScrimController scrimController,
@@ -111,7 +111,7 @@
         mPowerManager = context.getSystemService(PowerManager.class);
         mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
         mUpdateMonitor.registerCallback(this);
-        mStatusBarWindowManager = statusBarWindowManager;
+        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
         mDozeScrimController = dozeScrimController;
         mKeyguardViewMediator = keyguardViewMediator;
         mScrimController = scrimController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 54c67d2..ea0918c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1431,10 +1431,10 @@
         Trace.beginSection("StatusBar#startKeyguard");
         KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mFingerprintUnlockController = new FingerprintUnlockController(mContext,
-                mStatusBarWindowManager, mDozeScrimController, keyguardViewMediator,
+                mDozeScrimController, keyguardViewMediator,
                 mScrimController, this, UnlockMethodCache.getInstance(mContext));
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
-                getBouncerContainer(), mStatusBarWindowManager, mScrimController,
+                getBouncerContainer(), mScrimController,
                 mFingerprintUnlockController);
         mKeyguardIndicationController.setStatusBarKeyguardViewManager(
                 mStatusBarKeyguardViewManager);
@@ -3381,9 +3381,6 @@
             pw.print("  status bar gestures: ");
             mGestureRec.dump(fd, pw, args);
         }
-        if (mStatusBarWindowManager != null) {
-            mStatusBarWindowManager.dump(fd, pw, args);
-        }
 
         if (mHeadsUpManager != null) {
             mHeadsUpManager.dump(fd, pw, args);
@@ -3422,9 +3419,8 @@
 
     private void addStatusBarWindow() {
         makeStatusBarView();
-        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
-        mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,
-                mHeadsUpManager);
+        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mRemoteInputController = new RemoteInputController(mHeadsUpManager);
         mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 8d5d890..2a69c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -32,6 +32,7 @@
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DejankUtils;
 import com.android.keyguard.LatencyTracker;
+import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.statusbar.CommandQueue;
@@ -67,6 +68,7 @@
     private static String TAG = "StatusBarKeyguardViewManager";
 
     protected final Context mContext;
+    private final StatusBarWindowManager mStatusBarWindowManager;
 
     protected LockPatternUtils mLockPatternUtils;
     protected ViewMediatorCallback mViewMediatorCallback;
@@ -75,7 +77,6 @@
     private FingerprintUnlockController mFingerprintUnlockController;
 
     private ViewGroup mContainer;
-    private StatusBarWindowManager mStatusBarWindowManager;
 
     private boolean mDeviceInteractive = false;
     private boolean mScreenTurnedOn;
@@ -101,16 +102,16 @@
         mContext = context;
         mViewMediatorCallback = callback;
         mLockPatternUtils = lockPatternUtils;
+        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
     }
 
     public void registerStatusBar(StatusBar statusBar,
-            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
+            ViewGroup container,
             ScrimController scrimController,
             FingerprintUnlockController fingerprintUnlockController,
             DismissCallbackRegistry dismissCallbackRegistry) {
         mStatusBar = statusBar;
         mContainer = container;
-        mStatusBarWindowManager = statusBarWindowManager;
         mScrimController = scrimController;
         mFingerprintUnlockController = fingerprintUnlockController;
         mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 16999b2..deb0070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -32,6 +32,7 @@
 import android.view.WindowManager;
 
 import com.android.keyguard.R;
+import com.android.systemui.Dumpable;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
@@ -43,7 +44,7 @@
 /**
  * Encapsulates all logic for the status bar window state management.
  */
-public class StatusBarWindowManager implements RemoteInputController.Callback {
+public class StatusBarWindowManager implements RemoteInputController.Callback, Dumpable {
 
     private static final String TAG = "StatusBarWindowManager";
 
@@ -59,6 +60,7 @@
     private final boolean mKeyguardScreenRotation;
     private final float mScreenBrightnessDoze;
     private final State mCurrentState = new State();
+    private OtherwisedCollapsedListener mListener;
 
     public StatusBarWindowManager(Context context) {
         mContext = context;
@@ -154,6 +156,10 @@
 
     private void applyHeight(State state) {
         boolean expanded = isExpanded(state);
+        if (state.forcePluginOpen) {
+            mListener.setWouldOtherwiseCollapse(expanded);
+            expanded = true;
+        }
         if (expanded) {
             mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
         } else {
@@ -356,6 +362,15 @@
         apply(mCurrentState);
     }
 
+    public void setForcePluginOpen(boolean forcePluginOpen) {
+        mCurrentState.forcePluginOpen = forcePluginOpen;
+        apply(mCurrentState);
+    }
+
+    public void setStateListener(OtherwisedCollapsedListener listener) {
+        mListener = listener;
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("StatusBarWindowManager state:");
         pw.println(mCurrentState);
@@ -388,6 +403,7 @@
         int statusBarState;
 
         boolean remoteInputActive;
+        boolean forcePluginOpen;
 
         private boolean isKeyguardShowingAndNotOccluded() {
             return keyguardShowing && !keyguardOccluded;
@@ -419,4 +435,13 @@
             return result.toString();
         }
     }
+
+    /**
+     * Custom listener to pipe data back to plugins about whether or not the status bar would be
+     * collapsed if not for the plugin.
+     * TODO: Find cleaner way to do this.
+     */
+    public interface OtherwisedCollapsedListener {
+        void setWouldOtherwiseCollapse(boolean otherwiseCollapse);
+    }
 }