|
48 | 48 | import android.os.Process; |
49 | 49 | import android.os.RemoteException; |
50 | 50 | import android.os.SystemClock; |
| 51 | +import android.os.SystemService; |
51 | 52 | import android.os.UserHandle; |
52 | 53 | import android.os.WorkSource; |
53 | 54 | import android.provider.Settings; |
@@ -81,6 +82,8 @@ public final class PowerManagerService extends IPowerManager.Stub |
81 | 82 | private static final int MSG_SANDMAN = 2; |
82 | 83 | // Message: Sent when the screen on blocker is released. |
83 | 84 | private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3; |
| 85 | + // Message: Sent to poll whether the boot animation has terminated. |
| 86 | + private static final int MSG_CHECK_IF_BOOT_ANIMATION_FINISHED = 4; |
84 | 87 |
|
85 | 88 | // Dirty bit: mWakeLocks changed |
86 | 89 | private static final int DIRTY_WAKE_LOCKS = 1 << 0; |
@@ -153,6 +156,12 @@ public final class PowerManagerService extends IPowerManager.Stub |
153 | 156 | // See point of use for more details. |
154 | 157 | private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95; |
155 | 158 |
|
| 159 | + // The name of the boot animation service in init.rc. |
| 160 | + private static final String BOOT_ANIMATION_SERVICE = "bootanim"; |
| 161 | + |
| 162 | + // Poll interval in milliseconds for watching boot animation finished. |
| 163 | + private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; |
| 164 | + |
156 | 165 | private Context mContext; |
157 | 166 | private LightsService mLightsService; |
158 | 167 | private BatteryService mBatteryService; |
@@ -1662,6 +1671,29 @@ private void handleBatteryStateChangedLocked() { |
1662 | 1671 | updatePowerStateLocked(); |
1663 | 1672 | } |
1664 | 1673 |
|
| 1674 | + private void startWatchingForBootAnimationFinished() { |
| 1675 | + mHandler.sendEmptyMessage(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED); |
| 1676 | + } |
| 1677 | + |
| 1678 | + private void checkIfBootAnimationFinished() { |
| 1679 | + if (DEBUG) { |
| 1680 | + Slog.d(TAG, "Check if boot animation finished..."); |
| 1681 | + } |
| 1682 | + |
| 1683 | + if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { |
| 1684 | + mHandler.sendEmptyMessageDelayed(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED, |
| 1685 | + BOOT_ANIMATION_POLL_INTERVAL); |
| 1686 | + return; |
| 1687 | + } |
| 1688 | + |
| 1689 | + synchronized (mLock) { |
| 1690 | + if (!mBootCompleted) { |
| 1691 | + Slog.i(TAG, "Boot animation finished."); |
| 1692 | + handleBootCompletedLocked(); |
| 1693 | + } |
| 1694 | + } |
| 1695 | + } |
| 1696 | + |
1665 | 1697 | private void handleBootCompletedLocked() { |
1666 | 1698 | final long now = SystemClock.uptimeMillis(); |
1667 | 1699 | mBootCompleted = true; |
@@ -2170,9 +2202,13 @@ public void onReceive(Context context, Intent intent) { |
2170 | 2202 | private final class BootCompletedReceiver extends BroadcastReceiver { |
2171 | 2203 | @Override |
2172 | 2204 | public void onReceive(Context context, Intent intent) { |
2173 | | - synchronized (mLock) { |
2174 | | - handleBootCompletedLocked(); |
2175 | | - } |
| 2205 | + // This is our early signal that the system thinks it has finished booting. |
| 2206 | + // However, the boot animation may still be running for a few more seconds |
| 2207 | + // since it is ultimately in charge of when it terminates. |
| 2208 | + // Defer transitioning into the boot completed state until the animation exits. |
| 2209 | + // We do this so that the screen does not start to dim prematurely before |
| 2210 | + // the user has actually had a chance to interact with the device. |
| 2211 | + startWatchingForBootAnimationFinished(); |
2176 | 2212 | } |
2177 | 2213 | } |
2178 | 2214 |
|
@@ -2227,6 +2263,9 @@ public void handleMessage(Message msg) { |
2227 | 2263 | case MSG_SCREEN_ON_BLOCKER_RELEASED: |
2228 | 2264 | handleScreenOnBlockerReleased(); |
2229 | 2265 | break; |
| 2266 | + case MSG_CHECK_IF_BOOT_ANIMATION_FINISHED: |
| 2267 | + checkIfBootAnimationFinished(); |
| 2268 | + break; |
2230 | 2269 | } |
2231 | 2270 | } |
2232 | 2271 | } |
|
0 commit comments