Notify SystemUI when ActivityDisplay is ready
Bug: 120748674
Test: atest ActivityManagerMultiDisplayTests#testNavBarNotShowingOnDisplayWithoutDecor * 100
Test: atest ActivityManagerMultiDisplayTests#testNavBarShowingOnDisplayWithDecor * 100
Test: atest ActivityManagerMultiDisplayTests#testNavBarNotShowingOnPrivateDisplay * 100
Test: atest SystemUITests
Change-Id: I302a35b9b860ab881b60c6407edabb2da16b75f8
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 6a28059..943c726 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -160,4 +160,9 @@
void onBiometricError(String error);
// Used to hide the biometric dialog when the AuthenticationClient is stopped
void hideBiometricDialog();
+
+ /**
+ * Notifies System UI that the display is ready to show system decorations.
+ */
+ void onDisplayReady(int displayId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 904478e..0150852 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -111,6 +111,7 @@
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
+ private static final int MSG_DISPLAY_READY = 47 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -274,6 +275,11 @@
default void onBiometricHelp(String message) { }
default void onBiometricError(String error) { }
default void hideBiometricDialog() { }
+
+ /**
+ * @see IStatusBar#onDisplayReady(int)
+ */
+ default void onDisplayReady(int displayId) { }
}
@VisibleForTesting
@@ -761,6 +767,13 @@
}
}
+ @Override
+ public void onDisplayReady(int displayId) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_DISPLAY_READY, displayId, 0).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -1015,6 +1028,11 @@
mCallbacks.get(i).showPinningEscapeToast();
}
break;
+ case MSG_DISPLAY_READY:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onDisplayReady(msg.arg1);
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 9740d1d..e11ec2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -19,6 +19,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+import static com.android.systemui.SysUiServiceProvider.getComponent;
import android.content.Context;
import android.hardware.display.DisplayManager;
@@ -34,6 +35,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -48,7 +50,7 @@
/** A controller to handle navigation bars. */
@Singleton
-public class NavigationBarController implements DisplayListener {
+public class NavigationBarController implements DisplayListener, Callbacks {
private static final String TAG = NavigationBarController.class.getName();
@@ -65,13 +67,11 @@
mHandler = handler;
mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(this, mHandler);
+ getComponent(mContext, CommandQueue.class).addCallback(this);
}
@Override
- public void onDisplayAdded(int displayId) {
- Display display = mDisplayManager.getDisplay(displayId);
- createNavigationBar(display);
- }
+ public void onDisplayAdded(int displayId) { }
@Override
public void onDisplayRemoved(int displayId) {
@@ -79,7 +79,12 @@
}
@Override
- public void onDisplayChanged(int displayId) {
+ public void onDisplayChanged(int displayId) { }
+
+ @Override
+ public void onDisplayReady(int displayId) {
+ Display display = mDisplayManager.getDisplay(displayId);
+ createNavigationBar(display);
}
// TODO(b/117478341): I use {@code includeDefaultDisplay} to make this method compatible to
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
index 73f3b43..6177344 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
@@ -51,6 +51,7 @@
@Before
public void setup() {
+ mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
final Display display = createVirtualDisplay();
final SysuiTestableContext context =
(SysuiTestableContext) mContext.createDisplayContext(display);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index a66f0ca..b9b5aae 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -100,4 +100,11 @@
* @param rotation rotation suggestion
*/
void onProposedRotationChanged(int rotation, boolean isValid);
+
+ /**
+ * Notifies System UI that the display is ready to show system decorations.
+ *
+ * @param displayId display ID
+ */
+ void onDisplayReady(int displayId);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8d2bab4..7e87c29 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -443,6 +443,15 @@
} catch (RemoteException ex) {}
}
}
+
+ @Override
+ public void onDisplayReady(int displayId) {
+ if (mBar != null) {
+ try {
+ mBar.onDisplayReady(displayId);
+ } catch (RemoteException ex) { }
+ }
+ }
};
private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4006332..bbf115f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2574,6 +2574,10 @@
}
}
+ void notifyDisplayReady() {
+ mHandler.post(() -> getStatusBarManagerInternal().onDisplayReady(getDisplayId()));
+ }
+
/**
* Return the display width available after excluding any screen
* decorations that could never be removed in Honeycomb. That is, system bar or
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index c4a853d..e95ac5c 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1296,16 +1296,21 @@
public void onDisplayAdded(int displayId) {
if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
synchronized (mService.mGlobalLock) {
- getActivityDisplayOrCreate(displayId);
+ final ActivityDisplay display = getActivityDisplayOrCreate(displayId);
// Do not start home before booting, or it may accidentally finish booting before it
// starts. Instead, we expect home activities to be launched when the system is ready
// (ActivityManagerService#systemReady).
if (mService.isBooted() || mService.isBooting()) {
- startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
+ startSystemDecorations(display.mDisplayContent);
}
}
}
+ private void startSystemDecorations(final DisplayContent displayContent) {
+ startHomeOnDisplay(mCurrentUser, "displayAdded", displayContent.getDisplayId());
+ displayContent.getDisplayPolicy().notifyDisplayReady();
+ }
+
@Override
public void onDisplayRemoved(int displayId) {
if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);