Merge "Remove the drawables for the VerticalTextSpinner, since they're no longer needed here."
diff --git a/api/current.xml b/api/current.xml
index 1b5cd4d..9308be0 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -595,6 +595,17 @@
  visibility="public"
 >
 </field>
+<field name="KILL_BACKGROUND_PROCESSES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.KILL_BACKGROUND_PROCESSES&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MANAGE_ACCOUNTS"
  type="java.lang.String"
  transient="false"
@@ -899,7 +910,7 @@
  value="&quot;android.permission.RESTART_PACKAGES&quot;"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -17534,7 +17545,7 @@
 <exception name="SecurityException" type="java.lang.SecurityException">
 </exception>
 </method>
-<method name="restartPackage"
+<method name="killBackgroundProcesses"
  return="void"
  abstract="false"
  native="false"
@@ -17547,6 +17558,19 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="restartPackage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <field name="RECENT_WITH_EXCLUDED"
  type="int"
  transient="false"
@@ -74858,6 +74882,75 @@
 </exception>
 </method>
 </class>
+<class name="GeocoderParams"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getClientPackage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocale"
+ return="java.util.Locale"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="GpsSatellite"
  extends="java.lang.Object"
  abstract="false"
@@ -76157,6 +76250,62 @@
 >
 </field>
 </class>
+<interface name="LocationManager.GeocodeProvider"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getFromLocation"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="latitude" type="double">
+</parameter>
+<parameter name="longitude" type="double">
+</parameter>
+<parameter name="maxResults" type="int">
+</parameter>
+<parameter name="params" type="android.location.GeocoderParams">
+</parameter>
+<parameter name="addrs" type="java.util.List&lt;android.location.Address&gt;">
+</parameter>
+</method>
+<method name="getFromLocationName"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="locationName" type="java.lang.String">
+</parameter>
+<parameter name="lowerLeftLatitude" type="double">
+</parameter>
+<parameter name="lowerLeftLongitude" type="double">
+</parameter>
+<parameter name="upperRightLatitude" type="double">
+</parameter>
+<parameter name="upperRightLongitude" type="double">
+</parameter>
+<parameter name="maxResults" type="int">
+</parameter>
+<parameter name="params" type="android.location.GeocoderParams">
+</parameter>
+<parameter name="addrs" type="java.util.List&lt;android.location.Address&gt;">
+</parameter>
+</method>
+</interface>
 <class name="LocationProvider"
  extends="java.lang.Object"
  abstract="true"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7d07604..930ab65 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -891,6 +891,38 @@
     }
     
     /**
+     * @deprecated This is now just a wrapper for
+     * {@link #killBackgroundProcesses(String)}; the previous behavior here
+     * is no longer available to applications because it allows them to
+     * break other applications by removing their alarms, stopping their
+     * services, etc.
+     */
+    @Deprecated
+    public void restartPackage(String packageName) {
+        killBackgroundProcesses(packageName);
+    }
+    
+    /**
+     * Have the system immediately kill all background processes associated
+     * with the given package.  This is the same as the kernel killing those
+     * processes to reclaim memory; the system will take care of restarting
+     * these processes in the future as needed.
+     * 
+     * <p>You must hold the permission
+     * {@link android.Manifest.permission#KILL_BACKGROUND_PROCESSES} to be able to
+     * call this method.
+     * 
+     * @param packageName The name of the package whose processes are to
+     * be killed.
+     */
+    public void killBackgroundProcesses(String packageName) {
+        try {
+            ActivityManagerNative.getDefault().killBackgroundProcesses(packageName);
+        } catch (RemoteException e) {
+        }
+    }
+    
+    /**
      * Have the system perform a force stop of everything associated with
      * the given application package.  All processes that share its uid
      * will be killed, all services it has running stopped, all activities
@@ -899,14 +931,18 @@
      * be stopped, notifications removed, etc.
      * 
      * <p>You must hold the permission
-     * {@link android.Manifest.permission#RESTART_PACKAGES} to be able to
+     * {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to
      * call this method.
      * 
      * @param packageName The name of the package to be stopped.
+     * 
+     * @hide This is not available to third party applications due to
+     * it allowing them to break other applications by stopping their
+     * services, removing their alarms, etc.
      */
-    public void restartPackage(String packageName) {
+    public void forceStopPackage(String packageName) {
         try {
-            ActivityManagerNative.getDefault().restartPackage(packageName);
+            ActivityManagerNative.getDefault().forceStopPackage(packageName);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 90f46dd..09b88ee 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1007,10 +1007,18 @@
             return true;
         }
 
-        case RESTART_PACKAGE_TRANSACTION: {
-            data.enforceInterface(IActivityManager.descriptor);            
+        case KILL_BACKGROUND_PROCESSES_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
             String packageName = data.readString();
-            restartPackage(packageName);
+            killBackgroundProcesses(packageName);
+            reply.writeNoException();
+            return true;
+        }
+        
+        case FORCE_STOP_PACKAGE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            String packageName = data.readString();
+            forceStopPackage(packageName);
             reply.writeNoException();
             return true;
         }
@@ -2388,12 +2396,23 @@
         reply.recycle();
     }
     
-    public void restartPackage(String packageName) throws RemoteException {
+    public void killBackgroundProcesses(String packageName) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(packageName);
-        mRemote.transact(RESTART_PACKAGE_TRANSACTION, data, reply, 0);
+        mRemote.transact(KILL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+    
+    public void forceStopPackage(String packageName) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeString(packageName);
+        mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ca6bfa7..016d465 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -216,7 +216,8 @@
     
     public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
     
-    public void restartPackage(final String packageName) throws RemoteException;
+    public void killBackgroundProcesses(final String packageName) throws RemoteException;
+    public void forceStopPackage(final String packageName) throws RemoteException;
     
     // Note: probably don't want to allow applications access to these.
     public void goingToSleep() throws RemoteException;
@@ -424,7 +425,7 @@
     int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+75;
     int GET_PROCESSES_IN_ERROR_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+76;
     int CLEAR_APP_DATA_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+77;
-    int RESTART_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
+    int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
     int KILL_PIDS_FOR_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79;
     int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80;
     int REPORT_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81;
@@ -448,4 +449,5 @@
     int START_ACTIVITY_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99;
     int OVERRIDE_PENDING_TRANSITION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+100;
     int HANDLE_APPLICATION_WTF_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+101;
+    int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
 }
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 76131fc..b0c3909 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -1118,6 +1118,11 @@
         if (action == MotionEvent.ACTION_DOWN) mSwipeTracker.clear();
         mSwipeTracker.addMovement(me);
 
+        // Ignore all motion events until a DOWN.
+        if (mAbortKey && action != MotionEvent.ACTION_DOWN) {
+            return true;
+        }
+
         if (mGestureDetector.onTouchEvent(me)) {
             showPreview(NOT_A_KEY);
             mHandler.removeMessages(MSG_REPEAT);
@@ -1150,9 +1155,14 @@
                         mKeys[keyIndex].codes[0] : 0);
                 if (mCurrentKey >= 0 && mKeys[mCurrentKey].repeatable) {
                     mRepeatKeyIndex = mCurrentKey;
-                    repeatKey();
                     Message msg = mHandler.obtainMessage(MSG_REPEAT);
                     mHandler.sendMessageDelayed(msg, REPEAT_START_DELAY);
+                    repeatKey();
+                    // Delivering the key could have caused an abort
+                    if (mAbortKey) {
+                        mRepeatKeyIndex = NOT_A_KEY;
+                        break;
+                    }
                 }
                 if (mCurrentKey != NOT_A_KEY) {
                     Message msg = mHandler.obtainMessage(MSG_LONGPRESS, me);
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
new file mode 100644
index 0000000..130cfef
--- /dev/null
+++ b/core/java/android/os/RecoverySystem.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2010 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.os;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import android.content.Context;
+import android.util.Log;
+
+import org.apache.harmony.security.asn1.BerInputStream;
+import org.apache.harmony.security.pkcs7.ContentInfo;
+import org.apache.harmony.security.pkcs7.SignedData;
+import org.apache.harmony.security.pkcs7.SignerInfo;
+import org.apache.harmony.security.provider.cert.X509CertImpl;
+
+/**
+ * RecoverySystem contains methods for interacting with the Android
+ * recovery system (the separate partition that can be used to install
+ * system updates, wipe user data, etc.)
+ *
+ * @pending
+ */
+public class RecoverySystem {
+    private static final String TAG = "RecoverySystem";
+
+    /**
+     * Default location of zip file containing public keys (X509
+     * certs) authorized to sign OTA updates.
+     */
+    private static final File DEFAULT_KEYSTORE =
+        new File("/system/etc/security/otacerts.zip");
+
+    /** Send progress to listeners no more often than this (in ms). */
+    private static final long PUBLISH_PROGRESS_INTERVAL_MS = 500;
+
+    /** Used to communicate with recovery.  See bootable/recovery/recovery.c. */
+    private static File RECOVERY_DIR = new File("/cache/recovery");
+    private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
+    private static File LOG_FILE = new File(RECOVERY_DIR, "log");
+
+    // Length limits for reading files.
+    private static int LOG_FILE_MAX_LENGTH = 8 * 1024;
+
+    /**
+     * Interface definition for a callback to be invoked regularly as
+     * verification proceeds.
+     */
+    public interface ProgressListener {
+        /**
+         * Called periodically as the verification progresses.
+         *
+         * @param progress  the approximate percentage of the
+         *        verification that has been completed, ranging from 0
+         *        to 100 (inclusive).
+         */
+        public void onProgress(int progress);
+    }
+
+    /** @return the set of certs that can be used to sign an OTA package. */
+    private static HashSet<Certificate> getTrustedCerts(File keystore)
+        throws IOException, GeneralSecurityException {
+        HashSet<Certificate> trusted = new HashSet<Certificate>();
+        if (keystore == null) {
+            keystore = DEFAULT_KEYSTORE;
+        }
+        ZipFile zip = new ZipFile(keystore);
+        try {
+            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+            Enumeration<? extends ZipEntry> entries = zip.entries();
+            while (entries.hasMoreElements()) {
+                ZipEntry entry = entries.nextElement();
+                trusted.add(cf.generateCertificate(zip.getInputStream(entry)));
+            }
+        } finally {
+            zip.close();
+        }
+        return trusted;
+    }
+
+    /**
+     * Verify the cryptographic signature of a system update package
+     * before installing it.  Note that the package is also verified
+     * separately by the installer once the device is rebooted into
+     * the recovery system.  This function will return only if the
+     * package was successfully verified; otherwise it will throw an
+     * exception.
+     *
+     * Verification of a package can take significant time, so this
+     * function should not be called from a UI thread.
+     *
+     * @param packageFile  the package to be verified
+     * @param listener     an object to receive periodic progress
+     * updates as verification proceeds.  May be null.
+     * @param deviceCertsZipFile  the zip file of certificates whose
+     * public keys we will accept.  Verification succeeds if the
+     * package is signed by the private key corresponding to any
+     * public key in this file.  May be null to use the system default
+     * file (currently "/system/etc/security/otacerts.zip").
+     *
+     * @throws IOException if there were any errors reading the
+     * package or certs files.
+     * @throws GeneralSecurityException if verification failed
+     */
+    public static void verifyPackage(File packageFile,
+                                     ProgressListener listener,
+                                     File deviceCertsZipFile)
+        throws IOException, GeneralSecurityException {
+        long fileLen = packageFile.length();
+
+        RandomAccessFile raf = new RandomAccessFile(packageFile, "r");
+        try {
+            int lastPercent = 0;
+            long lastPublishTime = System.currentTimeMillis();
+            if (listener != null) {
+                listener.onProgress(lastPercent);
+            }
+
+            raf.seek(fileLen - 6);
+            byte[] footer = new byte[6];
+            raf.readFully(footer);
+
+            if (footer[2] != (byte)0xff || footer[3] != (byte)0xff) {
+                throw new SignatureException("no signature in file (no footer)");
+            }
+
+            int commentSize = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8);
+            int signatureStart = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8);
+            Log.v(TAG, String.format("comment size %d; signature start %d",
+                                     commentSize, signatureStart));
+
+            byte[] eocd = new byte[commentSize + 22];
+            raf.seek(fileLen - (commentSize + 22));
+            raf.readFully(eocd);
+
+            // Check that we have found the start of the
+            // end-of-central-directory record.
+            if (eocd[0] != (byte)0x50 || eocd[1] != (byte)0x4b ||
+                eocd[2] != (byte)0x05 || eocd[3] != (byte)0x06) {
+                throw new SignatureException("no signature in file (bad footer)");
+            }
+
+            for (int i = 4; i < eocd.length-3; ++i) {
+                if (eocd[i  ] == (byte)0x50 && eocd[i+1] == (byte)0x4b &&
+                    eocd[i+2] == (byte)0x05 && eocd[i+3] == (byte)0x06) {
+                    throw new SignatureException("EOCD marker found after start of EOCD");
+                }
+            }
+
+            // The following code is largely copied from
+            // JarUtils.verifySignature().  We could just *call* that
+            // method here if that function didn't read the entire
+            // input (ie, the whole OTA package) into memory just to
+            // compute its message digest.
+
+            BerInputStream bis = new BerInputStream(
+                new ByteArrayInputStream(eocd, commentSize+22-signatureStart, signatureStart));
+            ContentInfo info = (ContentInfo)ContentInfo.ASN1.decode(bis);
+            SignedData signedData = info.getSignedData();
+            if (signedData == null) {
+                throw new IOException("signedData is null");
+            }
+            Collection encCerts = signedData.getCertificates();
+            if (encCerts.isEmpty()) {
+                throw new IOException("encCerts is empty");
+            }
+            // Take the first certificate from the signature (packages
+            // should contain only one).
+            Iterator it = encCerts.iterator();
+            X509Certificate cert = null;
+            if (it.hasNext()) {
+                cert = new X509CertImpl((org.apache.harmony.security.x509.Certificate)it.next());
+            } else {
+                throw new SignatureException("signature contains no certificates");
+            }
+
+            List sigInfos = signedData.getSignerInfos();
+            SignerInfo sigInfo;
+            if (!sigInfos.isEmpty()) {
+                sigInfo = (SignerInfo)sigInfos.get(0);
+            } else {
+                throw new IOException("no signer infos!");
+            }
+
+            // Check that the public key of the certificate contained
+            // in the package equals one of our trusted public keys.
+
+            HashSet<Certificate> trusted = getTrustedCerts(
+                deviceCertsZipFile == null ? DEFAULT_KEYSTORE : deviceCertsZipFile);
+
+            PublicKey signatureKey = cert.getPublicKey();
+            boolean verified = false;
+            for (Certificate c : trusted) {
+                if (c.getPublicKey().equals(signatureKey)) {
+                    verified = true;
+                    break;
+                }
+            }
+            if (!verified) {
+                throw new SignatureException("signature doesn't match any trusted key");
+            }
+
+            // The signature cert matches a trusted key.  Now verify that
+            // the digest in the cert matches the actual file data.
+
+            // The verifier in recovery *only* handles SHA1withRSA
+            // signatures.  SignApk.java always uses SHA1withRSA, no
+            // matter what the cert says to use.  Ignore
+            // cert.getSigAlgName(), and instead use whatever
+            // algorithm is used by the signature (which should be
+            // SHA1withRSA).
+
+            String da = sigInfo.getdigestAlgorithm();
+            String dea = sigInfo.getDigestEncryptionAlgorithm();
+            String alg = null;
+            if (da == null || dea == null) {
+                // fall back to the cert algorithm if the sig one
+                // doesn't look right.
+                alg = cert.getSigAlgName();
+            } else {
+                alg = da + "with" + dea;
+            }
+            Signature sig = Signature.getInstance(alg);
+            sig.initVerify(cert);
+
+            // The signature covers all of the OTA package except the
+            // archive comment and its 2-byte length.
+            long toRead = fileLen - commentSize - 2;
+            long soFar = 0;
+            raf.seek(0);
+            byte[] buffer = new byte[4096];
+            while (soFar < toRead) {
+                int size = buffer.length;
+                if (soFar + size > toRead) {
+                    size = (int)(toRead - soFar);
+                }
+                int read = raf.read(buffer, 0, size);
+                sig.update(buffer, 0, read);
+                soFar += read;
+
+                if (listener != null) {
+                    long now = System.currentTimeMillis();
+                    int p = (int)(soFar * 100 / toRead);
+                    if (p > lastPercent &&
+                        now - lastPublishTime > PUBLISH_PROGRESS_INTERVAL_MS) {
+                        lastPercent = p;
+                        lastPublishTime = now;
+                        listener.onProgress(lastPercent);
+                    }
+                }
+            }
+            if (listener != null) {
+                listener.onProgress(100);
+            }
+
+            if (!sig.verify(sigInfo.getEncryptedDigest())) {
+                throw new SignatureException("signature digest verification failed");
+            }
+        } finally {
+            raf.close();
+        }
+    }
+
+    /**
+     * Reboots the device in order to install the given update
+     * package.
+     * Requires the {@link android.Manifest.permission#REBOOT}
+     * and {@link android.Manifest.permission#ACCESS_CACHE_FILESYSTEM}
+     * permissions.
+     *
+     * @param context      the Context to use
+     * @param packageFile  the update package to install.  Currently
+     * must be on the /cache or /data partitions.
+     *
+     * @throws IOException  if writing the recovery command file
+     * fails, or if the reboot itself fails.
+     */
+    public static void installPackage(Context context, File packageFile)
+        throws IOException {
+        String filename = packageFile.getCanonicalPath();
+
+        if (filename.startsWith("/cache/")) {
+            filename = "CACHE:" + filename.substring(7);
+        } else if (filename.startsWith("/data/")) {
+            filename = "DATA:" + filename.substring(6);
+        } else {
+            throw new IllegalArgumentException(
+                "Must start with /cache or /data: " + filename);
+        }
+        Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
+        String arg = "--update_package=" + filename;
+        bootCommand(context, arg);
+    }
+
+    /**
+     * Reboots the device and wipes the user data partition.  This is
+     * sometimes called a "factory reset", which is something of a
+     * misnomer because the system partition is not restored to its
+     * factory state.
+     * Requires the {@link android.Manifest.permission#REBOOT}
+     * and {@link android.Manifest.permission#ACCESS_CACHE_FILESYSTEM}
+     * permissions.
+     *
+     * @param context  the Context to use
+     *
+     * @throws IOException  if writing the recovery command file
+     * fails, or if the reboot itself fails.
+     */
+    public static void rebootWipeUserData(Context context)
+        throws IOException {
+        bootCommand(context, "--wipe_data");
+    }
+
+    /**
+     * Reboot into the recovery system to wipe the /data partition and toggle
+     * Encrypted File Systems on/off.
+     * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
+     * @throws IOException if something goes wrong.
+     *
+     * @hide
+     */
+    public static void rebootToggleEFS(Context context, boolean efsEnabled)
+        throws IOException {
+        if (efsEnabled) {
+            bootCommand(context, "--set_encrypted_filesystem=on");
+        } else {
+            bootCommand(context, "--set_encrypted_filesystem=off");
+        }
+    }
+
+    /**
+     * Reboot into the recovery system with the supplied argument.
+     * @param arg to pass to the recovery utility.
+     * @throws IOException if something goes wrong.
+     */
+    private static void bootCommand(Context context, String arg) throws IOException {
+        RECOVERY_DIR.mkdirs();  // In case we need it
+        COMMAND_FILE.delete();  // In case it's not writable
+        LOG_FILE.delete();
+
+        FileWriter command = new FileWriter(COMMAND_FILE);
+        try {
+            command.write(arg);
+            command.write("\n");
+        } finally {
+            command.close();
+        }
+
+        // Having written the command file, go ahead and reboot
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        pm.reboot("recovery");
+
+        throw new IOException("Reboot failed (no permissions?)");
+    }
+
+    /**
+     * Called after booting to process and remove recovery-related files.
+     * @return the log file from recovery, or null if none was found.
+     *
+     * @hide
+     */
+    public static String handleAftermath() {
+        // Record the tail of the LOG_FILE
+        String log = null;
+        try {
+            log = FileUtils.readTextFile(LOG_FILE, -LOG_FILE_MAX_LENGTH, "...\n");
+        } catch (FileNotFoundException e) {
+            Log.i(TAG, "No recovery log file");
+        } catch (IOException e) {
+            Log.e(TAG, "Error reading recovery log", e);
+        }
+
+        // Delete everything in RECOVERY_DIR
+        String[] names = RECOVERY_DIR.list();
+        for (int i = 0; names != null && i < names.length; i++) {
+            File f = new File(RECOVERY_DIR, names[i]);
+            if (!f.delete()) {
+                Log.e(TAG, "Can't delete: " + f);
+            } else {
+                Log.i(TAG, "Deleted: " + f);
+            }
+        }
+
+        return log;
+    }
+
+    private void RecoverySystem() { }  // Do not instantiate
+}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 248ed03..60d8e72 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1636,6 +1636,7 @@
             if (mDataChanged) return;
 
             if (mAdapter != null && mItemCount > 0 &&
+                    mClickMotionPosition != INVALID_POSITION &&
                     mClickMotionPosition < mAdapter.getCount() && sameWindow()) {
                 performItemClick(mChild, mClickMotionPosition, getAdapter().getItemId(
                         mClickMotionPosition));
diff --git a/core/java/com/android/internal/os/RecoverySystem.java b/core/java/com/android/internal/os/RecoverySystem.java
deleted file mode 100644
index 3aca683..0000000
--- a/core/java/com/android/internal/os/RecoverySystem.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2008 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 com.android.internal.os;
-
-import android.os.FileUtils;
-import android.os.Power;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Utility class for interacting with the Android recovery partition.
- * The recovery partition is a small standalone system which can perform
- * operations that are difficult while the main system is running, like
- * upgrading system software or reformatting the data partition.
- * Note that most of these operations must be run as root.
- *
- * @hide
- */
-public class RecoverySystem {
-    private static final String TAG = "RecoverySystem";  // for logging
-
-    // Used to communicate with recovery.  See commands/recovery/recovery.c.
-    private static File RECOVERY_DIR = new File("/cache/recovery");
-    private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
-    private static File LOG_FILE = new File(RECOVERY_DIR, "log");
-
-    // Length limits for reading files.
-    private static int LOG_FILE_MAX_LENGTH = 8 * 1024;
-
-    /**
-     * Reboot into the recovery system to install a system update.
-     * @param update package to install (must be in /cache or /data).
-     * @throws IOException if something goes wrong.
-     */
-    public static void rebootAndUpdate(File update) throws IOException {
-        String path = update.getCanonicalPath();
-        if (path.startsWith("/cache/")) {
-            path = "CACHE:" + path.substring(7);
-        } else if (path.startsWith("/data/")) {
-            path = "DATA:" + path.substring(6);
-        } else {
-            throw new IllegalArgumentException(
-                    "Must start with /cache or /data: " + path);
-        }
-        bootCommand("--update_package=" + path);
-    }
-
-    /**
-     * Reboot into the recovery system to wipe the /data partition.
-     * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
-     * @throws IOException if something goes wrong.
-     */
-    public static void rebootAndWipe() throws IOException {
-        bootCommand("--wipe_data");
-    }
-
-    /**
-     * Reboot into the recovery system to wipe the /data partition and toggle
-     * Encrypted File Systems on/off.
-     * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
-     * @throws IOException if something goes wrong.
-     * @hide
-     */
-    public static void rebootAndToggleEFS(boolean efsEnabled) throws IOException {
-        if (efsEnabled) {
-            bootCommand("--set_encrypted_filesystem=on");
-        } else {
-            bootCommand("--set_encrypted_filesystem=off");
-        }
-    }
-
-    /**
-     * Reboot into the recovery system with the supplied argument.
-     * @param arg to pass to the recovery utility.
-     * @throws IOException if something goes wrong.
-     */
-    private static void bootCommand(String arg) throws IOException {
-        RECOVERY_DIR.mkdirs();  // In case we need it
-        COMMAND_FILE.delete();  // In case it's not writable
-        LOG_FILE.delete();
-
-        FileWriter command = new FileWriter(COMMAND_FILE);
-        try {
-            command.write(arg);
-            command.write("\n");
-        } finally {
-            command.close();
-        }
-
-        // Having written the command file, go ahead and reboot
-        Power.reboot("recovery");
-        throw new IOException("Reboot failed (no permissions?)");
-    }
-
-    /**
-     * Called after booting to process and remove recovery-related files.
-     * @return the log file from recovery, or null if none was found.
-     */
-    public static String handleAftermath() {
-        // Record the tail of the LOG_FILE
-        String log = null;
-        try {
-            log = FileUtils.readTextFile(LOG_FILE, -LOG_FILE_MAX_LENGTH, "...\n");
-        } catch (FileNotFoundException e) {
-            Log.i(TAG, "No recovery log file");
-        } catch (IOException e) {
-            Log.e(TAG, "Error reading recovery log", e);
-        }
-
-        // Delete everything in RECOVERY_DIR
-        String[] names = RECOVERY_DIR.list();
-        for (int i = 0; names != null && i < names.length; i++) {
-            File f = new File(RECOVERY_DIR, names[i]);
-            if (!f.delete()) {
-                Log.e(TAG, "Can't delete: " + f);
-            } else {
-                Log.i(TAG, "Deleted: " + f);
-            }
-        }
-
-        return log;
-    }
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 72ad324..d202372 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -556,12 +556,30 @@
         android:label="@string/permlab_changeConfiguration"
         android:description="@string/permdesc_changeConfiguration" />
 
-    <!-- Allows an application to restart other applications. -->
+    <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
+        API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_restartPackages"
-        android:description="@string/permdesc_restartPackages" />
+        android:protectionLevel="normal"
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses" />
+
+    <!-- Allows an application to call
+        {@link android.app.ActivityManager#killBackgroundProcesses}. -->
+    <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="normal"
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses" />
+
+    <!-- Allows an application to call
+        {@link android.app.ActivityManager#forceStopPackage}.
+        @hide -->
+    <permission android:name="android.permission.FORCE_STOP_PACKAGES"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_forceStopPackages"
+        android:description="@string/permdesc_forceStopPackages" />
 
     <!-- Allows an application to retrieve state dump information from system
          services. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bc354c5..4fb476b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -462,10 +462,17 @@
         size.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_restartPackages">restart other applications</string>
+    <string name="permlab_killBackgroundProcesses">kill background processes</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_restartPackages">Allows an application to
-        forcibly restart other applications.</string>
+    <string name="permdesc_killBackgroundProcesses">Allows an application to
+        kill background processes of other applications, even if memory
+        isn\'t low.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_forceStopPackages">force stop other applications</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_forceStopPackages">Allows an application to
+        forcibly stop other applications.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_forceBack">force application to close</string>
diff --git a/location/java/android/location/Geocoder.java b/location/java/android/location/Geocoder.java
index 2ce1273..c325b1b 100644
--- a/location/java/android/location/Geocoder.java
+++ b/location/java/android/location/Geocoder.java
@@ -45,10 +45,7 @@
 public final class Geocoder {
     private static final String TAG = "Geocoder";
 
-    private String mLanguage;
-    private String mCountry;
-    private String mVariant;
-    private String mAppName;
+    private GeocoderParams mParams;
     private ILocationManager mService;
 
     /**
@@ -64,11 +61,7 @@
         if (locale == null) {
             throw new NullPointerException("locale == null");
         }
-        mLanguage = locale.getLanguage();
-        mCountry = locale.getCountry();
-        mVariant = locale.getVariant();
-        mAppName = context.getPackageName();
-
+        mParams = new GeocoderParams(context, locale);
         IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
         mService = ILocationManager.Stub.asInterface(b);
     }
@@ -119,7 +112,7 @@
         try {
             List<Address> results = new ArrayList<Address>();
             String ex =  mService.getFromLocation(latitude, longitude, maxResults,
-                mLanguage, mCountry, mVariant, mAppName, results);
+                mParams, results);
             if (ex != null) {
                 throw new IOException(ex);
             } else {
@@ -161,7 +154,7 @@
         try {
             List<Address> results = new ArrayList<Address>();
             String ex = mService.getFromLocationName(locationName,
-                0, 0, 0, 0, maxResults, mLanguage, mCountry, mVariant, mAppName, results);
+                0, 0, 0, 0, maxResults, mParams, results);
             if (ex != null) {
                 throw new IOException(ex);
             } else {
@@ -234,7 +227,7 @@
             ArrayList<Address> result = new ArrayList<Address>();
             String ex =  mService.getFromLocationName(locationName,
                 lowerLeftLatitude, lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
-                maxResults, mLanguage, mCountry, mVariant, mAppName, result);
+                maxResults, mParams, result);
             if (ex != null) {
                 throw new IOException(ex);
             } else {
diff --git a/location/java/android/location/GeocoderParams.aidl b/location/java/android/location/GeocoderParams.aidl
new file mode 100644
index 0000000..2484e20
--- /dev/null
+++ b/location/java/android/location/GeocoderParams.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010, 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.location;
+
+parcelable GeocoderParams;
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
new file mode 100644
index 0000000..8b8e63b
--- /dev/null
+++ b/location/java/android/location/GeocoderParams.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 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.location;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Locale;
+
+/**
+ * This class contains extra parameters to pass to an IGeocodeProvider
+ * implementation from the Geocoder class.  Currently this contains the
+ * language, country and variant information from the Geocoder's locale
+ * as well as the Geocoder client's package name for geocoder server
+ * logging.  This information is kept in a separate class to allow for
+ * future expansion of the IGeocodeProvider interface.
+ */
+public class GeocoderParams implements Parcelable {
+    private Locale mLocale;
+    private String mPackageName;
+
+    // used only for parcelling
+    private GeocoderParams() {
+    }
+
+    /**
+     * This object is only constructed by the Geocoder class
+     *
+     * @hide
+     */
+    public GeocoderParams(Context context, Locale locale) {
+        mLocale = locale;
+        mPackageName = context.getPackageName();
+    }
+
+    /**
+     * returns the Geocoder's locale
+     */
+    public Locale getLocale() {
+        return mLocale;
+    }
+
+    /**
+     * returns the package name of the Geocoder's client
+     */
+    public String getClientPackage() {
+        return mPackageName;
+    }
+
+    public static final Parcelable.Creator<GeocoderParams> CREATOR =
+        new Parcelable.Creator<GeocoderParams>() {
+        public GeocoderParams createFromParcel(Parcel in) {
+            GeocoderParams gp = new GeocoderParams();
+            String language = in.readString();
+            String country = in.readString();
+            String variant = in.readString();
+            gp.mLocale = new Locale(language, country, variant);
+            gp.mPackageName = in.readString();
+            return gp;
+        }
+
+        public GeocoderParams[] newArray(int size) {
+            return new GeocoderParams[size];
+        }
+    };
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mLocale.getLanguage());
+        parcel.writeString(mLocale.getCountry());
+        parcel.writeString(mLocale.getVariant());
+        parcel.writeString(mPackageName);
+    }
+}
diff --git a/location/java/android/location/IGeocodeProvider.aidl b/location/java/android/location/IGeocodeProvider.aidl
index e79e8d2..aaa70c7 100644
--- a/location/java/android/location/IGeocodeProvider.aidl
+++ b/location/java/android/location/IGeocodeProvider.aidl
@@ -17,6 +17,7 @@
 package android.location;
 
 import android.location.Address;
+import android.location.GeocoderParams;
 
 /**
  * An interface for location providers implementing the Geocoder services.
@@ -26,10 +27,10 @@
 interface IGeocodeProvider {
 
     String getFromLocation(double latitude, double longitude, int maxResults,
-        String language, String country, String variant, String appName, out List<Address> addrs);
+        in GeocoderParams params, out List<Address> addrs);
 
     String getFromLocationName(String locationName,
         double lowerLeftLatitude, double lowerLeftLongitude,
         double upperRightLatitude, double upperRightLongitude, int maxResults,
-        String language, String country, String variant, String appName, out List<Address> addrs);
+        in GeocoderParams params, out List<Address> addrs);
 }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index b6c59d6..1fac07c 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.location.Address;
+import android.location.GeocoderParams;
 import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
 import android.location.ILocationListener;
@@ -63,11 +64,11 @@
     void reportLocation(in Location location);
 
     String getFromLocation(double latitude, double longitude, int maxResults,
-        String language, String country, String variant, String appName, out List<Address> addrs);
+        in GeocoderParams params, out List<Address> addrs);
     String getFromLocationName(String locationName,
         double lowerLeftLatitude, double lowerLeftLongitude,
         double upperRightLatitude, double upperRightLongitude, int maxResults,
-        String language, String country, String variant, String appName, out List<Address> addrs);
+        in GeocoderParams params, out List<Address> addrs);
 
     void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
         boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 94ced22..cbe10d9 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -105,6 +105,48 @@
      */
     public static final String KEY_LOCATION_CHANGED = "location";
 
+    public interface GeocodeProvider {
+        String getFromLocation(double latitude, double longitude, int maxResults,
+            GeocoderParams params, List<Address> addrs);
+
+        String getFromLocationName(String locationName,
+            double lowerLeftLatitude, double lowerLeftLongitude,
+            double upperRightLatitude, double upperRightLongitude, int maxResults,
+            GeocoderParams params, List<Address> addrs);
+    }
+
+    private static final class GeocodeProviderProxy extends IGeocodeProvider.Stub {
+        private GeocodeProvider mProvider;
+
+        GeocodeProviderProxy(GeocodeProvider provider) {
+            mProvider = provider;
+        }
+
+        /**
+         * This method is overridden to implement the
+         * {@link Geocoder#getFromLocation(double, double, int)} method.
+         * Classes implementing this method should not hold a reference to the params parameter.
+         */
+        public String getFromLocation(double latitude, double longitude, int maxResults,
+                GeocoderParams params, List<Address> addrs) {
+            return mProvider.getFromLocation(latitude, longitude, maxResults, params, addrs);
+        }
+
+        /**
+         * This method is overridden to implement the
+         * {@link Geocoder#getFromLocationName(String, int, double, double, double, double)} method.
+         * Classes implementing this method should not hold a reference to the params parameter.
+         */
+        public String getFromLocationName(String locationName,
+                double lowerLeftLatitude, double lowerLeftLongitude,
+                double upperRightLatitude, double upperRightLongitude, int maxResults,
+                GeocoderParams params, List<Address> addrs) {
+            return mProvider.getFromLocationName(locationName, lowerLeftLatitude,
+                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
+                    maxResults, params, addrs);
+        }
+    }
+
     // Map from LocationListeners to their associated ListenerTransport objects
     private HashMap<LocationListener,ListenerTransport> mListeners =
         new HashMap<LocationListener,ListenerTransport>();
@@ -1388,9 +1430,9 @@
      *
      * {@hide}
      */
-    public boolean installGeocodeProvider(IGeocodeProvider provider) {
+    public boolean installGeocodeProvider(GeocodeProvider provider) {
         try {
-            mService.installGeocodeProvider(provider);
+            mService.installGeocodeProvider(new GeocodeProviderProxy(provider));
             return true;
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in setGeocodeProvider: ", e);
diff --git a/preloaded-classes b/preloaded-classes
index c50b36e..ddcecc9 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -698,7 +698,6 @@
 com.ibm.icu4jni.text.DecimalFormat
 com.ibm.icu4jni.text.DecimalFormatSymbols
 com.ibm.icu4jni.text.NativeDecimalFormat$UNumberFormatAttribute
-com.ibm.icu4jni.text.NativeDecimalFormat$UNumberFormatSymbol
 com.ibm.icu4jni.text.RuleBasedCollator
 com.ibm.icu4jni.util.Resources$DefaultTimeZones
 dalvik.system.DexFile
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index 84f0068..4279e00 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -23,12 +23,11 @@
 import android.os.Build;
 import android.os.DropBoxManager;
 import android.os.FileUtils;
+import android.os.RecoverySystem;
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Log;
 
-import com.android.internal.os.RecoverySystem;
-
 import java.io.File;
 import java.io.IOException;
 
diff --git a/services/java/com/android/server/FallbackCheckinService.java b/services/java/com/android/server/FallbackCheckinService.java
index 1e5bc09..fc0ab69 100644
--- a/services/java/com/android/server/FallbackCheckinService.java
+++ b/services/java/com/android/server/FallbackCheckinService.java
@@ -21,11 +21,11 @@
 import android.os.Binder;
 import android.os.ICheckinService;
 import android.os.IParentalControlCallback;
+import android.os.RecoverySystem;
 import android.util.Log;
 
 import java.io.IOException;
 
-import com.android.internal.os.RecoverySystem;
 import com.google.android.net.ParentalControlState;
 
 /**
@@ -50,7 +50,7 @@
 
         // Save the android ID so the new system can get it erased.
         try {
-            RecoverySystem.rebootAndWipe();
+            RecoverySystem.rebootWipeUserData(mContext);
         } catch (IOException e) {
             Log.e(TAG, "Reboot for masterClear() failed", e);
         }
@@ -67,7 +67,7 @@
 
         // Save the android ID so the new system can get it erased.
         try {
-            RecoverySystem.rebootAndToggleEFS(efsEnabled);
+            RecoverySystem.rebootToggleEFS(mContext, efsEnabled);
         } catch (IOException e) {
             Log.e(TAG, "Reboot for toggle EFS failed", e);
         }
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index c17a3bc..406897d 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -37,6 +37,7 @@
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.location.Address;
+import android.location.GeocoderParams;
 import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
 import android.location.IGpsStatusProvider;
@@ -1655,11 +1656,11 @@
     // Geocoder
 
     public String getFromLocation(double latitude, double longitude, int maxResults,
-            String language, String country, String variant, String appName, List<Address> addrs) {
+            GeocoderParams params, List<Address> addrs) {
         if (mGeocodeProvider != null) {
             try {
-                return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, language, country,
-                        variant, appName,  addrs);
+                return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
+                        params, addrs);
             } catch (RemoteException e) {
                 Log.e(TAG, "getFromLocation failed", e);
                 mGeocodeProvider = null;
@@ -1672,13 +1673,13 @@
     public String getFromLocationName(String locationName,
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
-            String language, String country, String variant, String appName, List<Address> addrs) {
+            GeocoderParams params, List<Address> addrs) {
 
         if (mGeocodeProvider != null) {
             try {
                 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
                         lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
-                        maxResults, language, country, variant, appName, addrs);
+                        maxResults, params, addrs);
             } catch (RemoteException e) {
                 Log.e(TAG, "getFromLocationName failed", e);
                 mGeocodeProvider = null;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index bf436b6..7f12b6d 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1194,7 +1194,7 @@
                     int uid = msg.arg1;
                     boolean restart = (msg.arg2 == 1);
                     String pkg = (String) msg.obj;
-                    uninstallPackageLocked(pkg, uid, restart);
+                    forceStopPackageLocked(pkg, uid, restart);
                 }
             } break;
             }
@@ -2734,8 +2734,7 @@
                 // Whoops, need to restart this activity!
                 next.state = lastState;
                 mResumedActivity = lastResumedActivity;
-                if (Config.LOGD) Log.d(TAG,
-                        "Restarting because process died: " + next);
+                Log.i(TAG, "Restarting because process died: " + next);
                 if (!next.hasBeenLaunched) {
                     next.hasBeenLaunched = true;
                 } else {
@@ -4293,7 +4292,9 @@
         
         cleanUpActivityLocked(r, false);
 
-        if (r.app != null) {
+        final boolean hadApp = r.app != null;
+        
+        if (hadApp) {
             if (removeFromApp) {
                 int idx = r.app.activities.indexOf(r);
                 if (idx >= 0) {
@@ -4350,16 +4351,14 @@
 
         r.configChangeFlags = 0;
         
-        if (!mLRUActivities.remove(r)) {
+        if (!mLRUActivities.remove(r) && hadApp) {
             Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
         }
         
         return removedFromHistory;
     }
 
-    private static void removeHistoryRecordsForAppLocked(ArrayList list,
-                                                         ProcessRecord app)
-    {
+    private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
         int i = list.size();
         if (localLOGV) Log.v(
             TAG, "Removing app " + app + " from list " + list
@@ -4550,7 +4549,7 @@
                     scheduleAppGcsLocked();
                 }
             }
-        } else if (Config.LOGD) {
+        } else if (DEBUG_PROCESSES) {
             Log.d(TAG, "Received spurious death notification for thread "
                     + thread.asBinder());
         }
@@ -4852,7 +4851,7 @@
                         android.Manifest.permission.CLEAR_APP_USER_DATA,
                         pid, uid, -1)
                         == PackageManager.PERMISSION_GRANTED) {
-                    restartPackageLocked(packageName, pkgUid);
+                    forceStopPackageLocked(packageName, pkgUid);
                 } else {
                     throw new SecurityException(pid+" does not have permission:"+
                             android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
@@ -4877,13 +4876,15 @@
         return true;
     }
 
-    public void restartPackage(final String packageName) {
-        if (checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
-                != PackageManager.PERMISSION_GRANTED) {
-            String msg = "Permission Denial: restartPackage() from pid="
+    public void killBackgroundProcesses(final String packageName) {
+        if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
+                != PackageManager.PERMISSION_GRANTED &&
+                checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
+                        != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: killBackgroundProcesses() from pid="
                     + Binder.getCallingPid()
                     + ", uid=" + Binder.getCallingUid()
-                    + " requires " + android.Manifest.permission.RESTART_PACKAGES;
+                    + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
             Log.w(TAG, msg);
             throw new SecurityException(msg);
         }
@@ -4901,7 +4902,39 @@
                     Log.w(TAG, "Invalid packageName: " + packageName);
                     return;
                 }
-                restartPackageLocked(packageName, pkgUid);
+                killPackageProcessesLocked(packageName, pkgUid,
+                        SECONDARY_SERVER_ADJ, false);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
+    public void forceStopPackage(final String packageName) {
+        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: forceStopPackage() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = ActivityThread.getPackageManager();
+            int pkgUid = -1;
+            synchronized(this) {
+                try {
+                    pkgUid = pm.getPackageUid(packageName);
+                } catch (RemoteException e) {
+                }
+                if (pkgUid == -1) {
+                    Log.w(TAG, "Invalid packageName: " + packageName);
+                    return;
+                }
+                forceStopPackageLocked(packageName, pkgUid);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -5011,8 +5044,8 @@
         }
     }
 
-    private void restartPackageLocked(final String packageName, int uid) {
-        uninstallPackageLocked(packageName, uid, false);
+    private void forceStopPackageLocked(final String packageName, int uid) {
+        forceStopPackageLocked(packageName, uid, false);
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                 Uri.fromParts("package", packageName, null));
         intent.putExtra(Intent.EXTRA_UID, uid);
@@ -5021,13 +5054,41 @@
                 false, false, MY_PID, Process.SYSTEM_UID);
     }
     
-    private final void uninstallPackageLocked(String name, int uid,
-            boolean callerWillRestart) {
-        if (Config.LOGD) Log.d(TAG, "Uninstalling process " + name);
+    private final void killPackageProcessesLocked(String packageName, int uid,
+            int minOomAdj, boolean callerWillRestart) {
+        ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
 
+        // Remove all processes this package may have touched: all with the
+        // same UID (except for the system or root user), and all whose name
+        // matches the package name.
+        final String procNamePrefix = packageName + ":";
+        for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+            final int NA = apps.size();
+            for (int ia=0; ia<NA; ia++) {
+                ProcessRecord app = apps.valueAt(ia);
+                if (app.removed) {
+                    procs.add(app);
+                } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
+                        || app.processName.equals(packageName)
+                        || app.processName.startsWith(procNamePrefix)) {
+                    if (app.setAdj >= minOomAdj) {
+                        app.removed = true;
+                        procs.add(app);
+                    }
+                }
+            }
+        }
+        
+        int N = procs.size();
+        for (int i=0; i<N; i++) {
+            removeProcessLocked(procs.get(i), callerWillRestart);
+        }
+    }
+    
+    private final void forceStopPackageLocked(String name, int uid,
+            boolean callerWillRestart) {
         int i, N;
 
-        final String procNamePrefix = name + ":";
         if (uid < 0) {
             try {
                 uid = ActivityThread.getPackageManager().getPackageUid(name);
@@ -5035,6 +5096,8 @@
             }
         }
 
+        Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
+
         Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
         while (badApps.hasNext()) {
             SparseArray<Long> ba = badApps.next();
@@ -5043,37 +5106,12 @@
             }
         }
 
-        ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
-
-        // Remove all processes this package may have touched: all with the
-        // same UID (except for the system or root user), and all whose name
-        // matches the package name.
-        for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
-            final int NA = apps.size();
-            for (int ia=0; ia<NA; ia++) {
-                ProcessRecord app = apps.valueAt(ia);
-                if (app.removed) {
-                    procs.add(app);
-                } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
-                        || app.processName.equals(name)
-                        || app.processName.startsWith(procNamePrefix)) {
-                    app.removed = true;
-                    procs.add(app);
-                }
-            }
-        }
-
-        N = procs.size();
-        for (i=0; i<N; i++) {
-            removeProcessLocked(procs.get(i), callerWillRestart);
-        }
+        killPackageProcessesLocked(name, uid, -100, callerWillRestart);
         
         for (i=mHistory.size()-1; i>=0; i--) {
             HistoryRecord r = (HistoryRecord)mHistory.get(i);
             if (r.packageName.equals(name)) {
-                if (Config.LOGD) Log.d(
-                    TAG, "  Force finishing activity "
-                    + r.intent.getComponent().flattenToShortString());
+                Log.i(TAG, "  Force finishing activity " + r);
                 if (r.app != null) {
                     r.app.removed = true;
                 }
@@ -5085,6 +5123,7 @@
         ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
         for (ServiceRecord service : mServices.values()) {
             if (service.packageName.equals(name)) {
+                Log.i(TAG, "  Force stopping service " + service);
                 if (service.app != null) {
                     service.app.removed = true;
                 }
@@ -5104,7 +5143,7 @@
     private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
         final String name = app.processName;
         final int uid = app.info.uid;
-        if (Config.LOGD) Log.d(
+        if (DEBUG_PROCESSES) Log.d(
             TAG, "Force removing process " + app + " (" + name
             + "/" + uid + ")");
 
@@ -7861,7 +7900,7 @@
 
         synchronized(this) {
             int count = mHistory.size();
-            if (Config.LOGD) Log.d(
+            if (DEBUG_SWITCH) Log.d(
                 TAG, "Performing unhandledBack(): stack size = " + count);
             if (count > 1) {
                 final long origId = Binder.clearCallingIdentity();
@@ -8062,7 +8101,7 @@
             mDebugTransient = !persistent;
             if (packageName != null) {
                 final long origId = Binder.clearCallingIdentity();
-                uninstallPackageLocked(packageName, -1, false);
+                forceStopPackageLocked(packageName, -1, false);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -8686,8 +8725,7 @@
             for (int i=mHistory.size()-1; i>=0; i--) {
                 HistoryRecord r = (HistoryRecord)mHistory.get(i);
                 if (r.app == app) {
-                    if (Config.LOGD) Log.d(
-                        TAG, "  Force finishing activity "
+                    Log.w(TAG, "  Force finishing activity "
                         + r.intent.getComponent().flattenToShortString());
                     finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
                 }
@@ -11922,7 +11960,7 @@
                     String ssp;
                     if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
                         if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
-                            uninstallPackageLocked(ssp,
+                            forceStopPackageLocked(ssp,
                                     intent.getIntExtra(Intent.EXTRA_UID, -1), false);
                             AttributeCache ac = AttributeCache.instance();
                             if (ac != null) {
@@ -12890,7 +12928,7 @@
             }
 
             final long origId = Binder.clearCallingIdentity();
-            uninstallPackageLocked(ii.targetPackage, -1, true);
+            forceStopPackageLocked(ii.targetPackage, -1, true);
             ProcessRecord app = addAppLocked(ai);
             app.instrumentationClass = className;
             app.instrumentationInfo = ai;
@@ -12945,7 +12983,7 @@
         app.instrumentationProfileFile = null;
         app.instrumentationArguments = null;
 
-        uninstallPackageLocked(app.processName, -1, false);
+        forceStopPackageLocked(app.processName, -1, false);
     }
 
     public void finishInstrumentation(IApplicationThread target,