Merge change 5940 into donut

* changes:
  Add CLDR data/formats for newly-translated locales.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 62dc651..5ee29ac 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3981,7 +3981,10 @@
             ProviderRecord pr = mProviderMap.get(name);
             if (pr.mProvider.asBinder() == provider.asBinder()) {
                 Log.i(TAG, "Removing dead content provider: " + name);
-                mProviderMap.remove(name);
+                ProviderRecord removed = mProviderMap.remove(name);
+                if (removed != null) {
+                    removed.mProvider.asBinder().unlinkToDeath(removed, 0);
+                }
             }
         }
     }
@@ -3990,7 +3993,10 @@
         ProviderRecord pr = mProviderMap.get(name);
         if (pr.mProvider.asBinder() == provider.asBinder()) {
             Log.i(TAG, "Removing dead content provider: " + name);
-            mProviderMap.remove(name);
+            ProviderRecord removed = mProviderMap.remove(name);
+            if (removed != null) {
+                removed.mProvider.asBinder().unlinkToDeath(removed, 0);
+            }
         }
     }
 
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 44d1eaa..0785029 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -242,8 +242,15 @@
         // Reset any stored values from last time dialog was shown.
         mStoredComponentName = null;
         mStoredAppSearchData = null;
-        
-        return doShow(initialQuery, selectInitialQuery, componentName, appSearchData, globalSearch);
+
+        boolean success = doShow(initialQuery, selectInitialQuery, componentName, appSearchData,
+                globalSearch);
+        if (success) {
+            // Display the drop down as soon as possible instead of waiting for the rest of the
+            // pending UI stuff to get done, so that things appear faster to the user.
+            mSearchAutoComplete.showDropDownAfterLayout();
+        }
+        return success;
     }
     
     /**
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index eca04b3..3660001 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -21,7 +21,9 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
 import android.widget.RemoteViews;
 
 import com.android.internal.appwidget.IAppWidgetService;
@@ -187,6 +189,8 @@
     
     Context mContext;
 
+    private DisplayMetrics mDisplayMetrics;
+
     /**
      * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
      * Context} object.
@@ -213,6 +217,7 @@
 
     private AppWidgetManager(Context context) {
         mContext = context;
+        mDisplayMetrics = context.getResources().getDisplayMetrics();
     }
 
     /**
@@ -292,7 +297,15 @@
      */
     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
         try {
-            return sService.getAppWidgetInfo(appWidgetId);
+            AppWidgetProviderInfo info = sService.getAppWidgetInfo(appWidgetId);
+            if (info != null) {
+                // Converting complex to dp.
+                info.minWidth = 
+                        TypedValue.complexToDimensionPixelSize(info.minWidth, mDisplayMetrics);
+                info.minHeight =
+                        TypedValue.complexToDimensionPixelSize(info.minHeight, mDisplayMetrics);
+            }
+            return info;
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index e84e5b0..2182384 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -124,6 +124,7 @@
     private boolean mBlockCompletion;
 
     private AutoCompleteTextView.ListSelectorHider mHideSelector;
+    private Runnable mShowDropDownRunnable;
 
     private AutoCompleteTextView.PassThroughClickListener mPassThroughClickListener;
 
@@ -1080,6 +1081,15 @@
     }
 
     /**
+     * Issues a runnable to show the dropdown as soon as possible.
+     *
+     * @hide internal used only by Search Dialog
+     */
+    public void showDropDownAfterLayout() {
+        post(mShowDropDownRunnable);
+    }
+
+    /**
      * <p>Displays the drop down on screen.</p>
      */
     public void showDropDown() {
@@ -1190,6 +1200,22 @@
 
             mHideSelector = new ListSelectorHider();
 
+            /**
+             * This Runnable exists for the sole purpose of checking if the view layout has got
+             * completed and if so call showDropDown to display the drop down. This is used to show
+             * the drop down as soon as possible after user opens up the search dialog, without
+             * waiting for the normal UI pipeline to do it's job which is slower than this method.
+             */
+            mShowDropDownRunnable = new Runnable() {
+                public void run() {
+                    // View layout should be all done before displaying the drop down.
+                    View view = getDropDownAnchorView();
+                    if (view != null && view.getWindowToken() != null) {
+                        showDropDown();
+                    }
+                }
+            };
+
             mDropDownList = new DropDownListView(context);
             mDropDownList.setSelector(mDropDownListHighlight);
             mDropDownList.setAdapter(mAdapter);
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index edd1ea0..4a51e31 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -617,6 +617,9 @@
             synchronized(mListeners) {
                 mListeners.remove(this);
             }
+            if (mListener != null) {
+                mListener.asBinder().unlinkToDeath(this, 0);
+            }
         }
     }
 
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index bd7088c..4ae424a 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -53,6 +53,12 @@
         }
     }
 
+    public void unlinkProvider() {
+        if (mProvider != null) {
+            mProvider.asBinder().unlinkToDeath(this, 0);
+        }
+    }
+
     public String getName() {
         return mName;
     }
@@ -255,5 +261,6 @@
     public void binderDied() {
         Log.w(TAG, "Location Provider " + mName + " died");
         mDead = true;
+        mProvider.asBinder().unlinkToDeath(this, 0);
     }
 }
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index c50ae94..bd8b8ef 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -40,6 +40,7 @@
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.util.Xml;
 import android.widget.RemoteViews;
 
@@ -695,10 +696,16 @@
 
             TypedArray sa = mContext.getResources().obtainAttributes(attrs,
                     com.android.internal.R.styleable.AppWidgetProviderInfo);
-            info.minWidth = sa.getDimensionPixelSize(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth, 0);
-            info.minHeight = sa.getDimensionPixelSize(
-                    com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight, 0);
+            
+            // These dimensions has to be resolved in the application's context.
+            // We simply send back the raw complex data, which will be
+            // converted to dp in {@link AppWidgetManager#getAppWidgetInfo}.
+            TypedValue value = sa.peekValue(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth);
+            info.minWidth = value != null ? value.data : 0; 
+            value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
+            info.minHeight = value != null ? value.data : 0;
+                    
             info.updatePeriodMillis = sa.getInt(
                     com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
             info.initialLayout = sa.getResourceId(
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index ecdf926..b15c06b 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -33,6 +33,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
 import android.net.Uri;
+import android.provider.Settings;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -42,7 +43,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -74,12 +74,13 @@
     private static final String TAG = "BackupManagerService";
     private static final boolean DEBUG = true;
 
-    // Persistent properties
-    private static final String BACKUP_TRANSPORT_PROPERTY = "persist.service.bkup.trans";
-    private static final String BACKUP_ENABLED_PROPERTY = "persist.service.bkup.enabled";
+    // Secure settings
+    private static final String BACKUP_TRANSPORT_SETTING = "backup_transport";
+    private static final String BACKUP_ENABLED_SETTING = "backup_enabled";
 
-    // Default time to wait after data changes before we back up the data
-    private static final long COLLECTION_INTERVAL = 3 * 60 * 1000;
+    // How often we perform a backup pass.  Privileged external callers can
+    // trigger an immediate pass.
+    private static final long BACKUP_INTERVAL = 60 * 60 * 1000;
 
     private static final int MSG_RUN_BACKUP = 1;
     private static final int MSG_RUN_FULL_BACKUP = 2;
@@ -166,7 +167,8 @@
         // Set up our bookkeeping
         // !!! STOPSHIP: make this disabled by default so that we then gate on
         //               setupwizard or other opt-out UI
-        mEnabled = SystemProperties.getBoolean(BACKUP_ENABLED_PROPERTY, true);
+        mEnabled = (Settings.Secure.getInt(mContext.getContentResolver(),
+                BACKUP_ENABLED_SETTING, 1) != 0);
         mBaseStateDir = new File(Environment.getDataDirectory(), "backup");
         mDataDir = Environment.getDownloadCacheDirectory();
 
@@ -191,8 +193,13 @@
 
         mGoogleTransport = null;
         // !!! TODO: set up the default transport name "the right way"
-        mCurrentTransport = SystemProperties.get(BACKUP_TRANSPORT_PROPERTY,
-                "com.google.android.backup/.BackupTransportService");
+        mCurrentTransport = Settings.Secure.getString(mContext.getContentResolver(),
+                BACKUP_TRANSPORT_SETTING);
+        if (mCurrentTransport == null) {
+            mCurrentTransport = "com.google.android.backup/.BackupTransportService";
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    BACKUP_TRANSPORT_SETTING, mCurrentTransport);
+        }
         if (DEBUG) Log.v(TAG, "Starting with transport " + mCurrentTransport);
 
         // Attach to the Google backup transport.  When this comes up, it will set
@@ -204,7 +211,7 @@
         context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE);
 
         // Now that we know about valid backup participants, parse any
-        // leftover journal files and schedule a new backup pass
+        // leftover journal files into the pending backup set
         parseLeftoverJournals();
 
         // Register for broadcasts about package install, etc., so we can
@@ -214,7 +221,13 @@
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
-    }
+
+        // Schedule the first backup pass -- okay because no other threads are
+        // running yet
+        if (mEnabled) {
+            scheduleBackupPassLocked(BACKUP_INTERVAL);
+        }
+}
 
     private void makeJournalLocked() {
         try {
@@ -336,35 +349,39 @@
                 ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>();
                 File oldJournal = mJournal;
                 synchronized (mQueueLock) {
-                    if (mPendingBackups.size() == 0) {
-                        Log.v(TAG, "Backup requested but nothing pending");
-                        break;
-                    }
-
-                    for (BackupRequest b: mPendingBackups.values()) {
-                        queue.add(b);
-                    }
-                    Log.v(TAG, "clearing pending backups");
-                    mPendingBackups.clear();
-
-                    // Start a new backup-queue journal file too
-                    if (mJournalStream != null) {
-                        try {
-                            mJournalStream.close();
-                        } catch (IOException e) {
-                            // don't need to do anything
+                    // Do we have any work to do?
+                    if (mPendingBackups.size() > 0) {
+                        for (BackupRequest b: mPendingBackups.values()) {
+                            queue.add(b);
                         }
-                        makeJournalLocked();
-                    }
+                        Log.v(TAG, "clearing pending backups");
+                        mPendingBackups.clear();
 
-                    // At this point, we have started a new journal file, and the old
-                    // file identity is being passed to the backup processing thread.
-                    // When it completes successfully, that old journal file will be
-                    // deleted.  If we crash prior to that, the old journal is parsed
-                    // at next boot and the journaled requests fulfilled.
+                        // Start a new backup-queue journal file too
+                        if (mJournalStream != null) {
+                            try {
+                                mJournalStream.close();
+                            } catch (IOException e) {
+                                // don't need to do anything
+                            }
+                            makeJournalLocked();
+                        }
+
+                        // At this point, we have started a new journal file, and the old
+                        // file identity is being passed to the backup processing thread.
+                        // When it completes successfully, that old journal file will be
+                        // deleted.  If we crash prior to that, the old journal is parsed
+                        // at next boot and the journaled requests fulfilled.
+                        (new PerformBackupThread(transport, queue, oldJournal)).start();
+                    } else {
+                        Log.v(TAG, "Backup requested but nothing pending");
+                    }
                 }
 
-                (new PerformBackupThread(transport, queue, oldJournal)).start();
+                // Schedule the next pass.
+                synchronized (mQueueLock) {
+                    scheduleBackupPassLocked(BACKUP_INTERVAL);
+                }
                 break;
             }
 
@@ -1109,10 +1126,6 @@
                         Log.d(TAG, "    + " + b + " agent=" + b.appInfo.backupAgentName);
                     }
                 }
-                // Schedule a backup pass in a few minutes.  As backup-eligible data
-                // keeps changing, continue to defer the backup pass until things
-                // settle down, to avoid extra overhead.
-                scheduleBackupPassLocked(COLLECTION_INTERVAL);
             }
         } else {
             Log.w(TAG, "dataChanged but no participant pkg " + packageName);
@@ -1148,20 +1161,21 @@
 
         boolean wasEnabled = mEnabled;
         synchronized (this) {
-            SystemProperties.set(BACKUP_ENABLED_PROPERTY, enable ? "true" : "false");
+            Settings.Secure.putInt(mContext.getContentResolver(), BACKUP_ENABLED_SETTING,
+                    enable ? 1 : 0);
             mEnabled = enable;
         }
 
-        if (enable && !wasEnabled) {
-            synchronized (mQueueLock) {
-                if (mPendingBackups.size() > 0) {
-                    // !!! TODO: better policy around timing of the first backup pass
-                    if (DEBUG) Log.v(TAG, "Backup enabled with pending data changes, scheduling");
-                    this.scheduleBackupPassLocked(COLLECTION_INTERVAL);
-                }
+        synchronized (mQueueLock) {
+            if (enable && !wasEnabled) {
+                // if we've just been enabled, start scheduling backup passes
+                scheduleBackupPassLocked(BACKUP_INTERVAL);
+            } else if (!enable) {
+                // No longer enabled, so stop running backups.
+                mBackupHandler.removeMessages(MSG_RUN_BACKUP);
             }
         }
-}
+    }
 
     // Report whether the backup mechanism is currently enabled
     public boolean isBackupEnabled() {
@@ -1206,7 +1220,8 @@
             if (mTransports.get(transport) != null) {
                 prevTransport = mCurrentTransport;
                 mCurrentTransport = transport;
-                SystemProperties.set(BACKUP_TRANSPORT_PROPERTY, transport);
+                Settings.Secure.putString(mContext.getContentResolver(), BACKUP_TRANSPORT_SETTING,
+                        transport);
                 Log.v(TAG, "selectBackupTransport() set " + mCurrentTransport
                         + " returning " + prevTransport);
             } else {
@@ -1334,13 +1349,22 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (mQueueLock) {
+            pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled"));
+            boolean scheduled = mBackupHandler.hasMessages(MSG_RUN_BACKUP);
+            if (scheduled != mEnabled) {
+                if (mEnabled) {
+                    pw.println("ERROR: backups enabled but none scheduled!");
+                } else {
+                    pw.println("ERROR: backups are scheduled but not enabled!");
+                }
+            }
             pw.println("Available transports:");
             for (String t : listAllTransports()) {
                 String pad = (t.equals(mCurrentTransport)) ? "  * " : "    ";
                 pw.println(pad + t);
             }
             int N = mBackupParticipants.size();
-            pw.println("Participants:");
+            pw.println("Participants: " + N);
             for (int i=0; i<N; i++) {
                 int uid = mBackupParticipants.keyAt(i);
                 pw.print("  uid: ");
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index fc37290..0f5b3fd 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -507,6 +507,7 @@
 
     private void removeProvider(LocationProviderProxy provider) {
         mProviders.remove(provider);
+        provider.unlinkProvider();
         mProvidersByName.remove(provider.getName());
     }
 
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index c5ea5fa9..79d78ad1 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -709,7 +709,10 @@
                     p.awakeOnSet = true;
                 }
             } else {
-                mPokeLocks.remove(token);
+                PokeLock rLock = mPokeLocks.remove(token);
+                if (rLock != null) {
+                    token.unlinkToDeath(rLock, 0);
+                }
             }
 
             int oldPokey = mPokey;
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5df88b2..f5e2e3d 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1875,7 +1875,9 @@
         private WifiLock removeLock(IBinder binder) {
             int index = findLockByBinder(binder);
             if (index >= 0) {
-                return mList.remove(index);
+                WifiLock ret = mList.remove(index);
+                ret.unlinkDeathRecipient();
+                return ret;
             } else {
                 return null;
             }
@@ -1987,6 +1989,10 @@
                 binderDied();
             }
         }
+
+        void unlinkDeathRecipient() {
+            mBinder.unlinkToDeath(this, 0);
+        }
     }
 
     private class Multicaster extends DeathRecipient {
@@ -2054,7 +2060,10 @@
 
     private void removeMulticasterLocked(int i, int uid)
     {
-        mMulticasters.remove(i);
+        Multicaster removed = mMulticasters.remove(i);
+        if (removed != null) {
+            removed.unlinkDeathRecipient();
+        }
         if (mMulticasters.size() == 0) {
             WifiNative.startPacketFiltering();
         }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 9bad153..cfa625c 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -3407,7 +3407,10 @@
                 synchronized (mWindowMap) {
                     for (int i=0; i<mRotationWatchers.size(); i++) {
                         if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
-                            mRotationWatchers.remove(i);
+                            IRotationWatcher removed = mRotationWatchers.remove(i);
+                            if (removed != null) {
+                                removed.asBinder().unlinkToDeath(this, 0);
+                            }
                             i--;
                         }
                     }
@@ -5442,6 +5445,7 @@
             } catch (RemoteException e) {
             }
             synchronized(mWindowMap) {
+                mClient.asBinder().unlinkToDeath(this, 0);
                 mClientDead = true;
                 killSessionLocked();
             }
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 48cbace..b44168a 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -119,6 +119,7 @@
         public void binderDied() {
             Log.i(TAG, "binder died for pkg=" + pkg);
             disable(0, token, pkg);
+            token.unlinkToDeath(this, 0);
         }
     }
 
@@ -494,6 +495,7 @@
             if (what == 0 || !token.isBinderAlive()) {
                 if (tok != null) {
                     mDisableRecords.remove(i);
+                    tok.token.unlinkToDeath(tok, 0);
                 }
             } else {
                 if (tok == null) {