From 421a9410b462770544c6ae9a554542fa2fe1acb1 Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Mon, 6 Feb 2017 09:15:21 -0800 Subject: [PATCH] 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 --- packages/SystemUI/plugin/Android.mk | 10 +++++ .../SampleOverlayPlugin.java | 37 ++++++++++++++++ .../systemui/plugins/OverlayPlugin.java | 10 +++++ .../src/com/android/systemui/Dependency.java | 4 ++ .../android/systemui/SystemUIApplication.java | 43 +++++++++++++------ .../keyguard/KeyguardViewMediator.java | 4 +- .../statusbar/RemoteInputController.java | 5 ++- .../phone/FingerprintUnlockController.java | 4 +- .../systemui/statusbar/phone/StatusBar.java | 12 ++---- .../phone/StatusBarKeyguardViewManager.java | 7 +-- .../phone/StatusBarWindowManager.java | 27 +++++++++++- 11 files changed, 133 insertions(+), 30 deletions(-) diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk index 86527db878c63..05ee6b23c4b72 100644 --- a/packages/SystemUI/plugin/Android.mk +++ b/packages/SystemUI/plugin/Android.mk @@ -27,3 +27,13 @@ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_JAR_EXCLUDE_FILES := none include $(BUILD_STATIC_JAVA_LIBRARY) + +include $(CLEAR_VARS) + +# Dummy to generate .toc files. +LOCAL_PACKAGE_NAME := PluginDummyLib +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_JAVA_LIBRARIES := SystemUIPluginLib + +include $(BUILD_PACKAGE) diff --git a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java index a2f84dc7af2a4..13fc76c5da495 100644 --- a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java +++ b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java @@ -15,11 +15,14 @@ package com.android.systemui.plugin.testoverlayplugin; import android.content.Context; +import android.graphics.Rect; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver.InternalInsetsInfo; +import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import com.android.systemui.plugins.OverlayPlugin; public class SampleOverlayPlugin implements OverlayPlugin { @@ -28,6 +31,9 @@ public class SampleOverlayPlugin implements OverlayPlugin { private View mStatusBarView; private View mNavBarView; + private boolean mInputSetup; + private boolean mCollapseDesired; + private float mStatusBarHeight; @Override public int getVersion() { @@ -43,6 +49,10 @@ public class SampleOverlayPlugin implements OverlayPlugin { @Override public void onDestroy() { + if (mInputSetup) { + mStatusBarView.getViewTreeObserver().removeOnComputeInternalInsetsListener( + onComputeInternalInsetsListener); + } Log.d(TAG, "onDestroy"); if (mStatusBarView != null) { mStatusBarView.post( @@ -57,6 +67,9 @@ public class SampleOverlayPlugin implements OverlayPlugin { public void setup(View statusBar, View navBar) { Log.d(TAG, "Setup"); + int id = mPluginContext.getResources().getIdentifier("status_bar_height", "dimen", + "android"); + mStatusBarHeight = mPluginContext.getResources().getDimension(id); if (statusBar instanceof ViewGroup) { mStatusBarView = LayoutInflater.from(mPluginContext) .inflate(R.layout.colored_overlay, (ViewGroup) statusBar, false); @@ -68,4 +81,28 @@ public class SampleOverlayPlugin implements OverlayPlugin { ((ViewGroup) navBar).addView(mNavBarView); } } + + @Override + public void setCollapseDesired(boolean collapseDesired) { + mCollapseDesired = collapseDesired; + } + + @Override + public boolean holdStatusBarOpen() { + if (!mInputSetup) { + mInputSetup = true; + mStatusBarView.getViewTreeObserver().addOnComputeInternalInsetsListener( + onComputeInternalInsetsListener); + } + return true; + } + + final OnComputeInternalInsetsListener onComputeInternalInsetsListener = inoutInfo -> { + inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); + if (mCollapseDesired) { + inoutInfo.touchableRegion.set(new Rect(0, 0, 50000, (int) mStatusBarHeight)); + } else { + inoutInfo.touchableRegion.set(new Rect(0, 0, 50000, 50000)); + } + }; } diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java index 91a260435eaa9..f5074f75b7a49 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java @@ -21,4 +21,14 @@ public interface OverlayPlugin extends Plugin { int VERSION = 1; void setup(View statusBar, View navBar); + + default boolean holdStatusBarOpen() { + return false; + } + + /** + * Only called if the plugin has returned true to holdStatusBarOpen(). + */ + default void setCollapseDesired(boolean collapseDesired) { + } } diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index e1f3176d808e6..7066a1b7ca255 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.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.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 @@ public class Dependency extends SystemUI { 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 27070edc73e59..e5bda7edfc589 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.content.res.Configuration; 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.shortcut.ShortcutKeyDispatcher; 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 @@ public class SystemUIApplication extends Application implements SysUiServiceProv * 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. - * *

This method must only be called from the main thread.

*/ public void startServicesIfNeeded() { @@ -160,7 +161,6 @@ public class SystemUIApplication extends Application implements SysUiServiceProv * 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. - * *

This method must only be called from the main thread.

*/ void startSecondaryUserServicesIfNeeded() { @@ -184,7 +184,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); final int N = services.length; - for (int i=0; i cl = services[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); try { @@ -207,15 +207,34 @@ public class SystemUIApplication extends Application implements SysUiServiceProv } Dependency.get(PluginManager.class).addPluginListener(OverlayPlugin.ACTION, new PluginListener() { - @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 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 99c8c6bacc62f..cbe822f2205dc 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 class KeyguardViewMediator extends SystemUI { } 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 66cc15d7cc8f5..7f28c4c2e7a43 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 @@ public class RemoteInputController { private final ArrayList 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 0773108b3d600..2bb3cbc31cebb 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.KeyguardConstants; 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 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { private int mPendingAuthenticatedUserId = -1; public FingerprintUnlockController(Context context, - StatusBarWindowManager statusBarWindowManager, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, @@ -111,7 +111,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { 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 54c67d22e8617..ea0918cd37fb7 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 @@ public class StatusBar extends SystemUI implements DemoMode, 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 @@ public class StatusBar extends SystemUI implements DemoMode, 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 @@ public class StatusBar extends SystemUI implements DemoMode, 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 8d5d890b07adf..2a69c1e663bbc 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.KeyguardUpdateMonitor; 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 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private static String TAG = "StatusBarKeyguardViewManager"; protected final Context mContext; + private final StatusBarWindowManager mStatusBarWindowManager; protected LockPatternUtils mLockPatternUtils; protected ViewMediatorCallback mViewMediatorCallback; @@ -75,7 +77,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private FingerprintUnlockController mFingerprintUnlockController; private ViewGroup mContainer; - private StatusBarWindowManager mStatusBarWindowManager; private boolean mDeviceInteractive = false; private boolean mScreenTurnedOn; @@ -101,16 +102,16 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb 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 16999b2f454f9..deb0070ccbc01 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.ViewGroup; 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 @@ import java.lang.reflect.Field; /** * 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 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { 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 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { 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 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { 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 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { int statusBarState; boolean remoteInputActive; + boolean forcePluginOpen; private boolean isKeyguardShowingAndNotOccluded() { return keyguardShowing && !keyguardOccluded; @@ -419,4 +435,13 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { 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); + } }