Fix issue where keyguard adds widgets before the system is ready

While under heavy system load,  keyguard was able to create widgets before
before ActivityManagerService was ready.  The result was a race
between keyguard adding widgets and ActivityManagerService being
ready to send broadcasts.

This fix provides keyguard with an additional signal to know when
the system is booted and widgets are safe to load.

Fixes bug b/11217169

Change-Id: I7a714d65b068678f961e52bdde4e1c20f9c287f0
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 45a38be..63ff5a0 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -43,4 +43,5 @@
     oneway void showAssistant();
     oneway void dispatch(in MotionEvent event);
     oneway void launchCamera();
+    oneway void onBootCompleted();
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
index d7c5fe2..36b2446 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
@@ -141,6 +141,10 @@
             checkPermission();
             mKeyguardViewMediator.launchCamera();
         }
+        public void onBootCompleted() {
+            checkPermission();
+            mKeyguardViewMediator.onBootCompleted();
+        }
     };
 
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 45cd3d4..520cea3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -635,15 +635,14 @@
      * PhoneWindowManager in this case.
      */
     protected void dispatchBootCompleted() {
-        if (!mBootCompleted) {
-            mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
-        }
+        mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
     }
 
     /**
      * Handle {@link #MSG_BOOT_COMPLETED}
      */
     protected void handleBootCompleted() {
+        if (mBootCompleted) return;
         mBootCompleted = true;
         mAudioManager = new AudioManager(mContext);
         mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
index a37a3a4..b92ae90 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
@@ -530,9 +530,6 @@
             mSystemReady = true;
             mUpdateMonitor.registerCallback(mUpdateCallback);
 
-            // Send boot completed message if it hasn't already been sent.
-            mUpdateMonitor.dispatchBootCompleted();
-
             // Suppress biometric unlock right after boot until things have settled if it is the
             // selected security method, otherwise unsuppress it.  It must be unsuppressed if it is
             // not the selected security method for the following reason:  if the user starts
@@ -1366,4 +1363,8 @@
         Message msg = mHandler.obtainMessage(LAUNCH_CAMERA);
         mHandler.sendMessage(msg);
     }
+
+    public void onBootCompleted() {
+        mUpdateMonitor.dispatchBootCompleted();
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1c43014..816672f 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -4668,6 +4668,9 @@
 
     /** {@inheritDoc} */
     public void systemBooted() {
+        if (mKeyguardDelegate != null) {
+            mKeyguardDelegate.onBootCompleted();
+        }
         synchronized (mLock) {
             mSystemBooted = true;
         }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 56a282b..bf22e2f 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -52,6 +52,7 @@
         public int offReason;
         public int currentUser;
         public boolean screenIsOn;
+        public boolean bootCompleted;
     };
 
     public interface ShowListener {
@@ -117,6 +118,9 @@
                 // This is used to hide the scrim once keyguard displays.
                 mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
             }
+            if (mKeyguardState.bootCompleted) {
+                mKeyguardService.onBootCompleted();
+            }
         }
 
         @Override
@@ -305,4 +309,11 @@
         });
     }
 
+    public void onBootCompleted() {
+        if (mKeyguardService != null) {
+            mKeyguardService.onBootCompleted();
+        }
+        mKeyguardState.bootCompleted = true;
+    }
+
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 83be1a8..9fb2a50 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -180,6 +180,14 @@
         }
     }
 
+    public void onBootCompleted() {
+        try {
+            mService.onBootCompleted();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
     public void showAssistant() {
         // Not used by PhoneWindowManager
     }