diff options
5 files changed, 175 insertions, 130 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 394b183..677fcef 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2295,6 +2295,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case BOOT_ANIMATION_COMPLETE_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + bootAnimationComplete(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -5301,5 +5308,16 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + @Override + public void bootAnimationComplete() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(BOOT_ANIMATION_COMPLETE_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 9483680..8fa1fd5 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -327,6 +327,8 @@ public interface IActivityManager extends IInterface { public void notifyActivityDrawn(IBinder token) throws RemoteException; public ActivityOptions getActivityOptions(IBinder token) throws RemoteException; + public void bootAnimationComplete() throws RemoteException; + public void setImmersive(IBinder token, boolean immersive) throws RemoteException; public boolean isImmersive(IBinder token) throws RemoteException; public boolean isTopActivityImmersive() throws RemoteException; @@ -772,4 +774,5 @@ public interface IActivityManager extends IInterface { int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234; int RELEASE_ACTIVITY_INSTANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+235; int RELEASE_SOME_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+236; + int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a9a4732..5845ad0 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -888,6 +888,8 @@ public final class ActivityManagerService extends ActivityManagerNative boolean mProcessesReady = false; boolean mSystemReady = false; boolean mBooting = false; + boolean mCallFinishBooting = false; + boolean mBootAnimationComplete = false; boolean mWaitingUpdate = false; boolean mDidUpdate = false; boolean mOnBattery = false; @@ -6195,6 +6197,14 @@ public final class ActivityManagerService extends ActivityManagerNative } final void finishBooting() { + synchronized (this) { + if (!mBootAnimationComplete) { + mCallFinishBooting = true; + return; + } + mCallFinishBooting = false; + } + // Register receivers to handle package update events mPackageMonitor.register(mContext, Looper.getMainLooper(), false); @@ -6253,6 +6263,18 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override + public void bootAnimationComplete() { + final boolean callFinishBooting; + synchronized (this) { + callFinishBooting = mCallFinishBooting; + mBootAnimationComplete = true; + } + if (callFinishBooting) { + finishBooting(); + } + } + final void ensureBootCompleted() { boolean booting; boolean enableScreen; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 5f97a00..7808800 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -91,8 +91,6 @@ public final class PowerManagerService extends com.android.server.SystemService private static final int MSG_SANDMAN = 2; // Message: Sent when the screen on blocker is released. private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3; - // Message: Sent to poll whether the boot animation has terminated. - private static final int MSG_CHECK_IF_BOOT_ANIMATION_FINISHED = 4; // Dirty bit: mWakeLocks changed private static final int DIRTY_WAKE_LOCKS = 1 << 0; @@ -154,12 +152,6 @@ public final class PowerManagerService extends com.android.server.SystemService // provider populates the actual default value (R.integer.def_screen_off_timeout). private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000; - // The name of the boot animation service in init.rc. - private static final String BOOT_ANIMATION_SERVICE = "bootanim"; - - // Poll interval in milliseconds for watching boot animation finished. - private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; - // Power hints defined in hardware/libhardware/include/hardware/power.h. private static final int POWER_HINT_INTERACTION = 2; private static final int POWER_HINT_LOW_POWER = 5; @@ -478,14 +470,15 @@ public final class PowerManagerService extends com.android.server.SystemService @Override public void onBootPhase(int phase) { - if (phase == PHASE_BOOT_COMPLETED) { - // This is our early signal that the system thinks it has finished booting. - // However, the boot animation may still be running for a few more seconds - // since it is ultimately in charge of when it terminates. - // Defer transitioning into the boot completed state until the animation exits. - // We do this so that the screen does not start to dim prematurely before - // the user has actually had a chance to interact with the device. - startWatchingForBootAnimationFinished(); + synchronized (mLock) { + if (phase == PHASE_BOOT_COMPLETED) { + final long now = SystemClock.uptimeMillis(); + mBootCompleted = true; + mDirty |= DIRTY_BOOT_COMPLETED; + userActivityNoUpdateLocked( + now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); + updatePowerStateLocked(); + } } } @@ -2076,38 +2069,6 @@ public final class PowerManagerService extends com.android.server.SystemService updatePowerStateLocked(); } - private void startWatchingForBootAnimationFinished() { - mHandler.sendEmptyMessage(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED); - } - - private void checkIfBootAnimationFinished() { - if (DEBUG) { - Slog.d(TAG, "Check if boot animation finished..."); - } - - if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { - mHandler.sendEmptyMessageDelayed(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED, - BOOT_ANIMATION_POLL_INTERVAL); - return; - } - - synchronized (mLock) { - if (!mBootCompleted) { - Slog.i(TAG, "Boot animation finished."); - handleBootCompletedLocked(); - } - } - } - - private void handleBootCompletedLocked() { - final long now = SystemClock.uptimeMillis(); - mBootCompleted = true; - mDirty |= DIRTY_BOOT_COMPLETED; - userActivityNoUpdateLocked( - now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); - updatePowerStateLocked(); - } - private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm, final String reason, boolean wait) { if (mHandler == null || !mSystemReady) { @@ -2528,9 +2489,6 @@ public final class PowerManagerService extends com.android.server.SystemService case MSG_SCREEN_ON_BLOCKER_RELEASED: handleScreenOnBlockerReleased(); break; - case MSG_CHECK_IF_BOOT_ANIMATION_FINISHED: - checkIfBootAnimationFinished(); - break; } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 10ab6b5..54af851 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.*; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import android.app.AppOpsManager; import android.os.Build; +import android.os.SystemService; import android.util.ArraySet; import android.util.TimeUtils; import android.view.IWindowId; @@ -272,6 +273,12 @@ public class WindowManagerService extends IWindowManager.Stub // Default input dispatching timeout in nanoseconds. static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; + // Poll interval in milliseconds for watching boot animation finished. + private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; + + // The name of the boot animation service in init.rc. + private static final String BOOT_ANIMATION_SERVICE = "bootanim"; + /** Minimum value for attachStack and resizeStack weight value */ public static final float STACK_WEIGHT_MIN = 0.2f; @@ -458,6 +465,7 @@ public class WindowManagerService extends IWindowManager.Stub boolean mSystemBooted = false; boolean mForceDisplayEnabled = false; boolean mShowingBootMessages = false; + boolean mBootAnimationStopped = false; String mLastANRState; @@ -5607,17 +5615,70 @@ public class WindowManagerService extends IWindowManager.Stub performEnableScreen(); } + private boolean checkWaitingForWindowsLocked() { + + boolean haveBootMsg = false; + boolean haveApp = false; + // if the wallpaper service is disabled on the device, we're never going to have + // wallpaper, don't bother waiting for it + boolean haveWallpaper = false; + boolean wallpaperEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enableWallpaperService) + && !mOnlyCore; + boolean haveKeyguard = true; + // TODO(multidisplay): Expand to all displays? + final WindowList windows = getDefaultWindowListLocked(); + final int N = windows.size(); + for (int i=0; i<N; i++) { + WindowState w = windows.get(i); + if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { + return true; + } + if (w.isDrawnLw()) { + if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { + haveBootMsg = true; + } else if (w.mAttrs.type == TYPE_APPLICATION) { + haveApp = true; + } else if (w.mAttrs.type == TYPE_WALLPAPER) { + haveWallpaper = true; + } else if (w.mAttrs.type == TYPE_STATUS_BAR) { + haveKeyguard = mPolicy.isKeyguardDrawnLw(); + } + } + } + + if (DEBUG_SCREEN_ON || DEBUG_BOOT) { + Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages + + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp + + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled + + " haveKeyguard=" + haveKeyguard); + } + + // If we are turning on the screen to show the boot message, + // don't do it until the boot message is actually displayed. + if (!mSystemBooted && !haveBootMsg) { + return true; + } + + // If we are turning on the screen after the boot is completed + // normally, don't do so until we have the application and + // wallpaper. + if (mSystemBooted && ((!haveApp && !haveKeyguard) || + (wallpaperEnabled && !haveWallpaper))) { + return true; + } + + return false; + } + public void performEnableScreen() { synchronized(mWindowMap) { - if (DEBUG_BOOT) { - RuntimeException here = new RuntimeException("here"); - here.fillInStackTrace(); - Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled - + " mForceDisplayEnabled=" + mForceDisplayEnabled - + " mShowingBootMessages=" + mShowingBootMessages - + " mSystemBooted=" + mSystemBooted - + " mOnlyCore=" + mOnlyCore, here); - } + if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled + + " mForceDisplayEnabled=" + mForceDisplayEnabled + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted + + " mOnlyCore=" + mOnlyCore, + new RuntimeException("here").fillInStackTrace()); if (mDisplayEnabled) { return; } @@ -5625,94 +5686,64 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (!mForceDisplayEnabled) { - // Don't enable the screen until all existing windows - // have been drawn. - boolean haveBootMsg = false; - boolean haveApp = false; - // if the wallpaper service is disabled on the device, we're never going to have - // wallpaper, don't bother waiting for it - boolean haveWallpaper = false; - boolean wallpaperEnabled = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_enableWallpaperService) - && !mOnlyCore; - boolean haveKeyguard = true; - // TODO(multidisplay): Expand to all displays? - final WindowList windows = getDefaultWindowListLocked(); - final int N = windows.size(); - for (int i=0; i<N; i++) { - WindowState w = windows.get(i); - if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { - return; - } - if (w.isDrawnLw()) { - if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { - haveBootMsg = true; - } else if (w.mAttrs.type == TYPE_APPLICATION) { - haveApp = true; - } else if (w.mAttrs.type == TYPE_WALLPAPER) { - haveWallpaper = true; - } else if (w.mAttrs.type == TYPE_STATUS_BAR) { - haveKeyguard = mPolicy.isKeyguardDrawnLw(); - } - } - } - - if (DEBUG_SCREEN_ON || DEBUG_BOOT) { - Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages - + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp - + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled - + " haveKeyguard=" + haveKeyguard); - } + // Don't enable the screen until all existing windows have been drawn. + if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) { + return; + } - // If we are turning on the screen to show the boot message, - // don't do it until the boot message is actually displayed. - if (!mSystemBooted && !haveBootMsg) { - return; + if (!mBootAnimationStopped) { + // Do this one time. + try { + IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); + if (surfaceFlinger != null) { + //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED + data, null, 0); + data.recycle(); + } + } catch (RemoteException ex) { + Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); } + mBootAnimationStopped = true; + } - // If we are turning on the screen after the boot is completed - // normally, don't do so until we have the application and - // wallpaper. - if (mSystemBooted && ((!haveApp && !haveKeyguard) || - (wallpaperEnabled && !haveWallpaper))) { - return; - } + if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) { + if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: Waiting for anim complete"); + return; } mDisplayEnabled = true; if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); - if (false) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new FastPrintWriter(sw, false, 1024); - this.dump(null, pw, null); - pw.flush(); - Slog.i(TAG, sw.toString()); - } - try { - IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); - if (surfaceFlinger != null) { - //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); - Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED - data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); - } // Enable input dispatch. mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); } + try { + mActivityManager.bootAnimationComplete(); + } catch (RemoteException e) { + } + mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. updateRotationUnchecked(false, false); } + private boolean checkBootAnimationCompleteLocked() { + if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { + mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED); + mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED, + BOOT_ANIMATION_POLL_INTERVAL); + if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Waiting for anim complete"); + return false; + } + if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Animation complete!"); + return true; + } + public void showBootMessage(final CharSequence msg, final boolean always) { boolean first = false; synchronized(mWindowMap) { @@ -7457,6 +7488,8 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; + public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; + @Override public void handleMessage(Message msg) { if (DEBUG_WINDOW_TRACE) { @@ -7941,6 +7974,17 @@ public class WindowManagerService extends IWindowManager.Stub } } break; + case CHECK_IF_BOOT_ANIMATION_FINISHED: { + final boolean bootAnimationComplete; + synchronized (mWindowMap) { + if (DEBUG_BOOT) Slog.i(TAG, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); + bootAnimationComplete = checkBootAnimationCompleteLocked(); + } + if (bootAnimationComplete) { + performEnableScreen(); + } + } + break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG, "handleMessage: exit"); |
