Add TaskStackBuilder#addParentStack(ComponentName)

Let TaskStackBuilder discover a parent activity stack by ComponentName
in addition to explicit Activity classes.

Change-Id: I18b8378548ed1d6ef033800e6a3e11ab965d07e5
diff --git a/api/current.txt b/api/current.txt
index b4a1eae..2025aa7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3999,6 +3999,7 @@
     method public android.app.TaskStackBuilder addNextIntent(android.content.Intent);
     method public android.app.TaskStackBuilder addParentStack(android.app.Activity);
     method public android.app.TaskStackBuilder addParentStack(java.lang.Class<?>);
+    method public android.app.TaskStackBuilder addParentStack(android.content.ComponentName);
     method public static android.app.TaskStackBuilder from(android.content.Context);
     method public android.content.Intent getIntent(int);
     method public int getIntentCount();
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index 7fd4747..e2d28dd 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -91,8 +91,10 @@
 
     /**
      * Add the activity parent chain as specified by the
-     * {@link android.R.attr#parentActivityName parentActivityName} attribute of the activity
-     * (or activity-alias) element in the application's manifest to the task stack builder.
+     * {@link Activity#getParentActivityIntent() getParentActivityIntent()} method of the activity
+     * specified and the {@link android.R.attr#parentActivityName parentActivityName} attributes
+     * of each successive activity (or activity-alias) element in the application's manifest
+     * to the task stack builder.
      *
      * @param sourceActivity All parents of this activity will be added
      * @return This TaskStackBuilder for method chaining
@@ -156,6 +158,41 @@
     }
 
     /**
+     * Add the activity parent chain as specified by the
+     * {@link android.R.attr#parentActivityName parentActivityName} attribute of the activity
+     * (or activity-alias) element in the application's manifest to the task stack builder.
+     *
+     * @param sourceActivityName Must specify an Activity component. All parents of
+     *                           this activity will be added
+     * @return This TaskStackBuilder for method chaining
+     */
+    public TaskStackBuilder addParentStack(ComponentName sourceActivityName) {
+        final int insertAt = mIntents.size();
+        PackageManager pm = mSourceContext.getPackageManager();
+        try {
+            ActivityInfo info = pm.getActivityInfo(sourceActivityName, 0);
+            String parentActivity = info.parentActivityName;
+            Intent parent = new Intent().setComponent(
+                    new ComponentName(info.packageName, parentActivity));
+            while (parent != null) {
+                mIntents.add(insertAt, parent);
+                info = pm.getActivityInfo(parent.getComponent(), 0);
+                parentActivity = info.parentActivityName;
+                if (parentActivity != null) {
+                    parent = new Intent().setComponent(
+                            new ComponentName(info.packageName, parentActivity));
+                } else {
+                    parent = null;
+                }
+            }
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
+            throw new IllegalArgumentException(e);
+        }
+        return this;
+    }
+
+    /**
      * @return the number of intents added so far.
      */
     public int getIntentCount() {