Merge change 4529 into donut

* changes:
  In the TTS service, read the default TTS settings from Settings.Secure.
diff --git a/Android.mk b/Android.mk
index 6e292a8..0e8793d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -70,10 +70,8 @@
 	core/java/android/app/IActivityPendingResult.aidl \
 	core/java/android/app/IActivityWatcher.aidl \
 	core/java/android/app/IAlarmManager.aidl \
-    core/java/android/app/IBackupAgent.aidl \
+        core/java/android/app/IBackupAgent.aidl \
 	core/java/android/app/IInstrumentationWatcher.aidl \
-	core/java/android/app/IIntentReceiver.aidl \
-	core/java/android/app/IIntentSender.aidl \
 	core/java/android/app/INotificationManager.aidl \
 	core/java/android/app/ISearchManager.aidl \
 	core/java/android/app/ISearchManagerCallback.aidl \
@@ -89,10 +87,12 @@
 	core/java/android/bluetooth/IBluetoothDevice.aidl \
 	core/java/android/bluetooth/IBluetoothDeviceCallback.aidl \
 	core/java/android/bluetooth/IBluetoothHeadset.aidl \
-    core/java/android/content/IContentService.aidl \
+        core/java/android/content/IContentService.aidl \
+	core/java/android/content/IIntentReceiver.aidl \
+	core/java/android/content/IIntentSender.aidl \
 	core/java/android/content/ISyncAdapter.aidl \
 	core/java/android/content/ISyncContext.aidl \
-    core/java/android/content/ISyncStatusObserver.aidl \
+        core/java/android/content/ISyncStatusObserver.aidl \
 	core/java/android/content/pm/IPackageDataObserver.aidl \
 	core/java/android/content/pm/IPackageDeleteObserver.aidl \
 	core/java/android/content/pm/IPackageInstallObserver.aidl \
@@ -198,6 +198,7 @@
 	frameworks/base/core/java/android/app/PendingIntent.aidl \
 	frameworks/base/core/java/android/content/ComponentName.aidl \
 	frameworks/base/core/java/android/content/Intent.aidl \
+	frameworks/base/core/java/android/content/IntentSender.aidl \
 	frameworks/base/core/java/android/content/SyncStats.aidl \
 	frameworks/base/core/java/android/content/res/Configuration.aidl \
 	frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \
diff --git a/api/current.xml b/api/current.xml
index f375257..4efc71f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -22948,6 +22948,17 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="getIntentSender"
+ return="android.content.IntentSender"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getService"
  return="android.app.PendingIntent"
  abstract="false"
@@ -29629,6 +29640,70 @@
 </parameter>
 </method>
 </interface>
+<interface name="IIntentReceiver"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.IInterface">
+</implements>
+<method name="performReceive"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="resultCode" type="int">
+</parameter>
+<parameter name="data" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<parameter name="ordered" type="boolean">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
+</interface>
+<interface name="IIntentSender"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.IInterface">
+</implements>
+<method name="send"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="resolvedType" type="java.lang.String">
+</parameter>
+<parameter name="finishedReceiver" type="android.content.IIntentReceiver">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
+</interface>
 <class name="Intent"
  extends="java.lang.Object"
  abstract="false"
@@ -30111,7 +30186,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="uri" type="java.lang.String">
@@ -30162,6 +30237,17 @@
 <parameter name="defaultValue" type="long">
 </parameter>
 </method>
+<method name="getPackage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getParcelableArrayExtra"
  return="android.os.Parcelable[]"
  abstract="false"
@@ -30361,6 +30447,23 @@
 <exception name="XmlPullParserException" type="org.xmlpull.v1.XmlPullParserException">
 </exception>
 </method>
+<method name="parseUri"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="java.lang.String">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+<exception name="URISyntaxException" type="java.net.URISyntaxException">
+</exception>
+</method>
 <method name="putExtra"
  return="android.content.Intent"
  abstract="false"
@@ -31034,6 +31137,19 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="setPackage"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="setType"
  return="android.content.Intent"
  abstract="false"
@@ -31054,9 +31170,22 @@
  synchronized="false"
  static="false"
  final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="toUri"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="flags" type="int">
+</parameter>
 </method>
 <method name="writeToParcel"
  return="void"
@@ -32425,6 +32554,17 @@
  visibility="public"
 >
 </field>
+<field name="FILL_IN_PACKAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_ACTIVITY_BROUGHT_TO_FRONT"
  type="int"
  transient="false"
@@ -32634,6 +32774,17 @@
  visibility="public"
 >
 </field>
+<field name="URI_INTENT_SCHEME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="Intent.FilterComparison"
  extends="java.lang.Object"
@@ -33648,6 +33799,190 @@
 </parameter>
 </constructor>
 </class>
+<class name="IntentSender"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="IntentSender"
+ type="android.content.IntentSender"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="target" type="android.content.IIntentSender">
+</parameter>
+</constructor>
+<constructor name="IntentSender"
+ type="android.content.IntentSender"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="target" type="android.os.IBinder">
+</parameter>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="readIntentSenderOrNullFromParcel"
+ return="android.content.IntentSender"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="in" type="android.os.Parcel">
+</parameter>
+</method>
+<method name="sendIntent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="code" type="int">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="onFinished" type="android.content.IntentSender.OnFinished">
+</parameter>
+<parameter name="handler" type="android.os.Handler">
+</parameter>
+<exception name="IntentSender.SendIntentException" type="android.content.IntentSender.SendIntentException">
+</exception>
+</method>
+<method name="writeIntentSenderOrNullToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sender" type="android.content.IntentSender">
+</parameter>
+<parameter name="out" type="android.os.Parcel">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" 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>
+<interface name="IntentSender.OnFinished"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSendFinished"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="IntentSender" type="android.content.IntentSender">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="resultCode" type="int">
+</parameter>
+<parameter name="resultData" type="java.lang.String">
+</parameter>
+<parameter name="resultExtras" type="android.os.Bundle">
+</parameter>
+</method>
+</interface>
+<class name="IntentSender.SendIntentException"
+ extends="android.util.AndroidException"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="IntentSender.SendIntentException"
+ type="android.content.IntentSender.SendIntentException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="IntentSender.SendIntentException"
+ type="android.content.IntentSender.SendIntentException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="IntentSender.SendIntentException"
+ type="android.content.IntentSender.SendIntentException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cause" type="java.lang.Exception">
+</parameter>
+</constructor>
+</class>
 <class name="MutableContextWrapper"
  extends="android.content.ContextWrapper"
  abstract="false"
@@ -36651,23 +36986,6 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
-<method name="resolveActivity"
- return="android.content.pm.ResolveInfo"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-<parameter name="packageName" type="java.lang.String">
-</parameter>
-</method>
 <method name="resolveContentProvider"
  return="android.content.pm.ProviderInfo"
  abstract="true"
@@ -115443,23 +115761,6 @@
 </parameter>
 <parameter name="flags" type="int">
 </parameter>
-<parameter name="packageName" type="java.lang.String">
-</parameter>
-</method>
-<method name="resolveActivity"
- return="android.content.pm.ResolveInfo"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
 </method>
 <method name="resolveContentProvider"
  return="android.content.pm.ProviderInfo"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7fb3449..51a8ed2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -23,6 +23,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IIntentSender;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -863,13 +864,24 @@
             final Integer dialogId = ids[i];
             Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId));
             if (dialogState != null) {
-                final Dialog dialog = onCreateDialog(dialogId);
-                dialog.onRestoreInstanceState(dialogState);
+                final Dialog dialog = createDialog(dialogId);
                 mManagedDialogs.put(dialogId, dialog);
+                onPrepareDialog(dialogId, dialog);
+                dialog.onRestoreInstanceState(dialogState);
             }
         }
     }
 
+    private Dialog createDialog(Integer dialogId) {
+        final Dialog dialog = onCreateDialog(dialogId);
+        if (dialog == null) {
+            throw new IllegalArgumentException("Activity#onCreateDialog did "
+                    + "not create a dialog for id " + dialogId);
+        }
+        dialog.dispatchOnCreate(null);
+        return dialog;
+    }
+
     private String savedDialogKeyFor(int key) {
         return SAVED_DIALOG_KEY_PREFIX + key;
     }
@@ -2418,12 +2430,7 @@
         }
         Dialog dialog = mManagedDialogs.get(id);
         if (dialog == null) {
-            dialog = onCreateDialog(id);
-            if (dialog == null) {
-                throw new IllegalArgumentException("Activity#onCreateDialog did "
-                        + "not create a dialog for id " + id);
-            }
-            dialog.dispatchOnCreate(null);
+            dialog = createDialog(id);
             mManagedDialogs.put(id, dialog);
         }
         
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3d3d7d5f..b6f855a2 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -17,9 +17,10 @@
 package android.app;
 
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IIntentSender;
+import android.content.IIntentReceiver;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3676594..477badb 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.IContentProvider;
 import android.content.Intent;
+import android.content.IIntentReceiver;
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index fc3cdcf..23daf12 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -32,6 +32,8 @@
 import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IIntentReceiver;
+import android.content.IntentSender;
 import android.content.ReceiverCallNotAllowedException;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
@@ -1517,14 +1519,16 @@
             // overall package (such as if it has multiple launcher entries).
             Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
             intentToResolve.addCategory(Intent.CATEGORY_INFO);
-            ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0, packageName);
+            intentToResolve.setPackage(packageName);
+            ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
 
             // Otherwise, try to find a main launcher activity.
             if (resolveInfo == null) {
                 // reuse the intent instance
                 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
                 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
-                resolveInfo = resolveActivity(intentToResolve, 0, packageName);
+                intentToResolve.setPackage(packageName);
+                resolveInfo = resolveActivity(intentToResolve, 0);
             }
             if (resolveInfo == null) {
                 return null;
@@ -1772,19 +1776,6 @@
         }
 
         @Override
-        public ResolveInfo resolveActivity(Intent intent, int flags, String packageName) {
-            try {
-                return mPM.resolveIntentForPackage(
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags,
-                    packageName);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
         public List<ResolveInfo> queryIntentActivities(Intent intent,
                 int flags) {
             try {
@@ -2357,11 +2348,20 @@
                 // Should never happen!
             }
         }
-        
+
         @Override
-        public void freeStorage(long idealStorageSize, PendingIntent opFinishedIntent) {
+        public void freeStorage(long freeStorageSize, PendingIntent pi) {
             try {
-                mPM.freeStorage(idealStorageSize, opFinishedIntent);
+                mPM.freeStorage(freeStorageSize, pi);
+            } catch (RemoteException e) {
+                // Should never happen!
+            }
+        }
+
+        @Override
+        public void freeStorageWithIntent(long freeStorageSize, IntentSender pi) {
+            try {
+                mPM.freeStorageWithIntent(freeStorageSize, pi);
             } catch (RemoteException e) {
                 // Should never happen!
             }
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 0c8f95d..6b17236 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -151,6 +151,11 @@
         public String exceptionClassName;
 
         /**
+         * Message stored in the exception.
+         */
+        public String exceptionMessage;
+
+        /**
          * File which the exception was thrown from.
          */
         public String throwFileName;
@@ -181,6 +186,7 @@
          */
         public CrashInfo(Parcel in) {
             exceptionClassName = in.readString();
+            exceptionMessage = in.readString();
             throwFileName = in.readString();
             throwClassName = in.readString();
             throwMethodName = in.readString();
@@ -192,6 +198,7 @@
          */
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeString(exceptionClassName);
+            dest.writeString(exceptionMessage);
             dest.writeString(throwFileName);
             dest.writeString(throwClassName);
             dest.writeString(throwMethodName);
@@ -203,6 +210,7 @@
          */
         public void dump(Printer pw, String prefix) {
             pw.println(prefix + "exceptionClassName: " + exceptionClassName);
+            pw.println(prefix + "exceptionMessage: " + exceptionMessage);
             pw.println(prefix + "throwFileName: " + throwFileName);
             pw.println(prefix + "throwClassName: " + throwClassName);
             pw.println(prefix + "throwMethodName: " + throwMethodName);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 6750d12..4b64c94 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IIntentReceiver;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ProviderInfo;
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 997bfdc..85c001c 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.app.IBackupAgent;
+import android.backup.BackupDataInput;
 import android.backup.BackupDataOutput;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -25,6 +26,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.io.IOException;
+
 /**
  * This is the central interface between an application and Android's
  * settings backup mechanism.
@@ -32,6 +35,8 @@
  * @hide pending API solidification
  */
 public abstract class BackupAgent extends ContextWrapper {
+    private static final String TAG = "BackupAgent";
+
     public BackupAgent() {
         super(null);
     }
@@ -77,8 +82,8 @@
      *                 file.  The application should record the final backup state
      *                 here after restoring its data from dataFd.
      */
-    public abstract void onRestore(ParcelFileDescriptor /* TODO: BackupDataInput */ data,
-            ParcelFileDescriptor newState);
+    public abstract void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
+            throws IOException;
 
 
     // ----- Core implementation -----
@@ -107,13 +112,11 @@
                 ParcelFileDescriptor newState) throws RemoteException {
             // !!! TODO - real implementation; for now just invoke the callbacks directly
             Log.v(TAG, "doBackup() invoked");
-            BackupDataOutput output = new BackupDataOutput(BackupAgent.this,
-                    data.getFileDescriptor());
+            BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
             try {
                 BackupAgent.this.onBackup(oldState, output, newState);
             } catch (RuntimeException ex) {
-                Log.d("BackupAgent", "onBackup ("
-                        + BackupAgent.this.getClass().getName() + ") threw", ex);
+                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw ex;
             }
         }
@@ -122,7 +125,16 @@
                 ParcelFileDescriptor newState) throws RemoteException {
             // !!! TODO - real implementation; for now just invoke the callbacks directly
             Log.v(TAG, "doRestore() invoked");
-            BackupAgent.this.onRestore(data, newState);
+            BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
+            try {
+                BackupAgent.this.onRestore(input, newState);
+            } catch (IOException ex) {
+                Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                throw new RuntimeException(ex);
+            } catch (RuntimeException ex) {
+                Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                throw ex;
+            }
         }
     }
 }
diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java
index bf5cb5d..89becf4 100644
--- a/core/java/android/app/FullBackupAgent.java
+++ b/core/java/android/app/FullBackupAgent.java
@@ -1,5 +1,6 @@
 package android.app;
 
+import android.backup.BackupDataInput;
 import android.backup.BackupDataOutput;
 import android.backup.FileBackupHelper;
 import android.os.ParcelFileDescriptor;
@@ -52,6 +53,6 @@
     }
 
     @Override
-    public void onRestore(ParcelFileDescriptor data, ParcelFileDescriptor newState) {
+    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) {
     }
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c948aec..66bc85b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -21,6 +21,8 @@
 import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IIntentSender;
+import android.content.IIntentReceiver;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index bca1fea..029c650 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IIntentReceiver;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ProviderInfo;
diff --git a/core/java/android/app/IIntentReceiver.aidl b/core/java/android/app/IIntentReceiver.aidl
deleted file mode 100755
index 5f5d0eb..0000000
--- a/core/java/android/app/IIntentReceiver.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-**
-** Copyright 2006, 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.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * System private API for dispatching intent broadcasts.  This is given to the
- * activity manager as part of registering for an intent broadcasts, and is
- * called when it receives intents.
- *
- * {@hide}
- */
-oneway interface IIntentReceiver {
-    void performReceive(in Intent intent, int resultCode,
-                        String data, in Bundle extras, boolean ordered);
-}
-
diff --git a/core/java/android/app/IIntentSender.aidl b/core/java/android/app/IIntentSender.aidl
deleted file mode 100644
index 53e135a..0000000
--- a/core/java/android/app/IIntentSender.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/* //device/java/android/android/app/IActivityPendingResult.aidl
-**
-** Copyright 2007, 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.app;
-
-import android.app.IIntentReceiver;
-import android.content.Intent;
-
-/** @hide */
-interface IIntentSender {
-    int send(int code, in Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver);
-}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index cb660c7..f9c38f9 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -18,6 +18,9 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
+import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.Handler;
@@ -105,7 +108,7 @@
         public CanceledException(Exception cause) {
             super(cause);
         }
-    };
+    }
 
     /**
      * Callback interface for discovering when a send operation has
@@ -270,6 +273,21 @@
         return null;
     }
 
+    private class IntentSenderWrapper extends IntentSender {
+        protected IntentSenderWrapper(IIntentSender target) {
+            super(target);
+        }
+    }
+    /**
+     * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
+     *
+     * @return Returns a IntentSender object that wraps the sender of PendingIntent
+     *
+     */
+    public IntentSender getIntentSender() {
+        return new IntentSenderWrapper(mTarget);
+    }
+
     /**
      * Cancel a currently active PendingIntent.  Only the original application
      * owning an PendingIntent can cancel it.
diff --git a/core/java/android/backup/BackupDataInputStream.java b/core/java/android/backup/BackupDataInputStream.java
index 52b1675..b705c4c 100644
--- a/core/java/android/backup/BackupDataInputStream.java
+++ b/core/java/android/backup/BackupDataInputStream.java
@@ -16,6 +16,8 @@
 
 package android.backup;
 
+import android.util.Log;
+
 import java.io.InputStream;
 import java.io.IOException;
 
diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java
index 1348d81..a6d5bec 100644
--- a/core/java/android/backup/BackupDataOutput.java
+++ b/core/java/android/backup/BackupDataOutput.java
@@ -24,13 +24,11 @@
 /** @hide */
 public class BackupDataOutput {
     int mBackupWriter;
-    private Context mContext;
 
     public static final int OP_UPDATE = 1;
     public static final int OP_DELETE = 2;
 
-    public BackupDataOutput(Context context, FileDescriptor fd) {
-        mContext = context;
+    public BackupDataOutput(FileDescriptor fd) {
         if (fd == null) throw new NullPointerException();
         mBackupWriter = ctor(fd);
         if (mBackupWriter == 0) {
diff --git a/core/java/android/backup/FileRestoreHelper.java b/core/java/android/backup/FileRestoreHelper.java
new file mode 100644
index 0000000..b7e3625
--- /dev/null
+++ b/core/java/android/backup/FileRestoreHelper.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.Log;
+
+import java.io.File;
+
+/** @hide */
+public class FileRestoreHelper extends RestoreHelperBase implements RestoreHelper {
+    private static final String TAG = "FileRestoreHelper";
+
+    File mFilesDir;
+
+    public FileRestoreHelper(Context context) {
+        super(context);
+        mFilesDir = context.getFilesDir();
+    }
+
+    public void restoreEntity(BackupDataInputStream data) {
+        Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); // TODO: turn this off before ship
+        File f = new File(mFilesDir, data.getKey());
+        writeFile(f, data);
+    }
+}
+
diff --git a/core/java/android/backup/RestoreHelper.java b/core/java/android/backup/RestoreHelper.java
index ee8bedd..ac7d8ee 100644
--- a/core/java/android/backup/RestoreHelper.java
+++ b/core/java/android/backup/RestoreHelper.java
@@ -26,6 +26,6 @@
      * Do not close the <code>data</code> stream.  Do not read more than
      * <code>dataSize</code> bytes from <code>data</code>.
      */
-    public void performRestore(BackupDataInputStream data);
+    public void restoreEntity(BackupDataInputStream data);
 }
 
diff --git a/core/java/android/backup/RestoreHelperBase.java b/core/java/android/backup/RestoreHelperBase.java
new file mode 100644
index 0000000..894c9af
--- /dev/null
+++ b/core/java/android/backup/RestoreHelperBase.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.Log;
+
+import java.io.InputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+class RestoreHelperBase {
+    private static final String TAG = "RestoreHelperBase";
+    private static final int BUF_SIZE = 8 * 1024;
+
+    Context mContext;
+    byte[] mBuf = new byte[BUF_SIZE];
+    boolean mExceptionLogged;
+    
+    RestoreHelperBase(Context context) {
+        mContext = context;
+    }
+
+    void writeFile(File f, InputStream in) {
+        boolean success = false;
+        FileOutputStream out = null;
+        try {
+            // Create the enclosing directory.
+            File parent = f.getParentFile();
+            parent.mkdirs();
+
+            // Copy the file.
+            int sum = 0;
+            out = new FileOutputStream(f);
+            byte[] buf = mBuf;
+            int amt;
+            while ((amt = in.read(buf)) > 0) {
+                out.write(buf, 0, amt);
+                sum += amt;
+            }
+
+            // TODO: Set the permissions of the file.
+
+            // We're done
+            success = true;
+            out = null;
+        } catch (IOException ex) {
+            // Bail on this entity.  Only log one exception per helper object.
+            if (!mExceptionLogged) {
+                Log.e(TAG, "Failed restoring file '" + f + "' for app '"
+                    + mContext.getPackageName() + '\'', ex);
+                mExceptionLogged = true;
+            }
+        }
+        finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException ex) {
+                }
+            }
+            if (!success) {
+                // Something didn't work out, delete the file
+                f.delete();
+            }
+        }
+    }
+}
+
+
diff --git a/core/java/android/backup/RestoreHelperDispatcher.java b/core/java/android/backup/RestoreHelperDispatcher.java
index cbfefdc..5928914 100644
--- a/core/java/android/backup/RestoreHelperDispatcher.java
+++ b/core/java/android/backup/RestoreHelperDispatcher.java
@@ -16,20 +16,27 @@
 
 package android.backup;
 
+import android.util.Log;
+
 import java.io.IOException;
 import java.util.HashMap;
 
 /** @hide */
 public class RestoreHelperDispatcher {
-    HashMap<String,RestoreHelper> mHelpers;
+    private static final String TAG = "RestoreHelperDispatcher";
+
+    HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
 
     public void addHelper(String keyPrefix, RestoreHelper helper) {
         mHelpers.put(keyPrefix, helper);
     }
 
     public void dispatch(BackupDataInput input) throws IOException {
+        boolean alreadyComplained = false;
+
         BackupDataInputStream stream = new BackupDataInputStream(input);
         while (input.readNextHeader()) {
+
             String rawKey = input.getKey();
             int pos = rawKey.indexOf(':');
             if (pos > 0) {
@@ -38,7 +45,17 @@
                 if (helper != null) {
                     stream.dataSize = input.getDataSize();
                     stream.key = rawKey.substring(pos+1);
-                    helper.performRestore(stream);
+                    helper.restoreEntity(stream);
+                } else {
+                    if (!alreadyComplained) {
+                        Log.w(TAG, "Couldn't find helper for: '" + rawKey + "'");
+                        alreadyComplained = true;
+                    }
+                }
+            } else {
+                if (!alreadyComplained) {
+                    Log.w(TAG, "Entity with no prefix: '" + rawKey + "'");
+                    alreadyComplained = true;
                 }
             }
             input.skipEntityData(); // In case they didn't consume the data.
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
new file mode 100755
index 0000000..443db2d
--- /dev/null
+++ b/core/java/android/content/IIntentReceiver.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 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.content;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * System private API for dispatching intent broadcasts.  This is given to the
+ * activity manager as part of registering for an intent broadcasts, and is
+ * called when it receives intents.
+ *
+ * {@hide}
+ */
+oneway interface IIntentReceiver {
+    void performReceive(in Intent intent, int resultCode,
+                        String data, in Bundle extras, boolean ordered);
+}
+
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
new file mode 100644
index 0000000..b7da472
--- /dev/null
+++ b/core/java/android/content/IIntentSender.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2006 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.content;
+
+import android.content.IIntentReceiver;
+import android.content.Intent;
+
+/** @hide */
+interface IIntentSender {
+    int send(int code, in Intent intent, String resolvedType,
+            IIntentReceiver finishedReceiver);
+}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 24262f5..17fcb91 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -240,35 +240,35 @@
  *
  *         &lt;activity class=".NotesList" android:label="@string/title_notes_list"&gt;
  *             &lt;intent-filter&gt;
- *                 &lt;action android:value="android.intent.action.MAIN" /&gt;
- *                 &lt;category android:value="android.intent.category.LAUNCHER" /&gt;
+ *                 &lt;action android:name="android.intent.action.MAIN" /&gt;
+ *                 &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
  *             &lt;/intent-filter&gt;
  *             &lt;intent-filter&gt;
- *                 &lt;action android:value="android.intent.action.VIEW" /&gt;
- *                 &lt;action android:value="android.intent.action.EDIT" /&gt;
- *                 &lt;action android:value="android.intent.action.PICK" /&gt;
- *                 &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- *                 &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
+ *                 &lt;action android:name="android.intent.action.VIEW" /&gt;
+ *                 &lt;action android:name="android.intent.action.EDIT" /&gt;
+ *                 &lt;action android:name="android.intent.action.PICK" /&gt;
+ *                 &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ *                 &lt;data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
  *             &lt;/intent-filter&gt;
  *             &lt;intent-filter&gt;
- *                 &lt;action android:value="android.intent.action.GET_CONTENT" /&gt;
- *                 &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- *                 &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
+ *                 &lt;action android:name="android.intent.action.GET_CONTENT" /&gt;
+ *                 &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ *                 &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
  *             &lt;/intent-filter&gt;
  *         &lt;/activity&gt;
  *
  *         &lt;activity class=".NoteEditor" android:label="@string/title_note"&gt;
  *             &lt;intent-filter android:label="@string/resolve_edit"&gt;
- *                 &lt;action android:value="android.intent.action.VIEW" /&gt;
- *                 &lt;action android:value="android.intent.action.EDIT" /&gt;
- *                 &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- *                 &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
+ *                 &lt;action android:name="android.intent.action.VIEW" /&gt;
+ *                 &lt;action android:name="android.intent.action.EDIT" /&gt;
+ *                 &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ *                 &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
  *             &lt;/intent-filter&gt;
  *
  *             &lt;intent-filter&gt;
- *                 &lt;action android:value="android.intent.action.INSERT" /&gt;
- *                 &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- *                 &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
+ *                 &lt;action android:name="android.intent.action.INSERT" /&gt;
+ *                 &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ *                 &lt;data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
  *             &lt;/intent-filter&gt;
  *
  *         &lt;/activity&gt;
@@ -276,11 +276,11 @@
  *         &lt;activity class=".TitleEditor" android:label="@string/title_edit_title"
  *                 android:theme="@android:style/Theme.Dialog"&gt;
  *             &lt;intent-filter android:label="@string/resolve_title"&gt;
- *                 &lt;action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /&gt;
- *                 &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- *                 &lt;category android:value="android.intent.category.ALTERNATIVE" /&gt;
- *                 &lt;category android:value="android.intent.category.SELECTED_ALTERNATIVE" /&gt;
- *                 &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
+ *                 &lt;action android:name="<i>com.android.notepad.action.EDIT_TITLE</i>" /&gt;
+ *                 &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ *                 &lt;category android:name="android.intent.category.ALTERNATIVE" /&gt;
+ *                 &lt;category android:name="android.intent.category.SELECTED_ALTERNATIVE" /&gt;
+ *                 &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
  *             &lt;/intent-filter&gt;
  *         &lt;/activity&gt;
  *
@@ -294,8 +294,8 @@
  * <ol>
  * <li><pre>
  * &lt;intent-filter&gt;
- *     &lt;action android:value="{@link #ACTION_MAIN android.intent.action.MAIN}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /&gt;
+ *     &lt;action android:name="{@link #ACTION_MAIN android.intent.action.MAIN}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /&gt;
  * &lt;/intent-filter&gt;</pre>
  * <p>This provides a top-level entry into the NotePad application: the standard
  * MAIN action is a main entry point (not requiring any other information in
@@ -303,11 +303,11 @@
  * listed in the application launcher.</p>
  * <li><pre>
  * &lt;intent-filter&gt;
- *     &lt;action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /&gt;
- *     &lt;action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
- *     &lt;action android:value="{@link #ACTION_PICK android.intent.action.PICK}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- *     &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
+ *     &lt;action android:name="{@link #ACTION_VIEW android.intent.action.VIEW}" /&gt;
+ *     &lt;action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
+ *     &lt;action android:name="{@link #ACTION_PICK android.intent.action.PICK}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
+ *     &lt;data mimeType:name="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
  * &lt;/intent-filter&gt;</pre>
  * <p>This declares the things that the activity can do on a directory of
  * notes.  The type being supported is given with the &lt;type&gt; tag, where
@@ -322,9 +322,9 @@
  * activity when its component name is not explicitly specified.</p>
  * <li><pre>
  * &lt;intent-filter&gt;
- *     &lt;action android:value="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- *     &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
+ *     &lt;action android:name="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
+ *     &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
  * &lt;/intent-filter&gt;</pre>
  * <p>This filter describes the ability return to the caller a note selected by
  * the user without needing to know where it came from.  The data type
@@ -371,10 +371,10 @@
  * <ol>
  * <li><pre>
  * &lt;intent-filter android:label="@string/resolve_edit"&gt;
- *     &lt;action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /&gt;
- *     &lt;action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- *     &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
+ *     &lt;action android:name="{@link #ACTION_VIEW android.intent.action.VIEW}" /&gt;
+ *     &lt;action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
+ *     &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
  * &lt;/intent-filter&gt;</pre>
  * <p>The first, primary, purpose of this activity is to let the user interact
  * with a single note, as decribed by the MIME type
@@ -384,9 +384,9 @@
  * specifying its component.</p>
  * <li><pre>
  * &lt;intent-filter&gt;
- *     &lt;action android:value="{@link #ACTION_INSERT android.intent.action.INSERT}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- *     &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
+ *     &lt;action android:name="{@link #ACTION_INSERT android.intent.action.INSERT}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
+ *     &lt;data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
  * &lt;/intent-filter&gt;</pre>
  * <p>The secondary use of this activity is to insert a new note entry into
  * an existing directory of notes.  This is used when the user creates a new
@@ -422,11 +422,11 @@
  *
  * <pre>
  * &lt;intent-filter android:label="@string/resolve_title"&gt;
- *     &lt;action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /&gt;
- *     &lt;category android:value="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /&gt;
- *     &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
+ *     &lt;action android:name="<i>com.android.notepad.action.EDIT_TITLE</i>" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /&gt;
+ *     &lt;category android:name="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /&gt;
+ *     &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
  * &lt;/intent-filter&gt;</pre>
  *
  * <p>In the single intent template here, we
@@ -509,8 +509,8 @@
  *     <li> {@link #ACTION_UID_REMOVED}
  *     <li> {@link #ACTION_BATTERY_CHANGED}
  *     <li> {@link #ACTION_POWER_CONNECTED}
- *     <li> {@link #ACTION_POWER_DISCONNECTED} 
- *     <li> {@link #ACTION_SHUTDOWN} 
+ *     <li> {@link #ACTION_POWER_DISCONNECTED}
+ *     <li> {@link #ACTION_SHUTDOWN}
  * </ul>
  *
  * <h3>Standard Categories</h3>
@@ -1277,10 +1277,10 @@
      * This is intended for applications that wish to register specifically to this notification.
      * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to
      * stay active to receive this notification.  This action can be used to implement actions
-     * that wait until power is available to trigger. 
+     * that wait until power is available to trigger.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";    
+    public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
     /**
      * Broadcast Action:  Device is shutting down.
      * This is broadcast when the device is being shut down (completely turned
@@ -1289,7 +1289,7 @@
      * to handle this, since the forground activity will be paused as well.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";    
+    public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
     /**
      * Broadcast Action:  Indicates low memory condition on the device
      */
@@ -1791,23 +1791,23 @@
      * delivered.
      */
     public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
-    
+
     /**
      * Used as a parcelable extra field in {@link #ACTION_APP_ERROR}, containing
      * the bug report.
-     * 
+     *
      * @hide
      */
     public static final String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
 
     /**
-     * Used as a string extra field when sending an intent to PackageInstaller to install a 
+     * Used as a string extra field when sending an intent to PackageInstaller to install a
      * package. Specifies the installer package name; this package will receive the
      * {@link #ACTION_APP_ERROR} intent.
-     * 
+     *
      * @hide
      */
-    public static final String EXTRA_INSTALLER_PACKAGE_NAME 
+    public static final String EXTRA_INSTALLER_PACKAGE_NAME
             = "android.intent.extra.INSTALLER_PACKAGE_NAME";
 
     // ---------------------------------------------------------------------
@@ -2040,10 +2040,25 @@
     public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000;
 
     // ---------------------------------------------------------------------
+    // ---------------------------------------------------------------------
+    // toUri() and parseUri() options.
+
+    /**
+     * Flag for use with {@link #toUri} and {@link #parseUri}: the URI string
+     * always has the "intent:" scheme.  This syntax can be used when you want
+     * to later disambiguate between URIs that are intended to describe an
+     * Intent vs. all others that should be treated as raw URIs.  When used
+     * with {@link #parseUri}, any other scheme will result in a generic
+     * VIEW action for that raw URI.
+     */
+    public static final int URI_INTENT_SCHEME = 1<<0;
+    
+    // ---------------------------------------------------------------------
 
     private String mAction;
     private Uri mData;
     private String mType;
+    private String mPackage;
     private ComponentName mComponent;
     private int mFlags;
     private HashSet<String> mCategories;
@@ -2064,6 +2079,7 @@
         this.mAction = o.mAction;
         this.mData = o.mData;
         this.mType = o.mType;
+        this.mPackage = o.mPackage;
         this.mComponent = o.mComponent;
         this.mFlags = o.mFlags;
         if (o.mCategories != null) {
@@ -2083,6 +2099,7 @@
         this.mAction = o.mAction;
         this.mData = o.mData;
         this.mType = o.mType;
+        this.mPackage = o.mPackage;
         this.mComponent = o.mComponent;
         if (o.mCategories != null) {
             this.mCategories = new HashSet<String>(o.mCategories);
@@ -2183,23 +2200,50 @@
     }
 
     /**
+     * Call {@link #parseUri} with 0 flags.
+     * @deprecated Use {@link #parseUri} instead.
+     */
+    @Deprecated
+    public static Intent getIntent(String uri) throws URISyntaxException {
+        return parseUri(uri, 0);
+    }
+    
+    /**
      * Create an intent from a URI.  This URI may encode the action,
-     * category, and other intent fields, if it was returned by toURI().  If
-     * the Intent was not generate by toURI(), its data will be the entire URI
-     * and its action will be ACTION_VIEW.
+     * category, and other intent fields, if it was returned by
+     * {@link #toUri}..  If the Intent was not generate by toUri(), its data
+     * will be the entire URI and its action will be ACTION_VIEW.
      *
      * <p>The URI given here must not be relative -- that is, it must include
      * the scheme and full path.
      *
      * @param uri The URI to turn into an Intent.
+     * @param flags Additional processing flags.  Either 0 or
      *
      * @return Intent The newly created Intent object.
      *
-     * @see #toURI
+     * @throws URISyntaxException Throws URISyntaxError if the basic URI syntax
+     * it bad (as parsed by the Uri class) or the Intent data within the
+     * URI is invalid.
+     * 
+     * @see #toUri
      */
-    public static Intent getIntent(String uri) throws URISyntaxException {
+    public static Intent parseUri(String uri, int flags) throws URISyntaxException {
         int i = 0;
         try {
+            // Validate intent scheme for if requested.
+            if ((flags&URI_INTENT_SCHEME) != 0) {
+                if (!uri.startsWith("intent:")) {
+                    Intent intent = new Intent(ACTION_VIEW);
+                    try {
+                        intent.setData(Uri.parse(uri));
+                    } catch (IllegalArgumentException e) {
+                        throw new URISyntaxException(uri, e.getMessage());
+                    }
+                    return intent;
+                }
+            }
+            
             // simple case
             i = uri.lastIndexOf("#");
             if (i == -1) return new Intent(ACTION_VIEW, Uri.parse(uri));
@@ -2211,16 +2255,15 @@
             Intent intent = new Intent(ACTION_VIEW);
 
             // fetch data part, if present
-            if (i > 0) {
-                intent.mData = Uri.parse(uri.substring(0, i));
-            }
+            String data = i >= 0 ? uri.substring(0, i) : null;
+            String scheme = null;
             i += "#Intent;".length();
 
             // loop over contents of Intent, all name=value;
             while (!uri.startsWith("end", i)) {
                 int eq = uri.indexOf('=', i);
                 int semi = uri.indexOf(';', eq);
-                String value = uri.substring(eq + 1, semi);
+                String value = Uri.decode(uri.substring(eq + 1, semi));
 
                 // action
                 if (uri.startsWith("action=", i)) {
@@ -2242,15 +2285,24 @@
                     intent.mFlags = Integer.decode(value).intValue();
                 }
 
+                // package
+                else if (uri.startsWith("package=", i)) {
+                    intent.mPackage = value;
+                }
+
                 // component
                 else if (uri.startsWith("component=", i)) {
                     intent.mComponent = ComponentName.unflattenFromString(value);
                 }
 
+                // scheme
+                else if (uri.startsWith("scheme=", i)) {
+                    scheme = value;
+                }
+
                 // extra
                 else {
                     String key = Uri.decode(uri.substring(i + 2, eq));
-                    value = Uri.decode(value);
                     // create Bundle if it doesn't already exist
                     if (intent.mExtras == null) intent.mExtras = new Bundle();
                     Bundle b = intent.mExtras;
@@ -2271,6 +2323,23 @@
                 i = semi + 1;
             }
 
+            if (data != null) {
+                if (data.startsWith("intent:")) {
+                    data = data.substring(7);
+                    if (scheme != null) {
+                        data = scheme + ':' + data;
+                    }
+                }
+                
+                if (data.length() > 0) {
+                    try {
+                        intent.mData = Uri.parse(data);
+                    } catch (IllegalArgumentException e) {
+                        throw new URISyntaxException(uri, e.getMessage());
+                    }
+                }
+            }
+            
             return intent;
 
         } catch (IndexOutOfBoundsException e) {
@@ -3084,6 +3153,20 @@
     }
 
     /**
+     * Retrieve the application package name this Intent is limited to.  When
+     * resolving an Intent, if non-null this limits the resolution to only
+     * components in the given application package.
+     *
+     * @return The name of the application package for the Intent.
+     *
+     * @see #resolveActivity
+     * @see #setPackage
+     */
+    public String getPackage() {
+        return mPackage;
+    }
+
+    /**
      * Retrieve the concrete component associated with the intent.  When receiving
      * an intent, this is the component that was found to best handle it (that is,
      * yourself) and will always be non-null; in all other cases it will be
@@ -3118,6 +3201,9 @@
      * <p>If {@link #addCategory} has added any categories, the activity must
      * handle ALL of the categories specified.
      *
+     * <p>If {@link #getPackage} is non-NULL, only activity components in
+     * that application package will be considered.
+     *
      * <p>If there are no activities that satisfy all of these conditions, a
      * null string is returned.
      *
@@ -3239,7 +3325,7 @@
      * only specify a type and not data, for example to indicate the type of
      * data to return.  This method automatically clears any data that was
      * previously set by {@link #setData}.
-     * 
+     *
      * <p><em>Note: MIME type matching in the Android framework is
      * case-sensitive, unlike formal RFC MIME types.  As a result,
      * you should always write your MIME types with lower case letters,
@@ -4089,6 +4175,27 @@
     }
 
     /**
+     * (Usually optional) Set an explicit application package name that limits
+     * the components this Intent will resolve to.  If left to the default
+     * value of null, all components in all applications will considered.
+     * If non-null, the Intent can only match the components in the given
+     * application package.
+     *
+     * @param packageName The name of the application package to handle the
+     * intent, or null to allow any application package.
+     *
+     * @return Returns the same Intent object, for chaining multiple calls
+     * into a single statement.
+     *
+     * @see #getPackage
+     * @see #resolveActivity
+     */
+    public Intent setPackage(String packageName) {
+        mPackage = packageName;
+        return this;
+    }
+
+    /**
      * (Usually optional) Explicitly set the component to handle the intent.
      * If left with the default value of null, the system will determine the
      * appropriate class to use based on the other fields (action, data,
@@ -4200,6 +4307,12 @@
     public static final int FILL_IN_COMPONENT = 1<<3;
 
     /**
+     * Use with {@link #fillIn} to allow the current package value to be
+     * overwritten, even if it is already set.
+     */
+    public static final int FILL_IN_PACKAGE = 1<<4;
+
+    /**
      * Copy the contents of <var>other</var> in to this object, but only
      * where fields are not defined by this object.  For purposes of a field
      * being defined, the following pieces of data in the Intent are
@@ -4210,14 +4323,15 @@
      * <li> data URI and MIME type, as set by {@link #setData(Uri)},
      * {@link #setType(String)}, or {@link #setDataAndType(Uri, String)}.
      * <li> categories, as set by {@link #addCategory}.
+     * <li> package, as set by {@link #setPackage}.
      * <li> component, as set by {@link #setComponent(ComponentName)} or
      * related methods.
      * <li> each top-level name in the associated extras.
      * </ul>
      *
      * <p>In addition, you can use the {@link #FILL_IN_ACTION},
-     * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and
-     * {@link #FILL_IN_COMPONENT} to override the restriction where the
+     * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
+     * and {@link #FILL_IN_COMPONENT} to override the restriction where the
      * corresponding field will not be replaced if it is already set.
      *
      * <p>For example, consider Intent A with {data="foo", categories="bar"}
@@ -4233,32 +4347,39 @@
      * @param flags Options to control which fields can be filled in.
      *
      * @return Returns a bit mask of {@link #FILL_IN_ACTION},
-     * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and
-     * {@link #FILL_IN_COMPONENT} indicating which fields were changed.
+     * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
+     * and {@link #FILL_IN_COMPONENT} indicating which fields were changed.
      */
     public int fillIn(Intent other, int flags) {
         int changes = 0;
-        if ((mAction == null && other.mAction == null)
-                || (flags&FILL_IN_ACTION) != 0) {
+        if (other.mAction != null
+                && (mAction == null || (flags&FILL_IN_ACTION) != 0)) {
             mAction = other.mAction;
             changes |= FILL_IN_ACTION;
         }
-        if ((mData == null && mType == null &&
-                (other.mData != null || other.mType != null))
-                || (flags&FILL_IN_DATA) != 0) {
+        if ((other.mData != null || other.mType != null)
+                && ((mData == null && mType == null)
+                        || (flags&FILL_IN_DATA) != 0)) {
             mData = other.mData;
             mType = other.mType;
             changes |= FILL_IN_DATA;
         }
-        if ((mCategories == null && other.mCategories == null)
-                || (flags&FILL_IN_CATEGORIES) != 0) {
+        if (other.mCategories != null
+                && (mCategories == null || (flags&FILL_IN_CATEGORIES) != 0)) {
             if (other.mCategories != null) {
                 mCategories = new HashSet<String>(other.mCategories);
             }
             changes |= FILL_IN_CATEGORIES;
         }
-        if ((mComponent == null && other.mComponent == null)
-                || (flags&FILL_IN_COMPONENT) != 0) {
+        if (other.mPackage != null
+                && (mPackage == null || (flags&FILL_IN_PACKAGE) != 0)) {
+            mPackage = other.mPackage;
+            changes |= FILL_IN_PACKAGE;
+        }
+        // Component is special: it can -only- be set if explicitly allowed,
+        // since otherwise the sender could force the intent somewhere the
+        // originator didn't intend.
+        if (other.mComponent != null && (flags&FILL_IN_COMPONENT) != 0) {
             mComponent = other.mComponent;
             changes |= FILL_IN_COMPONENT;
         }
@@ -4373,6 +4494,17 @@
                 }
             }
         }
+        if (mPackage != other.mPackage) {
+            if (mPackage != null) {
+                if (!mPackage.equals(other.mPackage)) {
+                    return false;
+                }
+            } else {
+                if (!other.mPackage.equals(mPackage)) {
+                    return false;
+                }
+            }
+        }
         if (mComponent != other.mComponent) {
             if (mComponent != null) {
                 if (!mComponent.equals(other.mComponent)) {
@@ -4418,6 +4550,9 @@
         if (mType != null) {
             code += mType.hashCode();
         }
+        if (mPackage != null) {
+            code += mPackage.hashCode();
+        }
         if (mComponent != null) {
             code += mComponent.hashCode();
         }
@@ -4444,7 +4579,7 @@
         toShortString(b, comp, extras);
         return b.toString();
     }
-    
+
     /** @hide */
     public void toShortString(StringBuilder b, boolean comp, boolean extras) {
         boolean first = true;
@@ -4488,6 +4623,13 @@
             first = false;
             b.append("flg=0x").append(Integer.toHexString(mFlags));
         }
+        if (mPackage != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("pkg=").append(mPackage);
+        }
         if (comp && mComponent != null) {
             if (!first) {
                 b.append(' ');
@@ -4504,28 +4646,87 @@
         }
     }
 
+    /**
+     * Call {@link #toUri} with 0 flags.
+     * @deprecated Use {@link #toUri} instead.
+     */
+    @Deprecated
     public String toURI() {
+        return toUri(0);
+    }
+
+    /**
+     * Convert this Intent into a String holding a URI representation of it.
+     * The returned URI string has been properly URI encoded, so it can be
+     * used with {@link Uri#parse Uri.parse(String)}.  The URI contains the
+     * Intent's data as the base URI, with an additional fragment describing
+     * the action, categories, type, flags, package, component, and extras.
+     * 
+     * <p>You can convert the returned string back to an Intent with
+     * {@link #getIntent}.
+     * 
+     * @param flags Additional operating flags.  Either 0 or
+     * {@link #URI_INTENT_SCHEME}.
+     * 
+     * @return Returns a URI encoding URI string describing the entire contents
+     * of the Intent.
+     */
+    public String toUri(int flags) {
         StringBuilder uri = new StringBuilder(128);
-        if (mData != null) uri.append(mData.toString());
+        String scheme = null;
+        if (mData != null) {
+            String data = mData.toString();
+            if ((flags&URI_INTENT_SCHEME) != 0) {
+                final int N = data.length();
+                for (int i=0; i<N; i++) {
+                    char c = data.charAt(i);
+                    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+                            || c == '.' || c == '-') {
+                        continue;
+                    }
+                    if (c == ':' && i > 0) {
+                        // Valid scheme.
+                        scheme = data.substring(0, i);
+                        uri.append("intent:");
+                        data = data.substring(i+1);
+                        break;
+                    }
+                    
+                    // No scheme.
+                    break;
+                }
+            }
+            uri.append(data);
+            
+        } else if ((flags&URI_INTENT_SCHEME) != 0) {
+            uri.append("intent:");
+        }
 
         uri.append("#Intent;");
 
+        if (scheme != null) {
+            uri.append("scheme=").append(scheme).append(';');
+        }
         if (mAction != null) {
-            uri.append("action=").append(mAction).append(';');
+            uri.append("action=").append(Uri.encode(mAction)).append(';');
         }
         if (mCategories != null) {
             for (String category : mCategories) {
-                uri.append("category=").append(category).append(';');
+                uri.append("category=").append(Uri.encode(category)).append(';');
             }
         }
         if (mType != null) {
-            uri.append("type=").append(mType).append(';');
+            uri.append("type=").append(Uri.encode(mType, "/")).append(';');
         }
         if (mFlags != 0) {
             uri.append("launchFlags=0x").append(Integer.toHexString(mFlags)).append(';');
         }
+        if (mPackage != null) {
+            uri.append("package=").append(Uri.encode(mPackage)).append(';');
+        }
         if (mComponent != null) {
-            uri.append("component=").append(mComponent.flattenToShortString()).append(';');
+            uri.append("component=").append(Uri.encode(
+                    mComponent.flattenToShortString(), "/")).append(';');
         }
         if (mExtras != null) {
             for (String key : mExtras.keySet()) {
@@ -4567,6 +4768,7 @@
         Uri.writeToParcel(out, mData);
         out.writeString(mType);
         out.writeInt(mFlags);
+        out.writeString(mPackage);
         ComponentName.writeToParcel(mComponent, out);
 
         if (mCategories != null) {
@@ -4600,6 +4802,7 @@
         mData = Uri.CREATOR.createFromParcel(in);
         mType = in.readString();
         mFlags = in.readInt();
+        mPackage = in.readString();
         mComponent = ComponentName.readFromParcel(in);
 
         int N = in.readInt();
diff --git a/core/java/android/content/IntentSender.aidl b/core/java/android/content/IntentSender.aidl
new file mode 100644
index 0000000..741bc8c
--- /dev/null
+++ b/core/java/android/content/IntentSender.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.content;
+
+parcelable IntentSender;
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
new file mode 100644
index 0000000..4da49d9
--- /dev/null
+++ b/core/java/android/content/IntentSender.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2006 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.content;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IIntentSender;
+import android.content.IIntentReceiver;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AndroidException;
+
+
+/**
+ * A description of an Intent and target action to perform with it.
+ * The returned object can be
+ * handed to other applications so that they can perform the action you
+ * described on your behalf at a later time.
+ *
+ * <p>By giving a IntentSender to another application,
+ * you are granting it the right to perform the operation you have specified
+ * as if the other application was yourself (with the same permissions and
+ * identity).  As such, you should be careful about how you build the IntentSender:
+ * often, for example, the base Intent you supply will have the component
+ * name explicitly set to one of your own components, to ensure it is ultimately
+ * sent there and nowhere else.
+ *
+ * <p>A IntentSender itself is simply a reference to a token maintained by
+ * the system describing the original data used to retrieve it.  This means
+ * that, even if its owning application's process is killed, the
+ * IntentSender itself will remain usable from other processes that
+ * have been given it.  If the creating application later re-retrieves the
+ * same kind of IntentSender (same operation, same Intent action, data,
+ * categories, and components, and same flags), it will receive a IntentSender
+ * representing the same token if that is still valid.
+ *
+ */
+public class IntentSender implements Parcelable {
+    private final IIntentSender mTarget;
+
+    /**
+     * Exception thrown when trying to send through a PendingIntent that
+     * has been canceled or is otherwise no longer able to execute the request.
+     */
+    public static class SendIntentException extends AndroidException {
+        public SendIntentException() {
+        }
+
+        public SendIntentException(String name) {
+            super(name);
+        }
+
+        public SendIntentException(Exception cause) {
+            super(cause);
+        }
+    }
+
+    /**
+     * Callback interface for discovering when a send operation has
+     * completed.  Primarily for use with a IntentSender that is
+     * performing a broadcast, this provides the same information as
+     * calling {@link Context#sendOrderedBroadcast(Intent, String,
+     * android.content.BroadcastReceiver, Handler, int, String, Bundle)
+     * Context.sendBroadcast()} with a final BroadcastReceiver.
+     */
+    public interface OnFinished {
+        /**
+         * Called when a send operation as completed.
+         *
+         * @param IntentSender The IntentSender this operation was sent through.
+         * @param intent The original Intent that was sent.
+         * @param resultCode The final result code determined by the send.
+         * @param resultData The final data collected by a broadcast.
+         * @param resultExtras The final extras collected by a broadcast.
+         */
+        void onSendFinished(IntentSender IntentSender, Intent intent,
+                int resultCode, String resultData, Bundle resultExtras);
+    }
+
+    private static class FinishedDispatcher extends IIntentReceiver.Stub
+            implements Runnable {
+        private final IntentSender mIntentSender;
+        private final OnFinished mWho;
+        private final Handler mHandler;
+        private Intent mIntent;
+        private int mResultCode;
+        private String mResultData;
+        private Bundle mResultExtras;
+        FinishedDispatcher(IntentSender pi, OnFinished who, Handler handler) {
+            mIntentSender = pi;
+            mWho = who;
+            mHandler = handler;
+        }
+        public void performReceive(Intent intent, int resultCode,
+                String data, Bundle extras, boolean serialized) {
+            mIntent = intent;
+            mResultCode = resultCode;
+            mResultData = data;
+            mResultExtras = extras;
+            if (mHandler == null) {
+                run();
+            } else {
+                mHandler.post(this);
+            }
+        }
+        public void run() {
+            mWho.onSendFinished(mIntentSender, mIntent, mResultCode,
+                    mResultData, mResultExtras);
+        }
+    }
+
+    /**
+     * Perform the operation associated with this IntentSender, allowing the
+     * caller to specify information about the Intent to use and be notified
+     * when the send has completed.
+     *
+     * @param context The Context of the caller.  This may be null if
+     * <var>intent</var> is also null.
+     * @param code Result code to supply back to the IntentSender's target.
+     * @param intent Additional Intent data.  See {@link Intent#fillIn
+     * Intent.fillIn()} for information on how this is applied to the
+     * original Intent.  Use null to not modify the original Intent.
+     * @param onFinished The object to call back on when the send has
+     * completed, or null for no callback.
+     * @param handler Handler identifying the thread on which the callback
+     * should happen.  If null, the callback will happen from the thread
+     * pool of the process.
+     *
+     *
+     * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+     * is no longer allowing more intents to be sent through it.
+     */
+    public void sendIntent(Context context, int code, Intent intent,
+            OnFinished onFinished, Handler handler) throws SendIntentException {
+        try {
+            String resolvedType = intent != null ?
+                    intent.resolveTypeIfNeeded(context.getContentResolver())
+                    : null;
+            int res = mTarget.send(code, intent, resolvedType,
+                    onFinished != null
+                    ? new FinishedDispatcher(this, onFinished, handler)
+                    : null);
+            if (res < 0) {
+                throw new SendIntentException();
+            }
+        } catch (RemoteException e) {
+            throw new SendIntentException();
+        }
+    }
+
+    /**
+     * Comparison operator on two IntentSender objects, such that true
+     * is returned then they both represent the same operation from the
+     * same package.
+     */
+    @Override
+    public boolean equals(Object otherObj) {
+        if (otherObj instanceof IntentSender) {
+            return mTarget.asBinder().equals(((IntentSender)otherObj)
+                    .mTarget.asBinder());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return mTarget.asBinder().hashCode();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("IntentSender{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(": ");
+        sb.append(mTarget != null ? mTarget.asBinder() : null);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeStrongBinder(mTarget.asBinder());
+    }
+
+    public static final Parcelable.Creator<IntentSender> CREATOR
+            = new Parcelable.Creator<IntentSender>() {
+        public IntentSender createFromParcel(Parcel in) {
+            IBinder target = in.readStrongBinder();
+            return target != null ? new IntentSender(target) : null;
+        }
+
+        public IntentSender[] newArray(int size) {
+            return new IntentSender[size];
+        }
+    };
+
+    /**
+     * Convenience function for writing either a IntentSender or null pointer to
+     * a Parcel.  You must use this with {@link #readIntentSenderOrNullFromParcel}
+     * for later reading it.
+     *
+     * @param sender The IntentSender to write, or null.
+     * @param out Where to write the IntentSender.
+     */
+    public static void writeIntentSenderOrNullToParcel(IntentSender sender,
+            Parcel out) {
+        out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
+                : null);
+    }
+
+    /**
+     * Convenience function for reading either a Messenger or null pointer from
+     * a Parcel.  You must have previously written the Messenger with
+     * {@link #writeIntentSenderOrNullToParcel}.
+     *
+     * @param in The Parcel containing the written Messenger.
+     *
+     * @return Returns the Messenger read from the Parcel, or null if null had
+     * been written.
+     */
+    public static IntentSender readIntentSenderOrNullFromParcel(Parcel in) {
+        IBinder b = in.readStrongBinder();
+        return b != null ? new IntentSender(b) : null;
+    }
+
+    protected IntentSender(IIntentSender target) {
+        mTarget = target;
+    }
+
+    protected IntentSender(IBinder target) {
+        mTarget = IIntentSender.Stub.asInterface(target);
+    }
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 5f62248..5656b6b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -35,6 +35,7 @@
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
 import android.app.PendingIntent;
+import android.content.IntentSender;
 
 /**
  *  See {@link PackageManager} for documentation on most of the APIs
@@ -81,9 +82,6 @@
     
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags);
 
-    ResolveInfo resolveIntentForPackage(in Intent intent, String resolvedType, int flags,
-            String packageName);
-
     List<ResolveInfo> queryIntentActivities(in Intent intent, 
             String resolvedType, int flags);
 
@@ -243,6 +241,30 @@
      */
      void freeStorage(in long freeStorageSize,
              in PendingIntent opFinishedIntent);
+
+    /**
+     * Free storage by deleting LRU sorted list of cache files across
+     * all applications. If the currently available free storage
+     * on the device is greater than or equal to the requested
+     * free storage, no cache files are cleared. If the currently
+     * available storage on the device is less than the requested
+     * free storage, some or all of the cache files across
+     * all applications are deleted (based on last accessed time)
+     * to increase the free storage space on the device to
+     * the requested value. There is no guarantee that clearing all
+     * the cache files from all applications will clear up
+     * enough storage to achieve the desired value.
+     * @param freeStorageSize The number of bytes of storage to be
+     * freed by the system. Say if freeStorageSize is XX,
+     * and the current free storage is YY,
+     * if XX is less than YY, just return. if not free XX-YY number
+     * of bytes if possible.
+     * @param pi IntentSender call back used to
+     * notify when the operation is completed.May be null
+     * to indicate that no call back is desired.
+     */
+     void freeStorageWithIntent(in long freeStorageSize,
+             in IntentSender pi);
      
     /**
      * Delete all the cache files in an applications cache directory
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 65783917..f746a40 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
@@ -985,23 +986,6 @@
     public abstract ResolveInfo resolveActivity(Intent intent, int flags);
 
     /**
-     * Resolve the intent restricted to a package.
-     * {@see #resolveActivity}
-     *
-     * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
-     * @param flags Additional option flags.  The most important is
-     *                    MATCH_DEFAULT_ONLY, to limit the resolution to only
-     *                    those activities that support the CATEGORY_DEFAULT.
-     * @param packageName Restrict the intent resolution to this package.
-     *
-     * @return Returns a ResolveInfo containing the final activity intent that
-     *         was determined to be the best action.  Returns null if no
-     *         matching activity was found.
-     */
-    public abstract ResolveInfo resolveActivity(Intent intent, int flags, String packageName);
-
-    /**
      * Retrieve all activities that can be performed for the given intent.
      *
      * @param intent The desired intent as per resolveActivity().
@@ -1522,7 +1506,7 @@
      * @hide
      */
     public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer);
-    
+
     /**
      * Free storage by deleting LRU sorted list of cache files across
      * all applications. If the currently available free storage
@@ -1543,10 +1527,37 @@
      * @param opFinishedIntent PendingIntent call back used to
      * notify when the operation is completed.May be null
      * to indicate that no call back is desired.
+     *
+     * @deprecated
+     * @hide
+     */
+    @Deprecated
+    public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent);
+
+    /**
+     * Free storage by deleting LRU sorted list of cache files across
+     * all applications. If the currently available free storage
+     * on the device is greater than or equal to the requested
+     * free storage, no cache files are cleared. If the currently
+     * available storage on the device is less than the requested
+     * free storage, some or all of the cache files across
+     * all applications are deleted (based on last accessed time)
+     * to increase the free storage space on the device to
+     * the requested value. There is no guarantee that clearing all
+     * the cache files from all applications will clear up
+     * enough storage to achieve the desired value.
+     * @param freeStorageSize The number of bytes of storage to be
+     * freed by the system. Say if freeStorageSize is XX,
+     * and the current free storage is YY,
+     * if XX is less than YY, just return. if not free XX-YY number
+     * of bytes if possible.
+     * @param pi IntentSender call back used to
+     * notify when the operation is completed.May be null
+     * to indicate that no call back is desired.
      * 
      * @hide
      */
-    public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent);
+    public abstract void freeStorageWithIntent(long freeStorageSize, IntentSender pi);
 
     /**
      * Retrieve the size information for a package.
diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java
index 5353b53..6ea2528 100644
--- a/core/java/android/preference/PreferenceScreen.java
+++ b/core/java/android/preference/PreferenceScreen.java
@@ -22,6 +22,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.Adapter;
@@ -147,13 +148,20 @@
         ListView listView = new ListView(context);
         bind(listView);
 
-        Dialog dialog = mDialog = new Dialog(context, com.android.internal.R.style.Theme_NoTitleBar);
+        // Set the title bar if title is available, else no title bar
+        final CharSequence title = getTitle();
+        Dialog dialog = mDialog = new Dialog(context, !TextUtils.isEmpty(title)
+                ? com.android.internal.R.style.Theme_NoTitleBar
+                : com.android.internal.R.style.Theme);
         dialog.setContentView(listView);
+        if (!TextUtils.isEmpty(title)) {
+            dialog.setTitle(title);
+        }
         dialog.setOnDismissListener(this);
         if (state != null) {
             dialog.onRestoreInstanceState(state);
         }
-        
+
         // Add the screen to the list of preferences screens opened as dialogs
         getPreferenceManager().addPreferencesScreen(dialog);
         
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 585ce3d..8f1b0ee 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -633,15 +633,19 @@
                         mDropDownList.getAdapter().getCount() - 1)) {
                     // When the selection is at the top, we block the key
                     // event to prevent focus from moving.
-                    mDropDownList.hideSelector();
-                    mDropDownList.requestLayout();
+                    clearListSelection();
                     mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
                     mPopup.update();
                     return true;
+                } else {
+                    // WARNING: Please read the comment where mListSelectionHidden
+                    //          is declared
+                    mDropDownList.mListSelectionHidden = false;
                 }
+
                 consumed = mDropDownList.onKeyDown(keyCode, event);
-                if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed="
-                        + consumed);
+                if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed);
+
                 if (consumed) {
                     // If it handled the key event, then the user is
                     // navigating in the list, so we should put it in front.
@@ -784,9 +788,12 @@
      * it back.
      */
     public void clearListSelection() {
-        if (mDropDownList != null) {
-            mDropDownList.hideSelector();
-            mDropDownList.requestLayout();
+        final DropDownListView list = mDropDownList;
+        if (list != null) {
+            // WARNING: Please read the comment where mListSelectionHidden is declared
+            list.mListSelectionHidden = true;
+            list.hideSelector();
+            list.requestLayout();
         }
     }
     
@@ -1079,8 +1086,7 @@
             mPopup.showAsDropDown(getDropDownAnchorView(),
                     mDropDownHorizontalOffset, mDropDownVerticalOffset);
             mDropDownList.setSelection(ListView.INVALID_POSITION);
-            mDropDownList.hideSelector();
-            mDropDownList.requestFocus();
+            clearListSelection();
             post(mHideSelector);
         }
     }
@@ -1123,6 +1129,18 @@
             mDropDownList.setOnItemClickListener(mDropDownItemClickListener);
             mDropDownList.setFocusable(true);
             mDropDownList.setFocusableInTouchMode(true);
+            mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view,
+                        int position, long id) {
+
+                    if (position != -1) {
+                        mDropDownList.mListSelectionHidden = false;
+                    }
+                }
+
+                public void onNothingSelected(AdapterView<?> parent) {
+                }
+            });
 
             if (mItemSelectedListener != null) {
                 mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
@@ -1246,10 +1264,7 @@
 
     private class ListSelectorHider implements Runnable {
         public void run() {
-            if (mDropDownList != null) {
-                mDropDownList.hideSelector();
-                mDropDownList.requestLayout();
-            }
+            clearListSelection();
         }
     }
 
@@ -1276,6 +1291,36 @@
      * passed to the drop down; the list only looks focused.</p>
      */
     private static class DropDownListView extends ListView {
+        /*
+         * WARNING: This is a workaround for a touch mode issue.
+         *
+         * Touch mode is propagated lazily to windows. This causes problems in
+         * the following scenario:
+         * - Type something in the AutoCompleteTextView and get some results
+         * - Move down with the d-pad to select an item in the list
+         * - Move up with the d-pad until the selection disappears
+         * - Type more text in the AutoCompleteTextView *using the soft keyboard*
+         *   and get new results; you are now in touch mode
+         * - The selection comes back on the first item in the list, even though
+         *   the list is supposed to be in touch mode
+         *
+         * Using the soft keyboard triggers the touch mode change but that change
+         * is propagated to our window only after the first list layout, therefore
+         * after the list attempts to resurrect the selection.
+         *
+         * The trick to work around this issue is to pretend the list is in touch
+         * mode when we know that the selection should not appear, that is when
+         * we know the user moved the selection away from the list.
+         *
+         * This boolean is set to true whenever we explicitely hide the list's
+         * selection and reset to false whenver we know the user moved the
+         * selection back to the list.
+         *
+         * When this boolean is true, isInTouchMode() returns true, otherwise it
+         * returns super.isInTouchMode().
+         */
+        private boolean mListSelectionHidden;
+
         /**
          * <p>Creates a new list view wrapper.</p>
          *
@@ -1321,6 +1366,12 @@
             return mSelectionBottomPadding;
         }
 
+        @Override
+        public boolean isInTouchMode() {
+            // WARNING: Please read the comment where mListSelectionHidden is declared
+            return mListSelectionHidden || super.isInTouchMode();
+        }
+
         /**
          * <p>Returns the focus state in the drop down.</p>
          *
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index a195ac7..6532125 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -174,6 +174,8 @@
             setDividerHeight(dividerHeight);
         }
 
+        setChoiceMode(a.getInt(R.styleable.ListView_choiceMode, CHOICE_MODE_NONE));
+        
         mHeaderDividersEnabled = a.getBoolean(R.styleable.ListView_headerDividersEnabled, true);
         mFooterDividersEnabled = a.getBoolean(R.styleable.ListView_footerDividersEnabled, true);
 
diff --git a/core/java/com/android/internal/backup/GoogleTransport.java b/core/java/com/android/internal/backup/GoogleTransport.java
deleted file mode 100644
index c089c23..0000000
--- a/core/java/com/android/internal/backup/GoogleTransport.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.android.internal.backup;
-
-import android.backup.RestoreSet;
-import android.content.pm.PackageInfo;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-
-/**
- * Backup transport for saving data to Google cloud storage.
- */
-
-public class GoogleTransport extends IBackupTransport.Stub {
-
-    public long requestBackupTime() throws RemoteException {
-        return 0;       // !!! TODO: implement real backoff policy
-    }
-
-    public int startSession() throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    public int endSession() throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
-            throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    // Restore handling
-    public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
-        // !!! TODO: real implementation
-        return null;
-    }
-
-    public PackageInfo[] getAppSet(int token) throws android.os.RemoteException {
-        // !!! TODO: real implementation
-        return new PackageInfo[0];
-    }
-
-    public int getRestoreData(int token, PackageInfo packageInfo, ParcelFileDescriptor data)
-            throws android.os.RemoteException {
-        // !!! TODO: real implementation
-        return 0;
-    }
-}
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 123c072..5caa015 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -12,6 +12,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import org.bouncycastle.util.encoders.Base64;
+
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileInputStream;
@@ -79,7 +81,10 @@
             while (changeSet.readNextHeader()) {
                 String key = changeSet.getKey();
                 int dataSize = changeSet.getDataSize();
-                if (DEBUG) Log.v(TAG, "Got change set key=" + key + " size=" + dataSize);
+
+                String base64Key = new String(Base64.encode(key.getBytes()));
+                if (DEBUG) Log.v(TAG, "Got change set key=" + key + " size=" + dataSize
+                        + " key64=" + base64Key);
                 if (dataSize > bufSize) {
                     bufSize = dataSize;
                     buf = new byte[bufSize];
@@ -87,7 +92,7 @@
                 changeSet.readEntityData(buf, 0, dataSize);
                 if (DEBUG) Log.v(TAG, "  + data size " + dataSize);
 
-                File entityFile = new File(packageDir, key);
+                File entityFile = new File(packageDir, base64Key);
                 FileOutputStream entity = new FileOutputStream(entityFile);
                 try {
                     entity.write(buf, 0, dataSize);
@@ -160,7 +165,7 @@
         File[] blobs = packageDir.listFiles();
         int err = 0;
         if (blobs != null && blobs.length > 0) {
-            BackupDataOutput out = new BackupDataOutput(mContext, outFd.getFileDescriptor());
+            BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
             try {
                 for (File f : blobs) {
                     FileInputStream in = new FileInputStream(f);
diff --git a/core/jni/android_bluetooth_Database.cpp b/core/jni/android_bluetooth_Database.cpp
index 136c9a3..73b8efd 100644
--- a/core/jni/android_bluetooth_Database.cpp
+++ b/core/jni/android_bluetooth_Database.cpp
@@ -53,6 +53,7 @@
             LOGE("Could not get onto the system bus!");
             dbus_error_free(&err);
         }
+        dbus_connection_set_exit_on_disconnect(conn, FALSE);
     }
 #endif
 }
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index fe94642..91a8e8e 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -84,6 +84,7 @@
         dbus_error_free(&err);
         return false;
     }
+    dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
 #endif  /*HAVE_BLUETOOTH*/
     return true;
 }
diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp
index b6e9798..58ae4f6 100644
--- a/core/jni/android_server_BluetoothDeviceService.cpp
+++ b/core/jni/android_server_BluetoothDeviceService.cpp
@@ -109,6 +109,7 @@
         dbus_error_free(&err);
         return false;
     }
+    dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
 
     nat->adapter = BLUEZ_ADAPTER_OBJECT_NAME;
 #endif  /*HAVE_BLUETOOTH*/
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 7c5da5b..ff8f28a 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -132,6 +132,7 @@
             LOGE("%s: Could not get onto the system bus!", __FUNCTION__);
             dbus_error_free(&err);
         }
+        dbus_connection_set_exit_on_disconnect(nat->conn, FALSE);
     }
 #endif
 }
diff --git a/core/res/res/layout/recent_apps_dialog.xml b/core/res/res/layout/recent_apps_dialog.xml
index 852b2f1..c4ee95d 100644
--- a/core/res/res/layout/recent_apps_dialog.xml
+++ b/core/res/res/layout/recent_apps_dialog.xml
@@ -17,67 +17,63 @@
 */
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content">
-    
+    android:layout_height="wrap_content"
+    android:padding="3dip"
+    android:orientation="vertical">
+
+    <!-- This is only intended to be visible when all buttons (below) are invisible -->
+    <TextView
+        android:id="@+id/no_applications_message"
+        android:layout_width="285dip"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="15dip"
+        android:layout_marginBottom="15dip"
+        android:gravity="center"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="@android:string/no_recent_tasks" />
+
+    <!-- The first row has a fixed-width because the UI spec requires the box
+         to display with full-width no matter how many icons are visible, but to
+         adjust height based on number of rows. -->
+    <!-- TODO Adjust all sizes, padding, etc. to meet pixel-perfect specs -->
+    <LinearLayout
+        android:layout_width="285dip"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <include
+            layout="@android:layout/recent_apps_icon"
+            android:id="@+id/button1" />
+
+        <include
+            layout="@android:layout/recent_apps_icon"
+            android:id="@+id/button2" />
+
+        <include
+            layout="@android:layout/recent_apps_icon"
+            android:id="@+id/button3" />
+
+    </LinearLayout>
+
     <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:padding="3dip"
-        android:orientation="vertical">
-        
-        <!-- This is only intended to be visible when all buttons (below) are invisible -->
-        <TextView
-            android:id="@+id/no_applications_message"
-            android:layout_width="285dip"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="15dip"
-            android:layout_marginBottom="15dip"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:text="@android:string/no_recent_tasks" />
-    
-        <!-- The first row has a fixed-width because the UI spec requires the box
-             to display with full-width no matter how many icons are visible, but to
-             adjust height based on number of rows. -->
-        <!-- TODO Adjust all sizes, padding, etc. to meet pixel-perfect specs -->
-        <LinearLayout
-            android:layout_width="285dip"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal" >
+        android:orientation="horizontal" >
 
-            <include
-                layout="@android:layout/recent_apps_icon"
-                android:id="@+id/button1" />
-    
-            <include
-                layout="@android:layout/recent_apps_icon"
-                android:id="@+id/button2" />
-    
-            <include
-                layout="@android:layout/recent_apps_icon"
-                android:id="@+id/button3" />
-    
-        </LinearLayout>
-        
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal" >
-            
-            <include
-                layout="@android:layout/recent_apps_icon"
-                android:id="@+id/button4" />
-            
-            <include
-                layout="@android:layout/recent_apps_icon"
-                android:id="@+id/button5" />
-            
-            <include
-                layout="@android:layout/recent_apps_icon"
-                android:id="@+id/button6" />
-                
-        </LinearLayout>    
+        <include
+            layout="@android:layout/recent_apps_icon"
+            android:id="@+id/button4" />
+
+        <include
+            layout="@android:layout/recent_apps_icon"
+            android:id="@+id/button5" />
+
+        <include
+            layout="@android:layout/recent_apps_icon"
+            android:id="@+id/button6" />
+
     </LinearLayout>
-</FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/recent_apps_icon.xml b/core/res/res/layout/recent_apps_icon.xml
index b8cf089..d32643c 100644
--- a/core/res/res/layout/recent_apps_icon.xml
+++ b/core/res/res/layout/recent_apps_icon.xml
@@ -18,27 +18,22 @@
 -->
 
 <!-- This is not a standalone element - it is imported into recent_apps_dialog.xml -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="87dip"
-    android:layout_height="78dip"
-    android:layout_margin="3dip"
-    android:orientation="vertical"
-    android:gravity="center_vertical"
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/label"
     style="?android:attr/buttonStyle"
-    android:background="@drawable/btn_application_selector">
-    <ImageView android:id="@+id/icon"
-        android:layout_width="@android:dimen/app_icon_size"
-        android:layout_height="@android:dimen/app_icon_size"
-        android:layout_gravity="center_horizontal"
-        android:scaleType="fitCenter" />
-    <TextView android:id="@+id/label"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:textSize="12dip"
-        android:maxLines="1"
-        android:ellipsize="end"
-        android:duplicateParentState="true"
-        android:textColor="@color/primary_text_dark_focused"
-        android:gravity="center_horizontal" />
-</LinearLayout>
+    android:background="@drawable/btn_application_selector"
+    android:layout_width="87dip"
+    android:layout_height="88dip"
+    android:layout_margin="3dip"
+    android:textColor="@color/primary_text_dark_focused"
+
+    android:paddingTop="5dip"
+    android:paddingBottom="2dip"
+    android:drawablePadding="0dip"
+
+    android:textSize="13dip"
+    android:maxLines="2"
+    android:ellipsize="marquee"
+    android:fadingEdge="horizontal"
+    android:gravity="top|center_horizontal" />
diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h
index 3ca8ad2..fa7f8d5 100644
--- a/include/utils/BackupHelpers.h
+++ b/include/utils/BackupHelpers.h
@@ -78,7 +78,7 @@
     bool HasEntities();
     status_t ReadEntityHeader(String8* key, size_t* dataSize);
     status_t SkipEntityData(); // must be called with the pointer at the begining of the data.
-    status_t ReadEntityData(void* data, size_t size);
+    ssize_t ReadEntityData(void* data, size_t size);
 
 private:
     explicit BackupDataReader();
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index 16ff1e5..34b37ed 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -281,16 +281,16 @@
     }
 }
 
-status_t
+ssize_t
 BackupDataReader::ReadEntityData(void* data, size_t size)
 {
     if (m_status != NO_ERROR) {
         return m_status;
     }
     int remaining = m_dataEndPos - m_pos;
+    //LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
+    //        size, m_pos, m_dataEndPos, remaining);
     if (size > remaining) {
-        printf("size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
-                size, m_pos, m_dataEndPos, remaining);
         size = remaining;
     }
     if (remaining <= 0) {
@@ -299,7 +299,7 @@
     int amt = read(m_fd, data, size);
     CHECK_SIZE(amt, (int)size);
     m_pos += size;
-    return NO_ERROR;
+    return amt;
 }
 
 status_t
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 16c66a6..2407d87 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -3,7 +3,7 @@
         android:sharedUserId="android.uid.system">
 
     <application android:allowClearUserData="false"
-                 android:label="Settings Storage"
+                 android:label="@string/app_label"
                  android:icon="@drawable/ic_launcher_settings">
 
         <provider android:name="SettingsProvider" android:authorities="settings"
diff --git a/packages/SettingsProvider/res/values/strings.xml b/packages/SettingsProvider/res/values/strings.xml
new file mode 100644
index 0000000..9ca575e
--- /dev/null
+++ b/packages/SettingsProvider/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2007, 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.
+ */
+-->
+<resources>
+    <!-- Name of the activity for Settings storage. -->
+    <string name="app_label">Settings Storage</string>
+</resources>
diff --git a/packages/SubscribedFeedsProvider/AndroidManifest.xml b/packages/SubscribedFeedsProvider/AndroidManifest.xml
index 6ecda48..ca00a9b 100644
--- a/packages/SubscribedFeedsProvider/AndroidManifest.xml
+++ b/packages/SubscribedFeedsProvider/AndroidManifest.xml
@@ -10,7 +10,7 @@
     <application android:process="system"
                  android:allowClearUserData="false"
                  android:icon="@drawable/app_icon"
-                 android:label="Sync Feeds">
+                 android:label="@string/app_label">
         <uses-library android:name="com.google.android.gtalkservice" />
         <provider android:name="SubscribedFeedsProvider"
                 android:authorities="subscribedfeeds" android:syncable="false"
diff --git a/packages/SubscribedFeedsProvider/res/values/strings.xml b/packages/SubscribedFeedsProvider/res/values/strings.xml
new file mode 100644
index 0000000..072571d
--- /dev/null
+++ b/packages/SubscribedFeedsProvider/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <!-- Title of the feed synchronization activity. -->
+    <string name="app_label">Sync Feeds</string>
+</resources>
+
diff --git a/packages/VpnServices/AndroidManifest.xml b/packages/VpnServices/AndroidManifest.xml
index e48b2da..6092e30 100644
--- a/packages/VpnServices/AndroidManifest.xml
+++ b/packages/VpnServices/AndroidManifest.xml
@@ -3,7 +3,7 @@
         package="com.android.server.vpn"
         android:sharedUserId="android.uid.system"
         >
-    <application android:label="VPN Services">
+    <application android:label="@string/app_label">
 
         <service android:name=".VpnServiceBinder" android:process=":remote">
             <intent-filter>
diff --git a/packages/VpnServices/res/values/strings.xml b/packages/VpnServices/res/values/strings.xml
index 892850a..e42c1e8 100755
--- a/packages/VpnServices/res/values/strings.xml
+++ b/packages/VpnServices/res/values/strings.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
+    <!-- Title for the VPN Services activity. -->
+    <string name="app_label">VPN Services</string>
+
     <string name="vpn_notification_title">%s VPN %s</string>
     <string name="vpn_notification_connected">connected</string>
     <string name="vpn_notification_disconnected">disconnected</string>
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index d842d34..2315821 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -21,14 +21,16 @@
 import android.app.IApplicationThread;
 import android.app.IBackupAgent;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -48,7 +50,6 @@
 import android.backup.RestoreSet;
 
 import com.android.internal.backup.LocalTransport;
-import com.android.internal.backup.GoogleTransport;
 import com.android.internal.backup.IBackupTransport;
 
 import java.io.EOFException;
@@ -122,7 +123,7 @@
 
     // Current active transport & restore session
     private int mTransportId;
-    private IBackupTransport mTransport;
+    private IBackupTransport mLocalTransport, mGoogleTransport;
     private RestoreSession mActiveRestoreSession;
 
     private File mStateDir;
@@ -151,10 +152,18 @@
             addPackageParticipantsLocked(null);
         }
 
-        // Stand up our default transport
-        //!!! TODO: default to cloud transport, not local
-        mTransportId = BackupManager.TRANSPORT_LOCAL;
-        mTransport = createTransport(mTransportId);
+        // Set up our transport options and initialize the default transport
+        // TODO: Have transports register themselves somehow?
+        // TODO: Don't create transports that we don't need to?
+        mTransportId = BackupManager.TRANSPORT_GOOGLE;
+        mLocalTransport = new LocalTransport(context);  // This is actually pretty cheap
+        mGoogleTransport = null;
+
+        // Attach to the Google backup transport.
+        Intent intent = new Intent().setComponent(new ComponentName(
+                "com.google.android.backup",
+                "com.google.android.backup.BackupTransportService"));
+        context.bindService(intent, mGoogleConnection, Context.BIND_AUTO_CREATE);
 
         // Now that we know about valid backup participants, parse any
         // leftover journal files and schedule a new backup pass
@@ -249,6 +258,19 @@
         }
     };
 
+    // ----- Track connection to GoogleBackupTransport service -----
+    ServiceConnection mGoogleConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DEBUG) Log.v(TAG, "Connected to Google transport");
+            mGoogleTransport = IBackupTransport.Stub.asInterface(service);
+        }
+
+        public void onServiceDisconnected(ComponentName name) {
+            if (DEBUG) Log.v(TAG, "Disconnected from Google transport");
+            mGoogleTransport = null;
+        }
+    };
+
     // ----- Run the actual backup process asynchronously -----
 
     private class BackupHandler extends Handler {
@@ -256,6 +278,13 @@
 
             switch (msg.what) {
             case MSG_RUN_BACKUP:
+            {
+                IBackupTransport transport = getTransport(mTransportId);
+                if (transport == null) {
+                    Log.v(TAG, "Backup requested but no transport available");
+                    break;
+                }
+
                 // snapshot the pending-backup set and work on that
                 File oldJournal = mJournal;
                 synchronized (mQueueLock) {
@@ -288,8 +317,10 @@
                     // deleted.  If we crash prior to that, the old journal is parsed
                     // at next boot and the journaled requests fulfilled.
                 }
-                (new PerformBackupThread(mTransport, mBackupQueue, oldJournal)).run();
+
+                (new PerformBackupThread(transport, mBackupQueue, oldJournal)).start();
                 break;
+            }
 
             case MSG_RUN_FULL_BACKUP:
                 break;
@@ -298,7 +329,7 @@
             {
                 int token = msg.arg1;
                 IBackupTransport transport = (IBackupTransport)msg.obj;
-                (new PerformRestoreThread(transport, token)).run();
+                (new PerformRestoreThread(transport, token)).start();
                 break;
             }
             }
@@ -416,25 +447,19 @@
         addPackageParticipantsLockedInner(packageName, allApps);
     }
 
-    // Instantiate the given transport
-    private IBackupTransport createTransport(int transportID) {
-        IBackupTransport transport = null;
+    // Return the given transport
+    private IBackupTransport getTransport(int transportID) {
         switch (transportID) {
         case BackupManager.TRANSPORT_LOCAL:
-            if (DEBUG) Log.v(TAG, "Initializing local transport");
-            transport = new LocalTransport(mContext);
-            break;
+            return mLocalTransport;
 
         case BackupManager.TRANSPORT_GOOGLE:
-            if (DEBUG) Log.v(TAG, "Initializing Google transport");
-            //!!! TODO: stand up the google backup transport for real here
-            transport = new GoogleTransport();
-            break;
+            return mGoogleTransport;
 
         default:
             Log.e(TAG, "Asked for unknown transport " + transportID);
+            return null;
         }
-        return transport;
     }
 
     // fire off a backup agent, blocking until it attaches or times out
@@ -937,14 +962,8 @@
     public int selectBackupTransport(int transportId) {
         mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport");
 
-        int prevTransport = -1;
-        IBackupTransport newTransport = createTransport(transportId);
-        if (newTransport != null) {
-            // !!! TODO: a method on the old transport that says it's being deactivated?
-            mTransport = newTransport;
-            prevTransport = mTransportId;
-            mTransportId = transportId;
-        }
+        int prevTransport = mTransportId;
+        mTransportId = transportId;
         return prevTransport;
     }
 
@@ -1005,7 +1024,7 @@
         RestoreSet[] mRestoreSets = null;
 
         RestoreSession(int transportID) {
-            mRestoreTransport = createTransport(transportID);
+            mRestoreTransport = getTransport(transportID);
         }
 
         // --- Binder interface ---
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 0d142da..f51f3d0 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -34,6 +34,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.IntentSender.SendIntentException;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
@@ -955,6 +957,34 @@
             }
         });
     }
+
+    public void freeStorageWithIntent(final long freeStorageSize, final IntentSender pi) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CLEAR_APP_CACHE, null);
+        // Queue up an async operation since clearing cache may take a little while.
+        mHandler.post(new Runnable() {
+            public void run() {
+                mHandler.removeCallbacks(this);
+                int retCode = -1;
+                if (mInstaller != null) {
+                    retCode = mInstaller.freeCache(freeStorageSize);
+                    if (retCode < 0) {
+                        Log.w(TAG, "Couldn't clear application caches");
+                    }
+                }
+                if(pi != null) {
+                    try {
+                        // Callback via pending intent
+                        int code = (retCode >= 0) ? 1 : 0;
+                        pi.sendIntent(null, code, null,
+                                null, null);
+                    } catch (SendIntentException e1) {
+                        Log.i(TAG, "Failed to send pending intent");
+                    }
+                }
+            }
+        });
+    }
     
     public ActivityInfo getActivityInfo(ComponentName component, int flags) {
         synchronized (mPackages) {
@@ -1239,28 +1269,6 @@
         return chooseBestActivity(intent, resolvedType, flags, query);
     }
 
-    public ResolveInfo resolveIntentForPackage(Intent intent, String resolvedType,
-                                               int flags, String packageName) {
-        ComponentName comp = intent.getComponent();
-        if (comp != null) {
-            // if this is an explicit intent, it must have the same the packageName
-            if (packageName.equals(comp.getPackageName())) {
-                return resolveIntent(intent, resolvedType, flags);
-            }
-            return null;
-        } else {
-            List<ResolveInfo> query = null;
-            synchronized (mPackages) {
-                PackageParser.Package pkg = mPackages.get(packageName);
-                if (pkg != null) {
-                    query = (List<ResolveInfo>) mActivities.
-                        queryIntentForPackage(intent, resolvedType, flags, pkg.activities);
-                }
-            }
-            return chooseBestActivity(intent, resolvedType, flags, query);
-        }
-    }
-
     private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
                                            int flags, List<ResolveInfo> query) {
         if (query != null) {
@@ -1379,8 +1387,17 @@
         }
 
         synchronized (mPackages) {
-            return (List<ResolveInfo>)mActivities.
-                queryIntent(intent, resolvedType, flags);
+            String pkgName = intent.getPackage();
+            if (pkgName == null) {
+                return (List<ResolveInfo>)mActivities.queryIntent(intent,
+                        resolvedType, flags);
+            }
+            PackageParser.Package pkg = mPackages.get(pkgName);
+            if (pkg != null) {
+                return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
+                        resolvedType, flags, pkg.activities);
+            }
+            return null;
         }
     }
 
@@ -1547,9 +1564,30 @@
 
     public List<ResolveInfo> queryIntentReceivers(Intent intent,
             String resolvedType, int flags) {
+        ComponentName comp = intent.getComponent();
+        if (comp != null) {
+            List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
+            ActivityInfo ai = getReceiverInfo(comp, flags);
+            if (ai != null) {
+                ResolveInfo ri = new ResolveInfo();
+                ri.activityInfo = ai;
+                list.add(ri);
+            }
+            return list;
+        }
+        
         synchronized (mPackages) {
-            return (List<ResolveInfo>)mReceivers.
-                queryIntent(intent, resolvedType, flags);
+            String pkgName = intent.getPackage();
+            if (pkgName == null) {
+                return (List<ResolveInfo>)mReceivers.queryIntent(intent,
+                        resolvedType, flags);
+            }
+            PackageParser.Package pkg = mPackages.get(pkgName);
+            if (pkg != null) {
+                return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
+                        resolvedType, flags, pkg.receivers);
+            }
+            return null;
         }
     }
 
@@ -1582,7 +1620,17 @@
         }
 
         synchronized (mPackages) {
-            return (List<ResolveInfo>)mServices.queryIntent(intent, resolvedType, flags);
+            String pkgName = intent.getPackage();
+            if (pkgName == null) {
+                return (List<ResolveInfo>)mServices.queryIntent(intent,
+                        resolvedType, flags);
+            }
+            PackageParser.Package pkg = mPackages.get(pkgName);
+            if (pkg != null) {
+                return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
+                        resolvedType, flags, pkg.services);
+            }
+            return null;
         }
     }
     
@@ -3076,6 +3124,27 @@
                 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
         }
 
+        public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
+                                          ArrayList<PackageParser.Service> packageServices) {
+            if (packageServices == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            int N = packageServices.size();
+            ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
+                new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
+
+            ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
+            for (int i = 0; i < N; ++i) {
+                intentFilters = packageServices.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    listCut.add(intentFilters);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
+        }
+
         public final void addService(PackageParser.Service s) {
             mServices.put(s.component, s);
             if (SHOW_INFO || Config.LOGV) Log.v(
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c0d4496..045e636 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -34,8 +34,6 @@
 import android.app.IActivityWatcher;
 import android.app.IApplicationThread;
 import android.app.IInstrumentationWatcher;
-import android.app.IIntentReceiver;
-import android.app.IIntentSender;
 import android.app.IServiceConnection;
 import android.app.IThumbnailReceiver;
 import android.app.Instrumentation;
@@ -48,6 +46,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
@@ -7904,7 +7904,8 @@
 
             // is there an Activity in this package that handles ACTION_APP_ERROR?
             Intent intent = new Intent(Intent.ACTION_APP_ERROR);
-            ResolveInfo info = pm.resolveIntentForPackage(intent, null, 0, installerPackageName);
+            intent.setPackage(installerPackageName);
+            ResolveInfo info = pm.resolveIntent(intent, null, 0);
             if (info == null || info.activityInfo == null) {
                 return null;
             }
@@ -8218,12 +8219,19 @@
                 report.time = crashData.getTime();
                 report.crashInfo.stackTrace = throwData.toString();
 
-                // extract the source of the exception, useful for report
-                // clustering
+                // Extract the source of the exception, useful for report
+                // clustering. Also extract the "deepest" non-null exception
+                // message.
+                String exceptionMessage = throwData.getMessage();
                 while (throwData.getCause() != null) {
                     throwData = throwData.getCause();
+                    String msg = throwData.getMessage();
+                    if (msg != null && msg.length() > 0) {
+                       exceptionMessage = msg;
+                    }
                 }
                 StackTraceElementData trace = throwData.getStackTrace()[0];
+                report.crashInfo.exceptionMessage = exceptionMessage;
                 report.crashInfo.exceptionClassName = throwData.getType();
                 report.crashInfo.throwFileName = trace.getFileName();
                 report.crashInfo.throwClassName = trace.getClassName();
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index 4057ae8..da55049 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -16,7 +16,7 @@
 
 package com.android.server.am;
 
-import android.app.IIntentReceiver;
+import android.content.IIntentReceiver;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 4381392..fa2a100 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -17,8 +17,8 @@
 package com.android.server.am;
 
 import android.app.IActivityManager;
-import android.app.IIntentSender;
-import android.app.IIntentReceiver;
+import android.content.IIntentSender;
+import android.content.IIntentReceiver;
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Binder;
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 0facefc..32c24c6 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -16,7 +16,7 @@
 
 package com.android.server.am;
 
-import android.app.IIntentReceiver;
+import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.Bundle;
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 866334b..2d58659 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -56,9 +56,9 @@
     private static final String TAG = "UsageStats";
     
     // Current on-disk Parcel version
-    private static final int VERSION = 1004;
+    private static final int VERSION = 1005;
 
-    private static final int CHECKIN_VERSION = 3;
+    private static final int CHECKIN_VERSION = 4;
     
     private static final String FILE_PREFIX = "usage-";
     
@@ -82,7 +82,9 @@
     // this lock held.
     final Object mFileLock;
     // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
-    private String mResumedPkg;
+    private String mLastResumedPkg;
+    private String mLastResumedComp;
+    private boolean mIsResumed;
     private File mFile;
     private String mFileLeaf;
     //private File mBackupFile;
@@ -92,11 +94,16 @@
     private int mLastWriteDay;
     
     static class TimeStats {
+        int count;
         int[] times = new int[NUM_LAUNCH_TIME_BINS];
         
         TimeStats() {
         }
         
+        void incCount() {
+            count++;
+        }
+        
         void add(int val) {
             final int[] bins = LAUNCH_TIME_BINS;
             for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
@@ -109,6 +116,7 @@
         }
         
         TimeStats(Parcel in) {
+            count = in.readInt();
             final int[] localTimes = times;
             for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                 localTimes[i] = in.readInt();
@@ -116,6 +124,7 @@
         }
         
         void writeToParcel(Parcel out) {
+            out.writeInt(count);
             final int[] localTimes = times;
             for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                 out.writeInt(localTimes[i]);
@@ -152,8 +161,10 @@
             }
         }
         
-        void updateResume() {
-            mLaunchCount ++;
+        void updateResume(boolean launched) {
+            if (launched) {
+                mLaunchCount ++;
+            }
             mResumedTime = SystemClock.elapsedRealtime();
         }
         
@@ -162,6 +173,15 @@
             mUsageTime += (mPausedTime - mResumedTime);
         }
         
+        void addLaunchCount(String comp) {
+            TimeStats times = mLaunchTimes.get(comp);
+            if (times == null) {
+                times = new TimeStats();
+                mLaunchTimes.put(comp, times);
+            }
+            times.incCount();
+        }
+        
         void addLaunchTime(String comp, int millis) {
             TimeStats times = mLaunchTimes.get(comp);
             if (times == null) {
@@ -436,43 +456,70 @@
     public void noteResumeComponent(ComponentName componentName) {
         enforceCallingPermission();
         String pkgName;
-        if ((componentName == null) ||
-                ((pkgName = componentName.getPackageName()) == null)) {
-            return;
-        }
-        if ((mResumedPkg != null) && (mResumedPkg.equalsIgnoreCase(pkgName))) {
-            // Moving across activities in same package. just return
-            return;
-        } 
-        if (localLOGV) Log.i(TAG, "started component:"+pkgName);
         synchronized (mStatsLock) {
+            if ((componentName == null) ||
+                    ((pkgName = componentName.getPackageName()) == null)) {
+                return;
+            }
+            
+            final boolean samePackage = pkgName.equals(mLastResumedPkg);
+            if (mIsResumed) {
+                if (samePackage) {
+                    Log.w(TAG, "Something wrong here, didn't expect "
+                            + pkgName + " to be resumed");
+                    return;
+                }
+                
+                if (mLastResumedPkg != null) {
+                    // We last resumed some other package...  just pause it now
+                    // to recover.
+                    Log.w(TAG, "Unexpected resume of " + pkgName
+                            + " while already resumed in " + mLastResumedPkg);
+                    PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg);
+                    if (pus != null) {
+                        pus.updatePause();
+                    }
+                }
+            }
+            
+            final boolean sameComp = samePackage
+                    && componentName.getClassName().equals(mLastResumedComp);
+            
+            mIsResumed = true;
+            mLastResumedPkg = pkgName;
+            mLastResumedComp = componentName.getClassName();
+            
+            if (localLOGV) Log.i(TAG, "started component:" + pkgName);
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus == null) {
                 pus = new PkgUsageStatsExtended();
                 mStats.put(pkgName, pus);
             }
-            pus.updateResume();
+            pus.updateResume(!samePackage);
+            if (!sameComp) {
+                pus.addLaunchCount(mLastResumedComp);
+            }
         }
-        mResumedPkg = pkgName;
     }
 
     public void notePauseComponent(ComponentName componentName) {
         enforceCallingPermission();
-        String pkgName;
-        if ((componentName == null) ||
-                ((pkgName = componentName.getPackageName()) == null)) {
-            return;
-        }
-        if ((mResumedPkg == null) || (!pkgName.equalsIgnoreCase(mResumedPkg))) {
-            Log.w(TAG, "Something wrong here, Didn't expect "+pkgName+" to be paused");
-            return;
-        }
-        if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
-        
-        // Persist current data to file if needed.
-        writeStatsToFile(false);
         
         synchronized (mStatsLock) {
+            String pkgName;
+            if ((componentName == null) ||
+                    ((pkgName = componentName.getPackageName()) == null)) {
+                return;
+            }
+            if (!mIsResumed) {
+                Log.w(TAG, "Something wrong here, didn't expect "
+                        + pkgName + " to be paused");
+                return;
+            }
+            mIsResumed = false;
+            
+            if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
+        
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus == null) {
                 // Weird some error here
@@ -481,6 +528,9 @@
             }
             pus.updatePause();
         }
+        
+        // Persist current data to file if needed.
+        writeStatsToFile(false);
     }
     
     public void noteLaunchTime(ComponentName componentName, int millis) {
@@ -631,9 +681,9 @@
             if (isCompactOutput) {
                 sb.append("P:");
                 sb.append(pkgName);
-                sb.append(",");
+                sb.append(',');
                 sb.append(pus.mLaunchCount);
-                sb.append(",");
+                sb.append(',');
                 sb.append(pus.mUsageTime);
                 sb.append('\n');
                 final int NC = pus.mLaunchTimes.size();
@@ -642,6 +692,8 @@
                         sb.append("A:");
                         sb.append(ent.getKey());
                         TimeStats times = ent.getValue();
+                        sb.append(',');
+                        sb.append(times.count);
                         for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                             sb.append(",");
                             sb.append(times.times[i]);
@@ -665,25 +717,26 @@
                         sb.append("    ");
                         sb.append(ent.getKey());
                         TimeStats times = ent.getValue();
+                        sb.append(": ");
+                        sb.append(times.count);
+                        sb.append(" starts");
                         int lastBin = 0;
-                        boolean first = true;
                         for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
                             if (times.times[i] != 0) {
-                                sb.append(first ? ": " : ", ");
+                                sb.append(", ");
                                 sb.append(lastBin);
                                 sb.append('-');
                                 sb.append(LAUNCH_TIME_BINS[i]);
-                                sb.append('=');
+                                sb.append("ms=");
                                 sb.append(times.times[i]);
-                                first = false;
                             }
                             lastBin = LAUNCH_TIME_BINS[i];
                         }
                         if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
-                            sb.append(first ? ": " : ", ");
+                            sb.append(", ");
                             sb.append(">=");
                             sb.append(lastBin);
-                            sb.append('=');
+                            sb.append("ms=");
                             sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
                         }
                         sb.append('\n');
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index 6ef5539..399a053 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageDeleteObserver;
@@ -62,11 +63,6 @@
     }
 
     @Override
-    public ResolveInfo resolveActivity(Intent intent, int flags, String packageName) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     public int[] getPackageGids(String packageName) throws NameNotFoundException {
         throw new UnsupportedOperationException();
     }
@@ -345,6 +341,15 @@
      * @hide - to match hiding in superclass
      */
     @Override
+    public void freeStorageWithIntent(
+            long idealStorageSize, IntentSender pi) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide - to match hiding in superclass
+     */
+    @Override
     public void deletePackage(
             String packageName, IPackageDeleteObserver observer, int flags) {
         throw new UnsupportedOperationException();
diff --git a/tests/backup/src/com/android/backuptest/BackupTestActivity.java b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
index af7dfd4..d87e85c 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestActivity.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
@@ -17,14 +17,17 @@
 package com.android.backuptest;
 
 import android.app.ListActivity;
+import android.backup.BackupDataInput;
+import android.backup.BackupDataOutput;
 import android.backup.BackupManager;
+import android.backup.FileBackupHelper;
+import android.backup.FileRestoreHelper;
+import android.backup.RestoreHelperDispatcher;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.PowerManager;
-import android.os.SystemClock;
+import android.os.ParcelFileDescriptor;
 import android.util.Log;
 import android.view.View;
 import android.widget.ArrayAdapter;
@@ -32,6 +35,10 @@
 import android.widget.Toast;
 
 import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -123,6 +130,43 @@
                 BackupManager bm = new BackupManager(BackupTestActivity.this);
                 bm.dataChanged();
             }
+        },
+        new Test("Backup Helpers") {
+            void run() {
+                try {
+                    writeFile("a", "a\naa", MODE_PRIVATE);
+                    writeFile("empty", "", MODE_PRIVATE);
+
+                    ParcelFileDescriptor state = ParcelFileDescriptor.open(
+                            new File(getFilesDir(), "state"),
+                            ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
+                            ParcelFileDescriptor.MODE_TRUNCATE);
+                    FileBackupHelper h = new FileBackupHelper(BackupTestActivity.this,
+                            "FileBackupHelper");
+                    FileOutputStream dataFile = openFileOutput("backup_test", MODE_WORLD_READABLE);
+                    BackupDataOutput data = new BackupDataOutput(dataFile.getFD());
+                    h.performBackup(null, data, state, new String[] { "a", "empty" });
+                    dataFile.close();
+                    state.close();
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+        },
+        new Test("Restore Helpers") {
+            void run() {
+                try {
+                    RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
+                    dispatch.addHelper("FileBackupHelper",
+                            new FileRestoreHelper(BackupTestActivity.this));
+                    FileInputStream dataFile = openFileInput("backup_test");
+                    BackupDataInput data = new BackupDataInput(dataFile.getFD());
+                    dispatch.dispatch(data);
+                    dataFile.close();
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
         }
     };
 
@@ -154,5 +198,14 @@
         t.run();
     }
     
+    void writeFile(String name, String contents, int mode) {
+        try {
+            PrintStream out = new PrintStream(openFileOutput(name, mode));
+            out.print(contents);
+            out.close();
+        } catch (FileNotFoundException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
 }
 
diff --git a/tests/backup/src/com/android/backuptest/BackupTestAgent.java b/tests/backup/src/com/android/backuptest/BackupTestAgent.java
index a370d69..e3566ec 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestAgent.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestAgent.java
@@ -17,28 +17,45 @@
 package com.android.backuptest;
 
 import android.app.BackupAgent;
+import android.backup.BackupDataInput;
 import android.backup.BackupDataOutput;
 import android.backup.FileBackupHelper;
+import android.backup.FileRestoreHelper;
+import android.backup.RestoreHelperDispatcher;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
+import java.io.IOException;
+
 public class BackupTestAgent extends BackupAgent
 {
     static final String TAG = "BackupTestAgent";
 
+    static final String SHARED_PREFS = "shared_prefs";
+    static final String DATA_FILES = "data_files";
+    static final String[] FILES = new String[] {
+                    BackupTestActivity.FILE_NAME
+                };
+
     @Override
     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
              ParcelFileDescriptor newState) {
         Log.d(TAG, "onBackup");
-        FileBackupHelper helper = new FileBackupHelper(this);
-        helper.performBackup(oldState, data, newState, new String[] {
-                    BackupTestActivity.FILE_NAME
-                });
+
+        (new FileBackupHelper(this, DATA_FILES)).performBackup(oldState, data, newState, FILES);
     }
 
     @Override
-    public void onRestore(ParcelFileDescriptor data, ParcelFileDescriptor newState) {
+    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
+            throws IOException {
         Log.d(TAG, "onRestore");
+
+        RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
+
+        // dispatch.addHelper(SHARED_PREFS, new SharedPrefsRestoreHelper(this));
+        dispatch.addHelper(DATA_FILES, new FileRestoreHelper(this));
+
+        dispatch.dispatch(data);
     }
 }
 
diff --git a/tests/permission/src/com/android/framework/permission/tests/SmsManagerPermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/SmsManagerPermissionTest.java
new file mode 100644
index 0000000..273943f
--- /dev/null
+++ b/tests/permission/src/com/android/framework/permission/tests/SmsManagerPermissionTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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 com.android.framework.permission.tests;
+
+import java.util.ArrayList;
+
+import android.telephony.SmsManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify that SmsManager apis cannot be called without required permissions.
+ */
+public class SmsManagerPermissionTest extends AndroidTestCase {
+
+    private static final String MSG_CONTENTS = "hi";
+    private static final short DEST_PORT = (short)1004;
+    private static final String DEST_NUMBER = "4567";
+    private static final String SRC_NUMBER = "1234";
+
+    /**
+     * Verify that SmsManager.sendTextMessage requires permissions.
+     * <p>Tests Permission:
+     *   {@link android.Manifest.permission#SEND_SMS}.
+     */
+    @SmallTest
+    public void testSendTextMessage() {
+        try {
+            SmsManager.getDefault().sendTextMessage(SRC_NUMBER, DEST_NUMBER, MSG_CONTENTS, null,
+                    null);
+            fail("SmsManager.sendTextMessage did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
+    /**
+     * Verify that SmsManager.sendDataMessage requires permissions.
+     * <p>Tests Permission:
+     *   {@link android.Manifest.permission#SEND_SMS}.
+     */
+    @SmallTest
+    public void testSendDataMessage() {
+        try {
+            SmsManager.getDefault().sendDataMessage(SRC_NUMBER, DEST_NUMBER, DEST_PORT,
+                    MSG_CONTENTS.getBytes(), null, null);
+            fail("SmsManager.sendDataMessage did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
+    /**
+     * Verify that SmsManager.sendMultipartMessage requires permissions.
+     * <p>Tests Permission:
+     *   {@link android.Manifest.permission#SEND_MMS}.
+     */
+    @SmallTest
+    public void testSendMultipartMessage() {
+        try {
+            ArrayList<String> msgParts = new ArrayList<String>(2);
+            msgParts.add(MSG_CONTENTS);
+            msgParts.add("foo");
+            SmsManager.getDefault().sendMultipartTextMessage(SRC_NUMBER, DEST_NUMBER, msgParts,
+                    null, null);
+            fail("SmsManager.sendMultipartTextMessage did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+}