am 234eadcf: Don\'t wait on ContactsProvider

* commit '234eadcf7d0dbf2d24f92c24f40343d518f6fe3a':
  Don't wait on ContactsProvider
diff --git a/src/com/android/browser/AutofillHandler.java b/src/com/android/browser/AutofillHandler.java
index 99ee6a0..5b0320d 100644
--- a/src/com/android/browser/AutofillHandler.java
+++ b/src/com/android/browser/AutofillHandler.java
@@ -26,6 +26,7 @@
 import android.os.Message;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract;
+import android.util.Log;
 import android.webkit.WebSettingsClassic.AutoFillProfile;
 
 import java.util.concurrent.CountDownLatch;
@@ -43,6 +44,8 @@
     private CountDownLatch mLoaded = new CountDownLatch(1);
     private Context mContext;
 
+    private static final String LOGTAG = "AutofillHandler";
+
     public AutofillHandler(Context context) {
         mContext = context.getApplicationContext();
     }
@@ -62,18 +65,24 @@
          new LoadFromDb().start();
     }
 
-    public void waitForLoad() {
+    private void waitForLoad() {
         try {
             mLoaded.await();
-        } catch (InterruptedException e) {}
+        } catch (InterruptedException e) {
+            Log.w(LOGTAG, "Caught exception while waiting for AutofillProfile to load.");
+        }
     }
 
     private class LoadFromDb extends Thread {
 
         @Override
         public void run() {
-            SharedPreferences p =
-                    PreferenceManager.getDefaultSharedPreferences(mContext);
+            // Note the lack of synchronization over mAutoFillActiveProfileId and
+            // mAutoFillProfile here. This is because we control all other access
+            // to these members through the public functions of this class, and they
+            // all wait for this thread via the mLoaded CountDownLatch.
+
+            SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(mContext);
 
             // Read the last active AutoFill profile id.
             mAutoFillActiveProfileId = p.getInt(
@@ -82,7 +91,9 @@
 
             // Load the autofill profile data from the database. We use a database separate
             // to the browser preference DB to make it easier to support multiple profiles
-            // and switching between them.
+            // and switching between them. Note that this may block startup if this DB lookup
+            // is extremely slow. We do this to ensure that if there's a profile set, the
+            // user never sees the "setup Autofill" option.
             AutoFillProfileDatabase autoFillDb = AutoFillProfileDatabase.getInstance(mContext);
             Cursor c = autoFillDb.getProfile(mAutoFillActiveProfileId);
 
@@ -116,12 +127,19 @@
             c.close();
             autoFillDb.close();
 
+            // At this point we've loaded the profile if there was one, so let any thread
+            // waiting on initialization continue.
+            mLoaded.countDown();
+
+            // Synchronization note: strictly speaking, it's possible that mAutoFillProfile
+            // may get a value after we check below, but that's OK. This check is only an
+            // optimisation, and we do a proper synchronized check further down when it comes
+            // to actually setting the inferred profile.
             if (mAutoFillProfile == null) {
-                // We did not load a profile from disk. Try to populate one with the user's
+                // We did not load a profile from disk. Try to infer one from the user's
                 // "me" contact.
                 final Uri profileUri = Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
                         ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
-
                 String name = getContactField(profileUri,
                         ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
                         ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
@@ -143,13 +161,16 @@
                     // When querying structured postal data, it often all comes back as a string
                     // inside the "street" field.
 
-                    mAutoFillProfile = new AutoFillProfile(
-                            1, name, email, company, null, null, null, null,
-                            null, null, phone);
+                    synchronized(AutofillHandler.this) {
+                        // Only use this profile if one hasn't been set inbetween the
+                        // inital import and this thread getting to this point.
+                        if (mAutoFillProfile == null) {
+                            setAutoFillProfile(new AutoFillProfile(1, name, email, company,
+                                    null, null, null, null, null, null, phone), null);
+                        }
+                    }
                 }
             }
-
-            mLoaded.countDown();
         }
 
         private String getContactField(Uri uri, String field, String itemType) {
@@ -174,7 +195,8 @@
         }
     }
 
-    public void setAutoFillProfile(AutoFillProfile profile, Message msg) {
+    public synchronized void setAutoFillProfile(AutoFillProfile profile, Message msg) {
+        waitForLoad();
         int profileId = NO_AUTOFILL_PROFILE_SET;
         if (profile != null) {
             profileId = profile.getUniqueId();
@@ -193,11 +215,12 @@
         setActiveAutoFillProfileId(profileId);
     }
 
-    public AutoFillProfile getAutoFillProfile() {
+    public synchronized AutoFillProfile getAutoFillProfile() {
+        waitForLoad();
         return mAutoFillProfile;
     }
 
-    private void setActiveAutoFillProfileId(int activeProfileId) {
+    private synchronized void setActiveAutoFillProfileId(int activeProfileId) {
         mAutoFillActiveProfileId = activeProfileId;
         Editor ed = PreferenceManager.
             getDefaultSharedPreferences(mContext).edit();
@@ -234,9 +257,11 @@
         @Override
         protected Void doInBackground(AutoFillProfile... values) {
             mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
-            assert mAutoFillActiveProfileId != NO_AUTOFILL_PROFILE_SET;
-            AutoFillProfile newProfile = values[0];
-            mAutoFillProfileDb.addOrUpdateProfile(mAutoFillActiveProfileId, newProfile);
+            synchronized (AutofillHandler.this) {
+                assert mAutoFillActiveProfileId != NO_AUTOFILL_PROFILE_SET;
+                AutoFillProfile newProfile = values[0];
+                mAutoFillProfileDb.addOrUpdateProfile(mAutoFillActiveProfileId, newProfile);
+            }
             return null;
         }
     }
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 76dc48f..0b7e87a 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -510,12 +510,10 @@
     }
 
     public AutoFillProfile getAutoFillProfile() {
-        mAutofillHandler.waitForLoad();
         return mAutofillHandler.getAutoFillProfile();
     }
 
     public void setAutoFillProfile(AutoFillProfile profile, Message msg) {
-        mAutofillHandler.waitForLoad();
         mAutofillHandler.setAutoFillProfile(profile, msg);
         // Auto-fill will reuse the same profile ID when making edits to the profile,
         // so we need to force a settings sync (otherwise the SharedPreferences