Work on fragments in layouts.

- Change semantics if IDs associated with these fragments, to
  work correctly when placed in a container.  If the container
  has an ID or you have supplied a tag, the fragment's ID is
  optional.

- To do this, there is a new LayoutInflater API that allows code
  creating views to access the parent container that view will
  be in.

- Fix issues with state management around these fragments.  Now
  correctly retains state when switching to a layout that doesn't
  include the fragment.

Also:

- Add new simple list layouts for items that want to show an
  activated state.
- Add new Activity.dump() that can be invoked with adb shell
  dumpsys; the default implementation dumps fragment state.

Change-Id: I192f35e3ea8c53fbd26cf909095f2a994abfc1b6
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1f8d697..c896c94 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7105,6 +7105,12 @@
                     dumpServicesLocked(fd, pw, args, opti, true);
                 }
                 return;
+            } else {
+                // Dumping a single activity?
+                if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
+                    return;
+                }
+                pw.println("Bad activity command: " + cmd);
             }
         }
         
@@ -7458,6 +7464,82 @@
         }
     }
 
+    /**
+     * There are three things that cmd can be:
+     *  - a flattened component name that matched an existing activity
+     *  - the cmd arg isn't the flattened component name of an existing activity:
+     *    dump all activity whose component contains the cmd as a substring
+     *  - A hex number of the ActivityRecord object instance.
+     */
+    protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+            int opti, boolean dumpAll) {
+        String[] newArgs;
+        ComponentName componentName = ComponentName.unflattenFromString(name);
+        int objectId = 0;
+        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);
+
+        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+        synchronized (this) {
+            for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+                if (componentName != null) {
+                    if (r1.intent.getComponent().equals(componentName)) {
+                        activities.add(r1);
+                    }
+                } else if (name != null) {
+                    if (r1.intent.getComponent().flattenToString().contains(name)) {
+                        activities.add(r1);
+                    }
+                } else if (System.identityHashCode(this) == objectId) {
+                    activities.add(r1);
+                }
+            }
+        }
+
+        if (activities.size() <= 0) {
+            return false;
+        }
+
+        for (int i=0; i<activities.size(); i++) {
+            dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
+        }
+        return true;
+    }
+
+    /**
+     * 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, "    ");
+            }
+            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");
+                pw.flush();
+            } catch (RemoteException e) {
+                pw.println("got a RemoteException while dumping the activity");
+            }
+        }
+    }
+
     boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll) {
         boolean needSep = false;