Merge change 840 into donut

* changes:
  TypedProperties: change the file format to be a subset of Java
diff --git a/api/current.xml b/api/current.xml
index 75eec10..c732c30 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -21740,82 +21740,6 @@
 </field>
 </class>
 </package>
-<package name="android.backup"
->
-<class name="BackupService"
- extends="android.app.Service"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="BackupService"
- type="android.backup.BackupService"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="onBackup"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="oldStateFd" type="int">
-</parameter>
-<parameter name="dataFd" type="int">
-</parameter>
-<parameter name="newStateFd" type="int">
-</parameter>
-</method>
-<method name="onBind"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-</method>
-<method name="onRestore"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dataFd" type="int">
-</parameter>
-<parameter name="newStateFd" type="int">
-</parameter>
-</method>
-<field name="SERVICE_ACTION"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.service.action.BACKUP&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-</package>
 <package name="android.content"
 >
 <class name="ActivityNotFoundException"
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 4fb17c7..cd44277 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -111,6 +111,10 @@
     private boolean mGlobalSearchMode;
     private Context mActivityContext;
     
+    // Values we store to allow user to toggle between in-app search and global search.
+    private ComponentName mStoredComponentName;
+    private Bundle mStoredAppSearchData;
+    
     // stack of previous searchables, to support the BACK key after
     // SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.
     // The top of the stack (= previous searchable) is the last element of the list,
@@ -228,20 +232,70 @@
             return true;
         }
         
+        // Reset any stored values from last time dialog was shown.
+        mStoredComponentName = null;
+        mStoredAppSearchData = null;
+        
+        return doShow(initialQuery, selectInitialQuery, componentName, appSearchData, globalSearch);
+    }
+    
+    
+    /**
+     * Called in response to a press of the hard search button in
+     * {@link #onKeyDown(int, KeyEvent)}, this method toggles between in-app
+     * search and global search when relevant.
+     * 
+     * If pressed within an in-app search context, this switches the search dialog out to
+     * global search. If pressed within a global search context that was originally an in-app
+     * search context, this switches back to the in-app search context. If pressed within a
+     * global search context that has no original in-app search context (e.g., global search
+     * from Home), this does nothing.
+     * 
+     * @return false if we wanted to toggle context but could not do so successfully, true
+     * in all other cases
+     */
+    private boolean toggleGlobalSearch() {
+        String currentSearchText = mSearchAutoComplete.getText().toString();
+        if (!mGlobalSearchMode) {
+            mStoredComponentName = mLaunchComponent;
+            mStoredAppSearchData = mAppSearchData;
+            return doShow(currentSearchText, false, null, mAppSearchData, true);
+        } else {
+            if (mStoredComponentName != null) {
+                // This means we should toggle *back* to an in-app search context from
+                // global search.
+                return doShow(currentSearchText, false, mStoredComponentName,
+                        mStoredAppSearchData, false);
+            } else {
+                return true;
+            }
+        }
+    }
+    
+    /**
+     * Does the rest of the work required to show the search dialog. Called by both
+     * {@link #show(String, boolean, ComponentName, Bundle, boolean)} and
+     * {@link #toggleGlobalSearch()}.
+     * 
+     * @return true if search dialog showed, false if not
+     */
+    private boolean doShow(String initialQuery, boolean selectInitialQuery,
+            ComponentName componentName, Bundle appSearchData,
+            boolean globalSearch) {
         // set up the searchable and show the dialog
         if (!show(componentName, appSearchData, globalSearch)) {
             return false;
         }
-        
+
         // finally, load the user's initial text (which may trigger suggestions)
         setUserQuery(initialQuery);
         if (selectInitialQuery) {
             mSearchAutoComplete.selectAll();
         }
-        
+
         return true;
     }
-    
+
     /**
      * Sets up the search dialog and shows it.
      * 
@@ -650,14 +704,11 @@
             return true;
         }
         
-        // search or cancel on search key
         if (keyCode == KeyEvent.KEYCODE_SEARCH) {
-            if (!mSearchAutoComplete.isEmpty()) {
-                launchQuerySearch();
-            } else {
-                cancel();
-            }
-            return true;
+            // If the search key is pressed, toggle between global and in-app search. If we are
+            // currently doing global search and there is no in-app search context to toggle to,
+            // just don't do anything.
+            return toggleGlobalSearch();
         }
 
         // if it's an action specified by the searchable activity, launch the
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
new file mode 100644
index 0000000..6f0b2ee
--- /dev/null
+++ b/core/java/android/backup/BackupManager.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.backup;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+/**
+ * BackupManager is the interface to the system's backup service.
+ * Applications simply instantiate one, and then use that instance
+ * to communicate with the backup infrastructure.
+ *
+ * <p>When your application has made changes to data it wishes to have
+ * backed up, call {@link #dataChanged()} to notify the backup service.
+ * The system will then schedule a backup operation to occur in the near
+ * future.  Repeated calls to {@link #dataChanged()} have no further effect
+ * until the backup operation actually occurs.
+ *
+ * <p>The backup operation itself begins with the system launching the
+ * {@link BackupService} subclass declared in your manifest.  See the documentation
+ * for {@link BackupService} for a detailed description of how the backup then proceeds.
+ *
+ * @hide pending API solidification
+ */
+public class BackupManager {
+    private Context mContext;
+    private IBackupManager mService;
+
+    /**
+     * Constructs a BackupManager object through which the application can
+     * communicate with the Android backup system.
+     *
+     * @param context The {@link android.content.Context} that was provided when
+     *                one of your application's {@link android.app.Activity Activities}
+     *                was created.
+     */
+    public BackupManager(Context context) {
+        mContext = context;
+        mService = IBackupManager.Stub.asInterface(
+                ServiceManager.getService(Context.BACKUP_SERVICE));
+    }
+
+    /**
+     * Notifies the Android backup system that your application wishes to back up
+     * new changes to its data.  A backup operation using your application's
+     * {@link BackupService} subclass will be scheduled when you call this method.
+     */
+    public void dataChanged() {
+        try {
+            mService.dataChanged(mContext.getPackageName());
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/core/java/android/backup/BackupService.java b/core/java/android/backup/BackupService.java
index 5cfa4f2..d912d8c 100644
--- a/core/java/android/backup/BackupService.java
+++ b/core/java/android/backup/BackupService.java
@@ -29,7 +29,20 @@
  * This is the central interface between an application and Android's
  * settings backup mechanism.
  * 
- * <p><em>Not hidden but API subject to change and should not be published</em>
+ * In order to use the backup service, your application must implement a
+ * subclass of BackupService, and declare an intent filter
+ * in the application manifest specifying that your BackupService subclass
+ * handles the {link #SERVICE_ACTION} intent action.  For example:
+ * 
+ * <pre class="prettyprint">
+ *      &lt;!-- Use the class "MyBackupService" to perform backups for my app --&gt;
+ *      &lt;service android:name=".MyBackupService"&gt;
+ *          &lt;intent-filter&gt;
+ *              &lt;action android:name="android.service.action.BACKUP"&gt;
+ *          &lt;/intent-filter&gt;
+ *      &lt;/service&gt;</pre>
+ * 
+ * @hide pending API solidification
  */
 
 public abstract class BackupService extends Service {
@@ -40,7 +53,7 @@
      * IntentFilter} that accepts this action. 
      */
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_ACTION = "android.service.action.BACKUP";
+    public static final String SERVICE_ACTION = "android.backup.BackupService";
 
     /**
      * The application is being asked to write any data changed since the
@@ -50,7 +63,7 @@
      * should perform a full backup.  In both cases, a representation of the
      * final backup state after this pass should be written to the file pointed
      * to by the newStateFd file descriptor.
-     * 
+     *
      * @param oldStateFd An open, read-only file descriptor pointing to the last
      *                   backup state provided by the application.  May be negative,
      *                   in which case no prior state is being provided and the
@@ -70,7 +83,7 @@
      * provided in the file pointed to by the dataFd file descriptor.  Once
      * the restore is finished, the application should write a representation
      * of the final state to the newStateFd file descriptor, 
-     * 
+     *
      * @param dataFd An open, read-only file descriptor pointing to a full snapshot
      *               of the application's data.
      * @param newStateFd An open, read/write file descriptor pointing to an empty
@@ -82,8 +95,15 @@
 
     // ----- Core implementation -----
     
+    /**
+     * Returns the private interface called by the backup system.  Applications will
+     * not typically override this.
+     */
     public IBinder onBind(Intent intent) {
-        return mBinder;
+        if (intent.getAction().equals(SERVICE_ACTION)) {
+            return mBinder;
+        }
+        return null;
     }
 
     private final IBinder mBinder = new BackupServiceBinder().asBinder();
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index 40cebdd..7efaf58 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -21,12 +21,15 @@
  * operation currently needed is a simple notification that the app has made changes to
  * data it wishes to back up, so the system should run a backup pass.
  *
- * {@hide pending API solidification}
+ * Apps will use the {@link android.backup.BackupManager} class rather than going through
+ * this Binder interface directly.
+ * 
+ * {@hide}
  */
 interface IBackupManager {
     /**
      * Tell the system service that the caller has made changes to its
      * data, and therefore needs to undergo a backup pass.
      */
-    oneway void dataChanged();
+    oneway void dataChanged(String packageName);
 }
diff --git a/core/java/android/util/CharsetUtils.java b/core/java/android/util/CharsetUtils.java
new file mode 100644
index 0000000..7553029
--- /dev/null
+++ b/core/java/android/util/CharsetUtils.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.os.Build;
+
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+
+/**
+ * A class containing utility methods related to character sets. This
+ * class is primarily useful for code that wishes to be vendor-aware
+ * in its interpretation of Japanese encoding names.
+ * 
+ * <p>As of this writing, the only vendor that is recognized by this
+ * class is Docomo (identified case-insensitively as {@code "docomo"}).</p>
+ * 
+ * <b>Note:</b> This class is hidden in Cupcake, with a plan to
+ * un-hide in Donut. This was done because the first deployment to use
+ * this code is based on Cupcake, but the API had to be introduced
+ * after the public API freeze for that release. The upshot is that
+ * only system applications can safely use this class until Donut is
+ * available.
+ * 
+ * @hide
+ */
+public final class CharsetUtils {
+    /**
+     * name of the vendor "Docomo". <b>Note:</b> This isn't a public
+     * constant, in order to keep this class from becoming a de facto
+     * reference list of vendor names.
+     */
+    private static final String VENDOR_DOCOMO = "docomo";
+    
+    /**
+     * This class is uninstantiable.
+     */
+    private CharsetUtils() {
+        // This space intentionally left blank.
+    }
+
+    /**
+     * Returns the name of the vendor-specific character set
+     * corresponding to the given original character set name and
+     * vendor. If there is no vendor-specific character set for the
+     * given name/vendor pair, this returns the original character set
+     * name. The vendor name is matched case-insensitively.
+     * 
+     * @param charsetName the base character set name
+     * @param vendor the vendor to specialize for
+     * @return the specialized character set name, or {@code charsetName} if
+     * there is no specialized name
+     */
+    public static String nameForVendor(String charsetName, String vendor) {
+        // TODO: Eventually, this may want to be table-driven.
+
+        if (vendor.equalsIgnoreCase(VENDOR_DOCOMO)
+                && isShiftJis(charsetName)) {
+            return "docomo-shift_jis-2007";
+        }
+
+        return charsetName;
+    }
+
+    /**
+     * Returns the name of the vendor-specific character set
+     * corresponding to the given original character set name and the
+     * default vendor (that is, the targeted vendor of the device this
+     * code is running on). This method merely calls through to
+     * {@link #nameForVendor(String,String)}, passing the default vendor
+     * as the second argument.
+     * 
+     * @param charsetName the base character set name
+     * @return the specialized character set name, or {@code charsetName} if
+     * there is no specialized name
+     */
+    public static String nameForDefaultVendor(String charsetName) {
+        return nameForVendor(charsetName, getDefaultVendor());
+    }
+
+    /**
+     * Returns the vendor-specific character set corresponding to the
+     * given original character set name and vendor. If there is no
+     * vendor-specific character set for the given name/vendor pair,
+     * this returns the character set corresponding to the original
+     * name. The vendor name is matched case-insensitively. This
+     * method merely calls {@code Charset.forName()} on a name
+     * transformed by a call to {@link #nameForVendor(String,String)}.
+     * 
+     * @param charsetName the base character set name
+     * @param vendor the vendor to specialize for
+     * @return the specialized character set, or the one corresponding
+     * directly to {@code charsetName} if there is no specialized
+     * variant
+     * @throws UnsupportedCharsetException thrown if the named character
+     * set is not supported by the system
+     * @throws IllegalCharsetNameException thrown if {@code charsetName}
+     * has invalid syntax
+     */
+    public static Charset charsetForVendor(String charsetName, String vendor)
+            throws UnsupportedCharsetException, IllegalCharsetNameException {
+        charsetName = nameForVendor(charsetName, vendor);
+        return Charset.forName(charsetName);
+    }
+    
+    /**
+     * Returns the vendor-specific character set corresponding to the
+     * given original character set name and default vendor (that is,
+     * the targeted vendor of the device this code is running on). 
+     * This method merely calls through to {@link
+     * #charsetForVendor(String,String)}, passing the default vendor
+     * as the second argument.
+     * 
+     * @param charsetName the base character set name
+     * @return the specialized character set, or the one corresponding
+     * directly to {@code charsetName} if there is no specialized
+     * variant
+     * @throws UnsupportedCharsetException thrown if the named character
+     * set is not supported by the system
+     * @throws IllegalCharsetNameException thrown if {@code charsetName}
+     * has invalid syntax
+     */
+    public static Charset charsetForVendor(String charsetName)
+            throws UnsupportedCharsetException, IllegalCharsetNameException {
+        return charsetForVendor(charsetName, getDefaultVendor());
+    }
+
+    /**
+     * Returns whether the given character set name indicates the Shift-JIS
+     * encoding.
+     * 
+     * @param charsetName the character set name
+     * @return {@code true} if the name corresponds to Shift-JIS or
+     * {@code false} if not
+     */
+    private static boolean isShiftJis(String charsetName) {
+        if (charsetName.length() != 9) {
+            // Bail quickly if the length doesn't match.
+            return false;
+        }
+
+        return charsetName.equalsIgnoreCase("shift_jis")
+            || charsetName.equalsIgnoreCase("shift-jis");
+    }
+
+    /**
+     * Gets the default vendor for this build.
+     * 
+     * @return the default vendor name
+     */
+    private static String getDefaultVendor() {
+        return Build.BRAND;
+    }
+}
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 2402660..0d55679 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -225,10 +225,12 @@
             mSize *= scale;
             mXPrecision *= scale;
             mYPrecision *= scale;
-            float[] history = mHistory;
-            int length = history.length;
-            for (int i = 0; i < length; i++) {
-                history[i] *= scale;
+            if (mHistory != null) {
+                float[] history = mHistory;
+                int length = history.length;
+                for (int i = 0; i < length; i++) {
+                    history[i] *= scale;
+                }
             }
         }
     }
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index e0f1bb4..92561ed 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -206,10 +206,15 @@
 
         int contentId = a.getResourceId(R.styleable.SlidingDrawer_content, 0);
         if (contentId == 0) {
-            throw new IllegalArgumentException("The handle attribute is required and must refer "
+            throw new IllegalArgumentException("The content attribute is required and must refer "
                     + "to a valid child.");
         }
 
+        if (handleId == contentId) {
+            throw new IllegalArgumentException("The content and handle attributes must refer "
+                    + "to different children.");
+        }
+
         mHandleId = handleId;
         mContentId = contentId;
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 77649f0..1218fe3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2360,6 +2360,12 @@
     public void updateKernelWakelocksLocked() {
         Map<String, KernelWakelockStats> m = readKernelWakelockStats();
         
+        if (m == null) {
+            // Not crashing might make board bringup easier.
+            Log.w(TAG, "Couldn't get kernel wake lock stats");
+            return;
+        }
+
         for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
             String name = ent.getKey();
             KernelWakelockStats kws = ent.getValue();
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index bbde8d5..9c63fd2 100644
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -155,6 +155,7 @@
         sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
     if (sGpsSuplInterface)
         sGpsSuplInterface->init(&sGpsSuplCallbacks);
+    return true;
 }
 
 static void android_location_GpsLocationProvider_disable(JNIEnv* env, jobject obj)
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index bb420a6e..c50ae94 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -35,6 +35,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -739,7 +740,7 @@
             throw new IllegalArgumentException("packageName and uid don't match packageName="
                     + packageName);
         }
-        if (callingUid != packageUid) {
+        if (callingUid != packageUid && Process.supportsProcesses()) {
             throw new IllegalArgumentException("packageName and uid don't match packageName="
                     + packageName);
         }
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index de14c33..0f95318 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -164,7 +164,7 @@
     
     // ----- IBackupManager binder interface -----
     
-    public void dataChanged() throws RemoteException {
+    public void dataChanged(String packageName) throws RemoteException {
         // Record that we need a backup pass for the caller.  Since multiple callers
         // may share a uid, we need to note all candidates within that uid and schedule
         // a backup pass for each of them.
@@ -173,10 +173,14 @@
         if (targets != null) {
             synchronized (mQueueLock) {
                 // Note that this client has made data changes that need to be backed up
-                // !!! add them to the set of pending packages
                 for (ServiceInfo service : targets) {
-                    if (mPendingBackups.add(service)) {
-                        // !!! TODO: write to the pending-backup journal file in case of crash
+                    // validate the caller-supplied package name against the known set of
+                    // packages associated with this uid
+                    if (service.packageName.equals(packageName)) {
+                        // add the caller to the set of pending backups
+                        if (mPendingBackups.add(service)) {
+                            // !!! TODO: write to the pending-backup journal file in case of crash
+                        }
                     }
                 }