diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index a32632736ee8f..dc53c22e8ceaa 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -1684,4 +1684,16 @@ public interface WindowManagerPolicy { public void onConfigurationChanged(); public boolean shouldRotateSeamlessly(int oldRotation, int newRotation); + + /** + * Called when System UI has been started. + */ + void onSystemUiStarted(); + + /** + * Checks whether the policy is ready for dismissing the boot animation and completing the boot. + * + * @return true if ready; false otherwise. + */ + boolean canDismissBootAnimation(); } diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java index 10b26092f3876..72ff6068cd686 100644 --- a/services/core/java/com/android/server/SystemServiceManager.java +++ b/services/core/java/com/android/server/SystemServiceManager.java @@ -164,6 +164,13 @@ public class SystemServiceManager { } } + /** + * @return true if system has completed the boot; false otherwise. + */ + public boolean isBootCompleted() { + return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED; + } + public void startUser(final int userHandle) { Slog.i(TAG, "Calling onStartUser u" + userHandle); final int serviceLen = mServices.size(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 78727c0562881..ae9852eb34a54 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -234,6 +234,7 @@ import com.android.internal.util.ScreenShapeHelper; import com.android.internal.widget.PointerLocationView; import com.android.server.GestureLauncherService; import com.android.server.LocalServices; +import com.android.server.SystemServiceManager; import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; @@ -476,6 +477,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mBootMessageNeedsHiding; KeyguardServiceDelegate mKeyguardDelegate; + private boolean mKeyguardBound; final Runnable mWindowManagerDrawCallback = new Runnable() { @Override public void run() { @@ -530,7 +532,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mSystemReady; boolean mSystemBooted; - private boolean mDeferBindKeyguard; boolean mHdmiPlugged; HdmiControl mHdmiControl; IUiModeManager mUiModeManager; @@ -2087,6 +2088,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { handleStartTransitionForKeyguardLw(transit, null /* transit */); } }); + mKeyguardDelegate = new KeyguardServiceDelegate(mContext, + new StateCallback() { + @Override + public void onTrustedChanged() { + mWindowManagerFuncs.notifyKeyguardTrustedChanged(); + } + }); } /** @@ -6631,6 +6639,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { reportScreenStateToVrManager(false); } + private long getKeyguardDrawnTimeout() { + final boolean bootCompleted = + LocalServices.getService(SystemServiceManager.class).isBootCompleted(); + // Set longer timeout if it has not booted yet to prevent showing empty window. + return bootCompleted ? 1000 : 5000; + } + // Called on the DisplayManager's DisplayPowerController thread. @Override public void screenTurningOn(final ScreenOnListener screenOnListener) { @@ -6646,7 +6661,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mKeyguardDelegate != null) { mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); - mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); + mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, + getKeyguardDrawnTimeout()); mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); } else { if (DEBUG_WAKEUP) Slog.d(TAG, @@ -7159,16 +7175,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { return out; } + private void bindKeyguard() { + synchronized (mLock) { + if (mKeyguardBound) { + return; + } + mKeyguardBound = true; + } + mKeyguardDelegate.bindService(mContext); + } + + @Override + public void onSystemUiStarted() { + bindKeyguard(); + } + /** {@inheritDoc} */ @Override public void systemReady() { - mKeyguardDelegate = new KeyguardServiceDelegate(mContext, - new StateCallback() { - @Override - public void onTrustedChanged() { - mWindowManagerFuncs.notifyKeyguardTrustedChanged(); - } - }); + // In normal flow, systemReady is called before other system services are ready. + // So it is better not to bind keyguard here. mKeyguardDelegate.onSystemReady(); mVrManagerInternal = LocalServices.getService(VrManagerInternal.class); @@ -7178,7 +7204,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { readCameraLensCoverState(); updateUiMode(); - boolean bindKeyguardNow; synchronized (mLock) { updateOrientationListenerLp(); mSystemReady = true; @@ -7188,18 +7213,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateSettings(); } }); - - bindKeyguardNow = mDeferBindKeyguard; - if (bindKeyguardNow) { - // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. - mDeferBindKeyguard = false; + // If this happens, for whatever reason, systemReady came later than systemBooted. + // And keyguard should be already bound from systemBooted + if (mSystemBooted) { + mKeyguardDelegate.onBootCompleted(); } } - if (bindKeyguardNow) { - mKeyguardDelegate.bindService(mContext); - mKeyguardDelegate.onBootCompleted(); - } mSystemGestures.systemReady(); mImmersiveModeConfirmation.systemReady(); } @@ -7207,30 +7227,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public void systemBooted() { - boolean bindKeyguardNow = false; - synchronized (mLock) { - // Time to bind Keyguard; take care to only bind it once, either here if ready or - // in systemReady if not. - if (mKeyguardDelegate != null) { - bindKeyguardNow = true; - } else { - // Because mKeyguardDelegate is null, we know that the synchronized block in - // systemReady didn't run yet and setting this will actually have an effect. - mDeferBindKeyguard = true; - } - } - if (bindKeyguardNow) { - mKeyguardDelegate.bindService(mContext); - mKeyguardDelegate.onBootCompleted(); - } + bindKeyguard(); synchronized (mLock) { mSystemBooted = true; + if (mSystemReady) { + mKeyguardDelegate.onBootCompleted(); + } } startedWakingUp(); screenTurningOn(null); screenTurnedOn(); } + @Override + public boolean canDismissBootAnimation() { + synchronized (mLock) { + return mKeyguardDrawComplete; + } + } + ProgressDialog mBootMsgDialog = null; /** {@inheritDoc} */ diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a2ae430bacecc..a15891bc64140 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3341,6 +3341,13 @@ public class WindowManagerService extends IWindowManager.Stub performEnableScreen(); } + /** + * Called when System UI has been started. + */ + public void onSystemUiStarted() { + mPolicy.onSystemUiStarted(); + } + private void performEnableScreen() { synchronized(mWindowMap) { if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled @@ -3356,6 +3363,10 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) { + return; + } + // Don't enable the screen until all existing windows have been drawn. if (!mForceDisplayEnabled // TODO(multidisplay): Expand to all displays? @@ -3369,7 +3380,7 @@ public class WindowManagerService extends IWindowManager.Stub try { IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); if (surfaceFlinger != null) { - //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); + Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); Parcel data = Parcel.obtain(); data.writeInterfaceToken("android.ui.ISurfaceComposer"); surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 09d1d9a6eeaec..db7b843fdafdb 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1653,6 +1653,7 @@ public final class SystemServer { final MediaRouterService mediaRouterF = mediaRouter; final MmsServiceBroker mmsServiceF = mmsService; final IpSecService ipSecServiceF = ipSecService; + final WindowManagerService windowManagerF = wm; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -1692,7 +1693,7 @@ public final class SystemServer { traceBeginAndSlog("StartSystemUI"); try { - startSystemUi(context); + startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } @@ -1846,13 +1847,14 @@ public final class SystemServer { }, BOOT_TIMINGS_TRACE_LOG); } - static final void startSystemUi(Context context) { + static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); + windowManager.onSystemUiStarted(); } private static void traceBeginAndSlog(String name) { diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 623d77ba57ed5..c457cb30a2d38 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -637,5 +637,14 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { @Override public void setRecentsVisibilityLw(boolean visible) { - } + } + + @Override + public void onSystemUiStarted() { + } + + @Override + public boolean canDismissBootAnimation() { + return true; + } }