Fix issue #3274841: Orientation change problem with a paused activity

Plus a bunch of debug output improvements.

And some new Intent helpers for dealing with restarting an app.

Change-Id: I50ec56bca6a86c562156b13fe8a6fdf68038a12e
diff --git a/api/current.xml b/api/current.xml
index a1b8d4b..9e45116 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -22167,6 +22167,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="prefix" type="java.lang.String">
+</parameter>
 <parameter name="fd" type="java.io.FileDescriptor">
 </parameter>
 <parameter name="writer" type="java.io.PrintWriter">
@@ -32145,6 +32147,25 @@
  visibility="public"
 >
 </constructor>
+<method name="dump"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="getLoader"
  return="android.content.Loader&lt;D&gt;"
  abstract="true"
@@ -50670,6 +50691,32 @@
  visibility="public"
 >
 </method>
+<method name="makeMainActivity"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mainActivity" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="makeRestartActivityTask"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mainActivity" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="parseIntent"
  return="android.content.Intent"
  abstract="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aaebbd0..5f460a2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4095,15 +4095,36 @@
 
     /**
      * Print the Activity's state into the given stream.  This gets invoked if
-     * you run "adb shell dumpsys activity <youractivityname>".
+     * you run "adb shell dumpsys activity <activity_component_name>".
      *
+     * @param prefix Desired prefix to prepend at each line of output.
      * @param fd The raw file descriptor that the dump is being sent to.
      * @param writer The PrintWriter to which you should dump your state.  This will be
      * closed for you after you return.
      * @param args additional arguments to the dump request.
      */
-    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        mFragments.dump("", fd, writer, args);
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.print(prefix); writer.print("Local Activity ");
+                writer.print(Integer.toHexString(System.identityHashCode(this)));
+                writer.println(" State:");
+        String innerPrefix = prefix + "  ";
+        writer.print(innerPrefix); writer.print("mResumed=");
+                writer.print(mResumed); writer.print(" mStopped=");
+                writer.print(mStopped); writer.print(" mFinished=");
+                writer.println(mFinished);
+        writer.print(innerPrefix); writer.print("mLoadersStarted=");
+                writer.println(mLoadersStarted);
+        writer.print(innerPrefix); writer.print("mChangingConfigurations=");
+                writer.println(mChangingConfigurations);
+        writer.print(innerPrefix); writer.print("mCurrentConfig=");
+                writer.println(mCurrentConfig);
+        if (mLoaderManager != null) {
+            writer.print(prefix); writer.print("Loader Manager ");
+                    writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
+                    writer.println(":");
+            mLoaderManager.dump(prefix + "  ", fd, writer, args);
+        }
+        mFragments.dump(prefix, fd, writer, args);
     }
 
     /**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 449992e..43f9d52 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -361,6 +361,7 @@
     private static final class DumpComponentInfo {
         FileDescriptor fd;
         IBinder token;
+        String prefix;
         String[] args;
         boolean dumped;
     }
@@ -680,10 +681,12 @@
             queueOrSendMessage(H.SCHEDULE_CRASH, msg);
         }
 
-        public void dumpActivity(FileDescriptor fd, IBinder activitytoken, String[] args) {
+        public void dumpActivity(FileDescriptor fd, IBinder activitytoken,
+                String prefix, String[] args) {
             DumpComponentInfo data = new DumpComponentInfo();
             data.fd = fd;
             data.token = activitytoken;
+            data.prefix = prefix;
             data.args = args;
             data.dumped = false;
             queueOrSendMessage(H.DUMP_ACTIVITY, data);
@@ -2076,7 +2079,7 @@
             ActivityClientRecord r = mActivities.get(info.token);
             if (r != null && r.activity != null) {
                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
-                r.activity.dump(info.fd, pw, info.args);
+                r.activity.dump(info.prefix, info.fd, pw, info.args);
                 pw.close();
             }
         } finally {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index abb26e3..7589e99 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -115,8 +115,9 @@
             return null;
         }
         Intent intent = new Intent(intentToResolve);
-        intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
-                            resolveInfo.activityInfo.name);
+        // Note: we do NOT fill in the component name; we'll leave the
+        // Intent unspecified, so if there are multiple matches within the
+        // package something reasonable will happen.
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         return intent;
     }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 801c3f9..d28e853 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -434,9 +434,10 @@
             data.enforceInterface(IApplicationThread.descriptor);
             ParcelFileDescriptor fd = data.readFileDescriptor();
             final IBinder activity = data.readStrongBinder();
+            final String prefix = data.readString();
             final String[] args = data.readStringArray();
             if (fd != null) {
-                dumpActivity(fd.getFileDescriptor(), activity, args);
+                dumpActivity(fd.getFileDescriptor(), activity, prefix, args);
                 try {
                     fd.close();
                 } catch (IOException e) {
@@ -906,12 +907,13 @@
         data.recycle();
     }
 
-    public void dumpActivity(FileDescriptor fd, IBinder token, String[] args)
+    public void dumpActivity(FileDescriptor fd, IBinder token, String prefix, String[] args)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeFileDescriptor(fd);
         data.writeStrongBinder(token);
+        data.writeString(prefix);
         data.writeStringArray(args);
         mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
         data.recycle();
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index e9b6869..b47aefd 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -21,6 +21,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 final class BackStackState implements Parcelable {
@@ -196,6 +198,61 @@
     int mBreadCrumbShortTitleRes;
     CharSequence mBreadCrumbShortTitleText;
 
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.print(prefix); writer.print("mName="); writer.print(mName);
+                writer.print(" mIndex="); writer.print(mIndex);
+                writer.print(" mCommitted="); writer.println(mCommitted);
+        if (mTransition != FragmentTransaction.TRANSIT_NONE) {
+            writer.print(prefix); writer.print("mTransition=#");
+                    writer.print(Integer.toHexString(mTransition));
+                    writer.print(" mTransitionStyle=#");
+                    writer.println(Integer.toHexString(mTransitionStyle));
+        }
+        if (mEnterAnim != 0 || mExitAnim !=0) {
+            writer.print(prefix); writer.print("mEnterAnim=#");
+                    writer.print(Integer.toHexString(mEnterAnim));
+                    writer.print(" mExitAnim=#");
+                    writer.println(Integer.toHexString(mExitAnim));
+        }
+        if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
+            writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
+                    writer.print(Integer.toHexString(mBreadCrumbTitleRes));
+                    writer.print(" mBreadCrumbTitleText=");
+                    writer.println(mBreadCrumbTitleText);
+        }
+        if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
+            writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#");
+                    writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
+                    writer.print(" mBreadCrumbShortTitleText=");
+                    writer.println(mBreadCrumbShortTitleText);
+        }
+
+        if (mHead != null) {
+            writer.print(prefix); writer.println("Operations:");
+            String innerPrefix = prefix + "    ";
+            Op op = mHead;
+            int num = 0;
+            while (op != null) {
+                writer.print(prefix); writer.print("  #"); writer.print(num);
+                        writer.print(" "); writer.print(op); writer.println(":");
+                writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd);
+                        writer.println("fragment="); writer.println(op.fragment);
+                if (op.enterAnim != 0 || op.exitAnim != 0) {
+                    writer.print(prefix); writer.print("enterAnim="); writer.print(op.enterAnim);
+                            writer.print(" exitAnim="); writer.println(op.exitAnim);
+                }
+                if (op.removed != null && op.removed.size() > 0) {
+                    for (int i=0; i<op.removed.size(); i++) {
+                        writer.print(innerPrefix); writer.println("Removed:");
+                        writer.print(innerPrefix); writer.print("  #"); writer.print(num);
+                                writer.print(": "); writer.println(op.removed.get(i));
+                    }
+                }
+                op = op.next;
+            }
+        }
+    }
+
     public BackStackRecord(FragmentManagerImpl manager) {
         mManager = manager;
     }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index b103385..eaa1e05 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1186,8 +1186,10 @@
      * @param args additional arguments to the dump request.
      */
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
-        writer.print(prefix); writer.print("mFragmentId="); writer.print(mFragmentId);
-                writer.print(" mContainerId="); writer.print(mContainerId);
+        writer.print(prefix); writer.print("mFragmentId=#");
+                writer.print(Integer.toHexString(mFragmentId));
+                writer.print(" mContainerId#=");
+                writer.print(Integer.toHexString(mContainerId));
                 writer.print(" mTag="); writer.println(mTag);
         writer.print(prefix); writer.print("mState="); writer.print(mState);
                 writer.print(" mIndex="); writer.print(mIndex);
@@ -1239,10 +1241,8 @@
             writer.print(prefix); writer.print("mView="); writer.println(mView);
         }
         if (mLoaderManager != null) {
-            writer.print(prefix); writer.print("mLoaderManager="); writer.print(mLoaderManager);
-                    writer.print(" mLoadersStarted="); writer.print(mLoadersStarted);
-                    writer.print(" mCheckedForLoaderManager=");
-                    writer.println(mCheckedForLoaderManager);
+            writer.print(prefix); writer.println("Loader Manager:");
+            mLoaderManager.dump(prefix + "  ", fd, writer, args);
         }
     }
 
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1b2d4df..196e7b2 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -248,7 +248,7 @@
      * @param prefix Text to print at the front of each line.
      * @param fd The raw file descriptor that the dump is being sent to.
      * @param writer A PrintWriter to which the dump is to be set.
-     * @param args additional arguments to the dump request.
+     * @param args Additional arguments to the dump request.
      */
     public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
 }
@@ -456,7 +456,9 @@
             return;
         }
 
-        writer.print(prefix); writer.println("Active Fragments:");
+        writer.print(prefix); writer.print("Active Fragments in ");
+                writer.print(Integer.toHexString(System.identityHashCode(this)));
+                writer.println(":");
 
         String innerPrefix = prefix + "    ";
 
@@ -490,6 +492,7 @@
                     BackStackRecord bs = mBackStack.get(i);
                     writer.print(prefix); writer.print("  #"); writer.print(i);
                             writer.print(": "); writer.println(bs.toString());
+                    bs.dump(innerPrefix, fd, writer, args);
                 }
             }
         }
@@ -1312,6 +1315,10 @@
                 Fragment f = fs.instantiate(mActivity);
                 if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f);
                 mActive.add(f);
+                // Now that the fragment is instantiated (or came from being
+                // retained above), clear mInstance in case we end up re-restoring
+                // from this FragmentState again.
+                fs.mInstance = null;
             } else {
                 if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": (null)");
                 mActive.add(null);
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index eca84ef..ecd199c 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -107,7 +107,7 @@
     static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
     void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
     void scheduleCrash(String msg) throws RemoteException;
-    void dumpActivity(FileDescriptor fd, IBinder servicetoken, String[] args)
+    void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
             throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index 7ae4b95..0ab987a 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -21,6 +21,9 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * Interface associated with an {@link Activity} or {@link Fragment} for managing
  * one or more {@link android.content.Loader} instances associated with it.
@@ -90,6 +93,16 @@
      * is found.
      */
     public abstract <D> Loader<D> getLoader(int id);
+
+    /**
+     * Print the LoaderManager's state into the given stream.
+     *
+     * @param prefix Text to print at the front of each line.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer A PrintWriter to which the dump is to be set.
+     * @param args Additional arguments to the dump request.
+     */
+    public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
 }
 
 class LoaderManagerImpl extends LoaderManager {
@@ -123,7 +136,7 @@
         boolean mRetainingStarted;
         boolean mDestroyed;
         boolean mListenerRegistered;
-        
+
         public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {
             mId = id;
             mArgs = args;
@@ -271,6 +284,28 @@
             sb.append("}");
             return sb.toString();
         }
+
+        public String toBasicString() {
+            StringBuilder sb = new StringBuilder(64);
+            sb.append("LoaderInfo{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" #");
+            sb.append(mId);
+            sb.append("}");
+            return sb.toString();
+        }
+
+        public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+            writer.print(prefix); writer.print("mId="); writer.print(mId);
+                    writer.print(" mArgs="); writer.println(mArgs);
+            writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks);
+            writer.print(prefix); writer.print("mLoader="); writer.println(mLoader);
+            writer.print(prefix); writer.print("mData="); writer.println(mData);
+            writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
+                    writer.print(" mRetaining="); writer.print(mRetaining);
+                    writer.print(" mDestroyed="); writer.print(mDestroyed);
+                    writer.print(" mListenerRegistered="); writer.println(mListenerRegistered);
+        }
     }
     
     LoaderManagerImpl(Activity activity, boolean started) {
@@ -443,4 +478,28 @@
         }
         mInactiveLoaders.clear();
     }
+
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        if (mLoaders.size() > 0) {
+            writer.print(prefix); writer.println("Active Loaders:");
+            String innerPrefix = prefix + "    ";
+            for (int i=0; i < mLoaders.size(); i++) {
+                LoaderInfo li = mLoaders.valueAt(i);
+                writer.print(prefix); writer.print("  #"); writer.print(mLoaders.keyAt(i));
+                        writer.print(": "); writer.println(li.toBasicString());
+                li.dump(innerPrefix, fd, writer, args);
+            }
+        }
+        if (mInactiveLoaders.size() > 0) {
+            writer.print(prefix); writer.println("Inactive Loaders:");
+            String innerPrefix = prefix + "    ";
+            for (int i=0; i < mInactiveLoaders.size(); i++) {
+                LoaderInfo li = mInactiveLoaders.valueAt(i);
+                writer.print(prefix); writer.print("  #"); writer.print(mInactiveLoaders.keyAt(i));
+                        writer.print(": "); writer.println(li.toBasicString());
+                li.dump(innerPrefix, fd, writer, args);
+            }
+        }
+    }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 84cb2fb..22befa8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2849,6 +2849,54 @@
     }
 
     /**
+     * Create an intent to launch the main (root) activity of a task.  This
+     * is the Intent that is started when the application's is launched from
+     * Home.  For anything else that wants to launch an application in the
+     * same way, it is important that they use an Intent structured the same
+     * way, and can use this function to ensure this is the case.
+     *
+     * <p>The returned Intent has the given Activity component as its explicit
+     * component, {@link #ACTION_MAIN} as its action, and includes the
+     * category {@link #CATEGORY_LAUNCHER}.  This does <em>not</em> have
+     * {@link #FLAG_ACTIVITY_NEW_TASK} set, though typically you will want
+     * to do that through {@link #addFlags(int)} on the returned Intent.
+     *
+     * @param mainActivity The main activity component that this Intent will
+     * launch.
+     * @return Returns a newly created Intent that can be used to launch the
+     * activity as a main application entry.
+     *
+     * @see #setClass
+     * @see #setComponent
+     */
+    public static Intent makeMainActivity(ComponentName mainActivity) {
+        Intent intent = new Intent(ACTION_MAIN);
+        intent.setComponent(mainActivity);
+        intent.addCategory(CATEGORY_LAUNCHER);
+        return intent;
+    }
+
+    /**
+     * Make an Intent that can be used to re-launch an application's task
+     * in its base state.  This is like {@link #makeMainActivity(ComponentName)},
+     * but also sets the flags {@link #FLAG_ACTIVITY_NEW_TASK} and
+     * {@link #FLAG_ACTIVITY_CLEAR_TASK}.
+     *
+     * @param mainActivity The activity component that is the root of the
+     * task; this is the activity that has been published in the application's
+     * manifest as the main launcher icon.
+     *
+     * @return Returns a newly created Intent that can be used to relaunch the
+     * activity's task in its root state.
+     */
+    public static Intent makeRestartActivityTask(ComponentName mainActivity) {
+        Intent intent = makeMainActivity(mainActivity);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        return intent;
+    }
+
+    /**
      * Call {@link #parseUri} with 0 flags.
      * @deprecated Use {@link #parseUri} instead.
      */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ac7a95a..2c2e7d7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -926,7 +926,7 @@
      *
      * @param packageName The name of the package to inspect.
      * 
-     * @return Returns either a fully-qualified Intent that can be used to
+     * @return Returns either an Intent that can be used to
      * launch the main activity in the package, or null if the package does
      * not contain such an activity.
      */
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1bfdcae..44029cd 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7340,6 +7340,9 @@
                 pw.println("    prov[iders]: content provider state");
                 pw.println("    s[ervices]: service state");
                 pw.println("    service [name]: service client-side state");
+                pw.println("  cmd may also be a component name (com.foo/.myApp),");
+                pw.println("    a partial substring in a component name, or an");
+                pw.println("    ActivityRecord hex object identifier.");
                 return;
             } else {
                 pw.println("Unknown argument: " + opt + "; use -h for help");
@@ -7393,7 +7396,9 @@
                 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
                     return;
                 }
-                pw.println("Bad activity command: " + cmd);
+                pw.println("Bad activity command, or no activities match: " + cmd);
+                pw.println("Use -h for help.");
+                return;
             }
         }
         
@@ -7811,11 +7816,14 @@
         String[] newArgs;
         ComponentName componentName = ComponentName.unflattenFromString(name);
         int objectId = 0;
-        try {
-            objectId = Integer.parseInt(name, 16);
-            name = null;
-            componentName = null;
-        } catch (RuntimeException e) {
+        if (componentName == null) {
+            // Not a '/' separated full component name; maybe an object ID?
+            try {
+                objectId = Integer.parseInt(name, 16);
+                name = null;
+                componentName = null;
+            } catch (RuntimeException e) {
+            }
         }
         newArgs = new String[args.length - opti];
         if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
@@ -7831,7 +7839,7 @@
                     if (r1.intent.getComponent().flattenToString().contains(name)) {
                         activities.add(r1);
                     }
-                } else if (System.identityHashCode(this) == objectId) {
+                } else if (System.identityHashCode(r1) == objectId) {
                     activities.add(r1);
                 }
             }
@@ -7841,8 +7849,18 @@
             return false;
         }
 
-        for (int i=0; i<activities.size(); i++) {
-            dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
+        TaskRecord lastTask = null;
+        for (int i=activities.size()-1; i>=0; i--) {
+            ActivityRecord r = (ActivityRecord)activities.get(i);
+            if (lastTask != r.task) {
+                lastTask = r.task;
+                pw.print("* Task "); pw.print(lastTask.affinity);
+                        pw.print(" id="); pw.println(lastTask.taskId);
+                if (dumpAll) {
+                    lastTask.dump(pw, "  ");
+                }
+            }
+            dumpActivity("  ", fd, pw, activities.get(i), newArgs, dumpAll);
         }
         return true;
     }
@@ -7851,23 +7869,24 @@
      * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
      * there is a thread associated with the activity.
      */
-    private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
-            boolean dumpAll) {
-        pw.println("  Activity " + r.intent.getComponent().flattenToString());
-        if (dumpAll) {
-            synchronized (this) {
-                pw.print("  * "); pw.println(r);
-                r.dump(pw, "    ");
+    private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
+            ActivityRecord r, String[] args, boolean dumpAll) {
+        synchronized (this) {
+            pw.print(prefix); pw.print("* Activity ");
+                    pw.print(Integer.toHexString(System.identityHashCode(r)));
+                    pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
+                    if (r.app != null) pw.println(r.app.pid);
+                    else pw.println("(not running)");
+            if (dumpAll) {
+                r.dump(pw, prefix + "  ");
             }
-            pw.println("");
         }
         if (r.app != null && r.app.thread != null) {
             try {
                 // flush anything that is already in the PrintWriter since the thread is going
                 // to write to the file descriptor directly
                 pw.flush();
-                r.app.thread.dumpActivity(fd, r, args);
-                pw.print("\n");
+                r.app.thread.dumpActivity(fd, r, prefix + "  ", args);
                 pw.flush();
             } catch (RemoteException e) {
                 pw.println("got a RemoteException while dumping the activity");
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index c2f8d67..b4e426f 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -587,7 +587,7 @@
             return stringName;
         }
         StringBuilder sb = new StringBuilder(128);
-        sb.append("HistoryRecord{");
+        sb.append("ActivityRecord{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(' ');
         sb.append(intent.getComponent().flattenToShortString());