Merge "Remove StaggeredGridView from support library and move to ex folder" into jb-dev
diff --git a/v4/Android.mk b/v4/Android.mk
index 267747e..3f01e5a 100644
--- a/v4/Android.mk
+++ b/v4/Android.mk
@@ -83,8 +83,7 @@
 # A helper sub-library that makes direct use of JellyBean APIs.
 include $(CLEAR_VARS)
 LOCAL_MODULE := android-support-v4-jellybean
-#TODO: Update LOCAL_SDK_VERSION as soon JellyBean has such. (tracked by bug:5947249)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 16
 LOCAL_SRC_FILES := $(call all-java-files-under, jellybean)
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
diff --git a/v4/java/android/support/v4/app/ActivityCompat.java b/v4/java/android/support/v4/app/ActivityCompat.java
index bf86786..9a8b62b 100644
--- a/v4/java/android/support/v4/app/ActivityCompat.java
+++ b/v4/java/android/support/v4/app/ActivityCompat.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Build;
+import android.os.Bundle;
 
 /**
  * Helper for accessing features in {@link android.app.Activity}
@@ -91,7 +92,43 @@
      * @return true if the underlying API was available and the call was successful, false otherwise
      */
     public static boolean startActivities(Activity activity, Intent[] intents) {
-        if (Build.VERSION.SDK_INT >= 11) {
+        return startActivities(activity, intents, null);
+    }
+
+    /**
+     * Start a set of activities as a synthesized task stack, if able.
+     *
+     * <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
+     * app navigation using the back key changed. The back key's behavior is local
+     * to the current task and does not capture navigation across different tasks.
+     * Navigating across tasks and easily reaching the previous task is accomplished
+     * through the "recents" UI, accessible through the software-provided Recents key
+     * on the navigation or system bar. On devices with the older hardware button configuration
+     * the recents UI can be accessed with a long press on the Home key.</p>
+     *
+     * <p>When crossing from one task stack to another post-Android 3.0,
+     * the application should synthesize a back stack/history for the new task so that
+     * the user may navigate out of the new task and back to the Launcher by repeated
+     * presses of the back key. Back key presses should not navigate across task stacks.</p>
+     *
+     * <p>startActivities provides a mechanism for constructing a synthetic task stack of
+     * multiple activities. If the underlying API is not available on the system this method
+     * will return false.</p>
+     *
+     * @param activity Start activities using this activity as the starting context
+     * @param intents Array of intents defining the activities that will be started. The element
+     *                length-1 will correspond to the top activity on the resulting task stack.
+     * @param options Additional options for how the Activity should be started.
+     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * @return true if the underlying API was available and the call was successful, false otherwise
+     */
+    public static boolean startActivities(Activity activity, Intent[] intents,
+            Bundle options) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 16) {
+            ActivityCompatJellybean.startActivities(activity, intents, options);
+            return true;
+        } else if (version >= 11) {
             ActivityCompatHoneycomb.startActivities(activity, intents);
             return true;
         }
diff --git a/v4/java/android/support/v4/app/TaskStackBuilder.java b/v4/java/android/support/v4/app/TaskStackBuilder.java
index 991ea65..29b0b64 100644
--- a/v4/java/android/support/v4/app/TaskStackBuilder.java
+++ b/v4/java/android/support/v4/app/TaskStackBuilder.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Build;
+import android.os.Bundle;
 import android.support.v4.content.IntentCompat;
 import android.util.Log;
 
@@ -68,12 +69,12 @@
 
     interface TaskStackBuilderImpl {
         PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
-                int flags);
+                int flags, Bundle options);
     }
 
     static class TaskStackBuilderImplBase implements TaskStackBuilderImpl {
         public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
-                int flags) {
+                int flags, Bundle options) {
             Intent topIntent = intents[intents.length - 1];
             topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             return PendingIntent.getActivity(context, requestCode, topIntent, flags);
@@ -82,7 +83,7 @@
 
     static class TaskStackBuilderImplHoneycomb implements TaskStackBuilderImpl {
         public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
-                int flags) {
+                int flags, Bundle options) {
             intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                     IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
             return TaskStackBuilderHoneycomb.getActivitiesPendingIntent(context, requestCode,
@@ -90,6 +91,16 @@
         }
     }
 
+    static class TaskStackBuilderImplJellybean implements TaskStackBuilderImpl {
+        public PendingIntent getPendingIntent(Context context, Intent[] intents, int requestCode,
+                int flags, Bundle options) {
+            intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                    IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
+            return TaskStackBuilderJellybean.getActivitiesPendingIntent(context, requestCode,
+                    intents, flags, options);
+        }
+    }
+
     private static final TaskStackBuilderImpl IMPL;
 
     static {
@@ -114,11 +125,24 @@
      * @param context The context that will launch the new task stack or generate a PendingIntent
      * @return A new TaskStackBuilder
      */
-    public static TaskStackBuilder from(Context context) {
+    public static TaskStackBuilder create(Context context) {
         return new TaskStackBuilder(context);
     }
 
     /**
+     * Return a new TaskStackBuilder for launching a fresh task stack consisting
+     * of a series of activities.
+     *
+     * @param context The context that will launch the new task stack or generate a PendingIntent
+     * @return A new TaskStackBuilder
+     *
+     * @deprecated use {@link #create(Context)} instead
+     */
+    public static TaskStackBuilder from(Context context) {
+        return create(context);
+    }
+
+    /**
      * Add a new Intent to the task stack. The most recently added Intent will invoke
      * the Activity at the top of the final task stack.
      *
@@ -188,11 +212,28 @@
      *
      * @param index Index from 0-getIntentCount()
      * @return the intent at position index
+     *
+     * @deprecated Renamed to editIntentAt to better reflect intended usage
      */
     public Intent getIntent(int index) {
+        return editIntentAt(index);
+    }
+
+    /**
+     * Return the intent at the specified index for modification.
+     * Useful if you need to modify the flags or extras of an intent that was previously added,
+     * for example with {@link #addParentStack(Activity)}.
+     *
+     * @param index Index from 0-getIntentCount()
+     * @return the intent at position index
+     */
+    public Intent editIntentAt(int index) {
         return mIntents.get(index);
     }
 
+    /**
+     * @deprecated Use editIntentAt instead
+     */
     public Iterator<Intent> iterator() {
         return mIntents.iterator();
     }
@@ -206,6 +247,21 @@
      * the new task stack will be created in its entirety.</p>
      */
     public void startActivities() {
+        startActivities(null);
+    }
+
+    /**
+     * Start the task stack constructed by this builder. The Context used to obtain
+     * this builder must be an Activity.
+     *
+     * <p>On devices that do not support API level 11 or higher the topmost activity
+     * will be started as a new task. On devices that do support API level 11 or higher
+     * the new task stack will be created in its entirety.</p>
+     *
+     * @param options Additional options for how the Activity should be started.
+     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     */
+    public void startActivities(Bundle options) {
         if (mIntents.isEmpty()) {
             throw new IllegalStateException(
                     "No intents added to TaskStackBuilder; cannot startActivities");
@@ -215,7 +271,7 @@
         intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                 IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
                 IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
-        if (!ActivityCompat.startActivities((Activity) mSourceContext, intents)) {
+        if (!ActivityCompat.startActivities((Activity) mSourceContext, intents, options)) {
             Intent topIntent = intents[intents.length - 1];
             topIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             mSourceContext.startActivity(topIntent);
@@ -234,6 +290,23 @@
      * @return The obtained PendingIntent
      */
     public PendingIntent getPendingIntent(int requestCode, int flags) {
+        return getPendingIntent(requestCode, flags, null);
+    }
+
+    /**
+     * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far.
+     *
+     * @param requestCode Private request code for the sender
+     * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT},
+     *              {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT},
+     *              {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by
+     *              {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the
+     *              intent that can be supplied when the actual send happens.
+     * @param options Additional options for how the Activity should be started.
+     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * @return The obtained PendingIntent
+     */
+    public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options) {
         if (mIntents.isEmpty()) {
             throw new IllegalStateException(
                     "No intents added to TaskStackBuilder; cannot getPendingIntent");
@@ -243,6 +316,17 @@
         intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                 IntentCompat.FLAG_ACTIVITY_CLEAR_TASK |
                 IntentCompat.FLAG_ACTIVITY_TASK_ON_HOME);
-        return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags);
+        return IMPL.getPendingIntent(mSourceContext, intents, requestCode, flags, options);
+    }
+
+    /**
+     * Return an array containing the intents added to this builder. The intent at the
+     * root of the task stack will appear as the first item in the array and the
+     * intent at the top of the stack will appear as the last item.
+     *
+     * @return An array containing the intents added to this builder.
+     */
+    public Intent[] getIntents() {
+        return mIntents.toArray(new Intent[mIntents.size()]);
     }
 }
diff --git a/v4/java/android/support/v4/view/PagerTitleStrip.java b/v4/java/android/support/v4/view/PagerTitleStrip.java
index e461cce..1c91bf2 100644
--- a/v4/java/android/support/v4/view/PagerTitleStrip.java
+++ b/v4/java/android/support/v4/view/PagerTitleStrip.java
@@ -198,10 +198,13 @@
 
     @Override
     protected void onDetachedFromWindow() {
-        updateAdapter(mPager.getAdapter(), null);
-        mPager.setInternalPageChangeListener(null);
-        mPager.setOnAdapterChangeListener(null);
-        mPager = null;
+        super.onDetachedFromWindow();
+        if (mPager != null) {
+            updateAdapter(mPager.getAdapter(), null);
+            mPager.setInternalPageChangeListener(null);
+            mPager.setOnAdapterChangeListener(null);
+            mPager = null;
+        }
     }
 
     void updateText(int currentItem, PagerAdapter adapter) {
diff --git a/v4/jellybean/android/support/v4/app/ActivityCompatJellybean.java b/v4/jellybean/android/support/v4/app/ActivityCompatJellybean.java
new file mode 100644
index 0000000..24d51d2
--- /dev/null
+++ b/v4/jellybean/android/support/v4/app/ActivityCompatJellybean.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 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.support.v4.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+class ActivityCompatJellybean {
+
+    public static void startActivities(Activity activity, Intent[] intents, Bundle options) {
+        activity.startActivities(intents, options);
+    }
+
+}
diff --git a/v4/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java b/v4/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java
new file mode 100644
index 0000000..8b79b1b
--- /dev/null
+++ b/v4/jellybean/android/support/v4/app/TaskStackBuilderJellybean.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 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.support.v4.app;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+class TaskStackBuilderJellybean {
+
+    public static PendingIntent getActivitiesPendingIntent(Context context, int requestCode,
+            Intent[] intents, int flags, Bundle options) {
+        return PendingIntent.getActivities(context, requestCode, intents, flags, options);
+    }
+
+}