Merge change 5196 into donut

* changes:
  Modify the IBackupTransport API to support bulk restore operations. Change the BackupManagerService and LocalTransport to support the new API.
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 2a4a672..3782136 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -26,10 +26,13 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.view.IWindowManager;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -446,6 +449,8 @@
             return;
         }
         
+        ParcelFileDescriptor fd = null;
+        
         String cmd = nextArg();
         if ("start".equals(cmd)) {
             start = true;
@@ -455,6 +460,16 @@
                 showUsage();
                 return;
             }
+            try {
+                fd = ParcelFileDescriptor.open(
+                        new File(profileFile),
+                        ParcelFileDescriptor.MODE_CREATE |
+                        ParcelFileDescriptor.MODE_TRUNCATE |
+                        ParcelFileDescriptor.MODE_READ_WRITE);
+            } catch (FileNotFoundException e) {
+                System.err.println("Error: Unable to open file: " + profileFile);
+                return;
+            }
         } else if (!"stop".equals(cmd)) {
             System.err.println("Error: Profile command " + cmd + " not valid");
             showUsage();
@@ -462,8 +477,8 @@
         }
         
         try {
-            if (!mAm.profileControl(process, start, profileFile)) {
-                System.out.println("PROFILE FAILED on process " + process);
+            if (!mAm.profileControl(process, start, profileFile, fd)) {
+                System.err.println("PROFILE FAILED on process " + process);
                 return;
             }
         } catch (IllegalArgumentException e) {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b6f855a..dfa8139 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -986,7 +986,9 @@
             String process = data.readString();
             boolean start = data.readInt() != 0;
             String path = data.readString();
-            boolean res = profileControl(process, start, path);
+            ParcelFileDescriptor fd = data.readInt() != 0
+                    ? data.readFileDescriptor() : null;
+            boolean res = profileControl(process, start, path, fd);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -2232,7 +2234,7 @@
     }
     
     public boolean profileControl(String process, boolean start,
-            String path) throws RemoteException
+            String path, ParcelFileDescriptor fd) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2240,6 +2242,12 @@
         data.writeString(process);
         data.writeInt(start ? 1 : 0);
         data.writeString(path);
+        if (fd != null) {
+            data.writeInt(1);
+            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
         mRemote.transact(PROFILE_CONTROL_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 98bd45a..79588ea 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -48,6 +48,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -74,6 +75,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -1236,6 +1238,11 @@
         String who;
     }
 
+    private static final class ProfilerControlData {
+        String path;
+        ParcelFileDescriptor fd;
+    }
+
     private final class ApplicationThread extends ApplicationThreadNative {
         private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
         private static final String ONE_COUNT_COLUMN = "%17s %8d";
@@ -1494,8 +1501,11 @@
             }
         }
         
-        public void profilerControl(boolean start, String path) {
-            queueOrSendMessage(H.PROFILER_CONTROL, path, start ? 1 : 0);
+        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
+            ProfilerControlData pcd = new ProfilerControlData();
+            pcd.path = path;
+            pcd.fd = fd;
+            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
         }
 
         public void setSchedulingGroup(int group) {
@@ -1838,7 +1848,7 @@
                     handleActivityConfigurationChanged((IBinder)msg.obj);
                     break;
                 case PROFILER_CONTROL:
-                    handleProfilerControl(msg.arg1 != 0, (String)msg.obj);
+                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
                     break;
                 case CREATE_BACKUP_AGENT:
                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
@@ -3618,15 +3628,20 @@
         performConfigurationChanged(r.activity, mConfiguration);
     }
 
-    final void handleProfilerControl(boolean start, String path) {
+    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
         if (start) {
-            File file = new File(path);
-            file.getParentFile().mkdirs();
             try {
-                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
+                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
+                        8 * 1024 * 1024, 0);
             } catch (RuntimeException e) {
-                Log.w(TAG, "Profiling failed on path " + path
+                Log.w(TAG, "Profiling failed on path " + pcd.path
                         + " -- can the process access this path?");
+            } finally {
+                try {
+                    pcd.fd.close();
+                } catch (IOException e) {
+                    Log.w(TAG, "Failure closing profile fd", e);
+                }
             }
         } else {
             Debug.stopMethodTracing();
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 4b64c94..b052c99 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -26,6 +26,7 @@
 import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -331,7 +332,9 @@
             data.enforceInterface(IApplicationThread.descriptor);
             boolean start = data.readInt() != 0;
             String path = data.readString();
-            profilerControl(start, path);
+            ParcelFileDescriptor fd = data.readInt() != 0
+                    ? data.readFileDescriptor() : null;
+            profilerControl(start, path, fd);
             return true;
         }
         
@@ -711,11 +714,18 @@
         data.recycle();
     }
     
-    public void profilerControl(boolean start, String path) throws RemoteException {
+    public void profilerControl(boolean start, String path,
+            ParcelFileDescriptor fd) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeInt(start ? 1 : 0);
         data.writeString(path);
+        if (fd != null) {
+            data.writeInt(1);
+            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
         mRemote.transact(PROFILER_CONTROL_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 66bc85b..3ec7938 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -250,7 +250,7 @@
     
     // Turn on/off profiling in a particular process.
     public boolean profileControl(String process, boolean start,
-            String path) throws RemoteException;
+            String path, ParcelFileDescriptor fd) throws RemoteException;
     
     public boolean shutdown(int timeout) throws RemoteException;
     
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 029c650..c0bc2a0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -25,6 +25,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
@@ -92,7 +93,8 @@
     void scheduleLowMemory() throws RemoteException;
     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
     void requestPss() throws RemoteException;
-    void profilerControl(boolean start, String path) throws RemoteException;
+    void profilerControl(boolean start, String path, ParcelFileDescriptor fd)
+            throws RemoteException;
     void setSchedulingGroup(int group) throws RemoteException;
     
     String descriptor = "android.app.IApplicationThread";
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 609fa74..6fe5506 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1578,6 +1578,16 @@
     public static final String ACTION_REBOOT =
             "android.intent.action.REBOOT";
 
+    /**
+     * @hide
+     * TODO: This will be unhidden in a later CL.
+     * Broadcast Action: The TextToSpeech synthesizer has completed processing 
+     * all of the text in the speech queue.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
+            "android.intent.action.TTS_QUEUE_PROCESSING_COMPLETED";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 8fcb4d7..d40ea6b 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -21,6 +21,7 @@
 import android.util.Config;
 import android.util.Log;
 
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -378,6 +379,20 @@
     }
 
     /**
+     * Like startMethodTracing(String, int, int), but taking an already-opened
+     * FileDescriptor in which the trace is written.  The file name is also
+     * supplied simply for logging.  Makes a dup of the file descriptor.
+     * 
+     * Not exposed in the SDK unless we are really comfortable with supporting
+     * this and find it would be useful.
+     * @hide
+     */
+    public static void startMethodTracing(String traceName, FileDescriptor fd,
+        int bufferSize, int flags) {
+        VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
+    }
+
+    /**
      * Determine whether method tracing is currently active.
      * @hide
      */
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 62b4d5e..0d9d2b0 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -12601,51 +12601,63 @@
     }
 
     public boolean profileControl(String process, boolean start,
-            String path) throws RemoteException {
+            String path, ParcelFileDescriptor fd) throws RemoteException {
 
-        synchronized (this) {
-            // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
-            // its own permission.
-            if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires permission "
-                        + android.Manifest.permission.SET_ACTIVITY_WATCHER);
-            }
-            
-            ProcessRecord proc = null;
-            try {
-                int pid = Integer.parseInt(process);
-                synchronized (mPidsSelfLocked) {
-                    proc = mPidsSelfLocked.get(pid);
+        try {
+            synchronized (this) {
+                // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
+                // its own permission.
+                if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    throw new SecurityException("Requires permission "
+                            + android.Manifest.permission.SET_ACTIVITY_WATCHER);
                 }
-            } catch (NumberFormatException e) {
-            }
-            
-            if (proc == null) {
-                HashMap<String, SparseArray<ProcessRecord>> all
-                        = mProcessNames.getMap();
-                SparseArray<ProcessRecord> procs = all.get(process);
-                if (procs != null && procs.size() > 0) {
-                    proc = procs.valueAt(0);
+                
+                if (start && fd == null) {
+                    throw new IllegalArgumentException("null fd");
                 }
-            }
-            
-            if (proc == null || proc.thread == null) {
-                throw new IllegalArgumentException("Unknown process: " + process);
-            }
-            
-            boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
-            if (isSecure) {
-                if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                    throw new SecurityException("Process not debuggable: " + proc);
+                
+                ProcessRecord proc = null;
+                try {
+                    int pid = Integer.parseInt(process);
+                    synchronized (mPidsSelfLocked) {
+                        proc = mPidsSelfLocked.get(pid);
+                    }
+                } catch (NumberFormatException e) {
                 }
-            }
+                
+                if (proc == null) {
+                    HashMap<String, SparseArray<ProcessRecord>> all
+                            = mProcessNames.getMap();
+                    SparseArray<ProcessRecord> procs = all.get(process);
+                    if (procs != null && procs.size() > 0) {
+                        proc = procs.valueAt(0);
+                    }
+                }
+                
+                if (proc == null || proc.thread == null) {
+                    throw new IllegalArgumentException("Unknown process: " + process);
+                }
+                
+                boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
+                if (isSecure) {
+                    if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+                        throw new SecurityException("Process not debuggable: " + proc);
+                    }
+                }
             
-            try {
-                proc.thread.profilerControl(start, path);
+                proc.thread.profilerControl(start, path, fd);
+                fd = null;
                 return true;
-            } catch (RemoteException e) {
-                throw new IllegalStateException("Process disappeared");
+            }
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Process disappeared");
+        } finally {
+            if (fd != null) {
+                try {
+                    fd.close();
+                } catch (IOException e) {
+                }
             }
         }
     }