Merge "Fix build." into klp-modular-dev
diff --git a/api/current.txt b/api/current.txt
index 0f84194..3e3c295 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3916,6 +3916,8 @@
     ctor public Notification(android.os.Parcel);
     method public android.app.Notification clone();
     method public int describeContents();
+    method public java.lang.String getGroup();
+    method public java.lang.String getSortKey();
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -3942,6 +3944,7 @@
     field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
     field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
     field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+    field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
     field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80
     field public static final int FLAG_INSISTENT = 4; // 0x4
     field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
@@ -3985,6 +3988,7 @@
     method public android.app.Notification.Action clone();
     method public int describeContents();
     method public android.os.Bundle getExtras();
+    method public android.app.RemoteInput[] getRemoteInputs();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public android.app.PendingIntent actionIntent;
@@ -3992,14 +3996,20 @@
     field public java.lang.CharSequence title;
   }
 
-  public static class Notification.Action.Builder {
+  public static final class Notification.Action.Builder {
     ctor public Notification.Action.Builder(int, java.lang.CharSequence, android.app.PendingIntent);
     ctor public Notification.Action.Builder(android.app.Notification.Action);
     method public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
+    method public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
+    method public android.app.Notification.Action.Builder apply(android.app.Notification.Action.Builder.Extender);
     method public android.app.Notification.Action build();
     method public android.os.Bundle getExtras();
   }
 
+  public static abstract interface Notification.Action.Builder.Extender {
+    method public abstract android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+  }
+
   public static class Notification.BigPictureStyle extends android.app.Notification.Style {
     ctor public Notification.BigPictureStyle();
     ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
@@ -4022,6 +4032,7 @@
     method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
+    method public android.app.Notification.Builder apply(android.app.Notification.Builder.Extender);
     method public android.app.Notification build();
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
@@ -4035,6 +4046,8 @@
     method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setExtras(android.os.Bundle);
     method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
+    method public android.app.Notification.Builder setGroup(java.lang.String);
+    method public android.app.Notification.Builder setGroupSummary(boolean);
     method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
@@ -4046,6 +4059,7 @@
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
+    method public android.app.Notification.Builder setSortKey(java.lang.String);
     method public android.app.Notification.Builder setSound(android.net.Uri);
     method public android.app.Notification.Builder setSound(android.net.Uri, int);
     method public android.app.Notification.Builder setStyle(android.app.Notification.Style);
@@ -4057,6 +4071,10 @@
     method public android.app.Notification.Builder setWhen(long);
   }
 
+  public static abstract interface Notification.Builder.Extender {
+    method public abstract android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+  }
+
   public static class Notification.InboxStyle extends android.app.Notification.Style {
     ctor public Notification.InboxStyle();
     ctor public Notification.InboxStyle(android.app.Notification.Builder);
@@ -4160,6 +4178,31 @@
     field public static final int STYLE_SPINNER = 0; // 0x0
   }
 
+  public final class RemoteInput implements android.os.Parcelable {
+    method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
+    method public int describeContents();
+    method public boolean getAllowFreeFormInput();
+    method public java.lang.CharSequence[] getChoices();
+    method public android.os.Bundle getExtras();
+    method public java.lang.CharSequence getLabel();
+    method public java.lang.String getResultKey();
+    method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+    field public static final java.lang.String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+  }
+
+  public static final class RemoteInput.Builder {
+    ctor public RemoteInput.Builder(java.lang.String);
+    method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
+    method public android.app.RemoteInput build();
+    method public android.os.Bundle getExtras();
+    method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+    method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
+    method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
+  }
+
   public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
     method public android.content.ComponentName getGlobalSearchActivity();
     method public android.app.SearchableInfo getSearchableInfo(android.content.ComponentName);
@@ -4618,6 +4661,80 @@
 
 }
 
+package android.app.wearable {
+
+  public final class WearableActionExtensions implements android.app.Notification.Action.Builder.Extender android.os.Parcelable {
+    method public android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+    method public int describeContents();
+    method public static android.app.wearable.WearableActionExtensions from(android.app.Notification.Action);
+    method public boolean isAvailableOffline();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static final class WearableActionExtensions.Builder {
+    ctor public WearableActionExtensions.Builder();
+    ctor public WearableActionExtensions.Builder(android.app.wearable.WearableActionExtensions);
+    method public android.app.wearable.WearableActionExtensions build();
+    method public android.app.wearable.WearableActionExtensions.Builder setAvailableOffline(boolean);
+  }
+
+  public final class WearableNotificationExtensions implements android.app.Notification.Builder.Extender android.os.Parcelable {
+    method public android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+    method public int describeContents();
+    method public static android.app.wearable.WearableNotificationExtensions from(android.app.Notification);
+    method public android.app.Notification.Action getAction(int);
+    method public int getActionCount();
+    method public android.app.Notification.Action[] getActions();
+    method public android.graphics.Bitmap getBackground();
+    method public int getContentAction();
+    method public int getContentIcon();
+    method public int getContentIconGravity();
+    method public boolean getContentIntentAvailableOffline();
+    method public int getCustomContentHeight();
+    method public int getCustomSizePreset();
+    method public android.app.PendingIntent getDisplayIntent();
+    method public int getGravity();
+    method public boolean getHintHideIcon();
+    method public boolean getHintShowBackgroundOnly();
+    method public android.app.Notification[] getPages();
+    method public boolean getStartScrollBottom();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int SIZE_DEFAULT = 0; // 0x0
+    field public static final int SIZE_LARGE = 4; // 0x4
+    field public static final int SIZE_MEDIUM = 3; // 0x3
+    field public static final int SIZE_SMALL = 2; // 0x2
+    field public static final int SIZE_XSMALL = 1; // 0x1
+    field public static final int UNSET_ACTION_INDEX = -1; // 0xffffffff
+  }
+
+  public static final class WearableNotificationExtensions.Builder {
+    ctor public WearableNotificationExtensions.Builder();
+    ctor public WearableNotificationExtensions.Builder(android.app.wearable.WearableNotificationExtensions);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addAction(android.app.Notification.Action);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addActions(java.util.List<android.app.Notification.Action>);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addPage(android.app.Notification);
+    method public android.app.wearable.WearableNotificationExtensions.Builder addPages(java.util.List<android.app.Notification>);
+    method public android.app.wearable.WearableNotificationExtensions build();
+    method public android.app.wearable.WearableNotificationExtensions.Builder clearActions();
+    method public android.app.wearable.WearableNotificationExtensions.Builder clearPages();
+    method public android.app.wearable.WearableNotificationExtensions.Builder setBackground(android.graphics.Bitmap);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentAction(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentIcon(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentIconGravity(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setContentIntentAvailableOffline(boolean);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setCustomContentHeight(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setCustomSizePreset(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setDisplayIntent(android.app.PendingIntent);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setGravity(int);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setHintHideIcon(boolean);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setHintShowBackgroundOnly(boolean);
+    method public android.app.wearable.WearableNotificationExtensions.Builder setStartScrollBottom(boolean);
+  }
+
+}
+
 package android.appwidget {
 
   public class AppWidgetHost {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8d263fd..e606194 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -39,6 +39,7 @@
 
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * A class that represents how a persistent notification is to be presented to
@@ -355,6 +356,14 @@
      */
     public static final int FLAG_LOCAL_ONLY         = 0x00000100;
 
+    /**
+     * Bit to be bitswise-ored into the {@link #flags} field that should be
+     * set if this notification is the group summary for a group of notifications.
+     * Grouped notifications may display in a cluster or stack on devices which
+     * support such rendering. Requires a group key also be set using {@link Builder#setGroup}.
+     */
+    public static final int FLAG_GROUP_SUMMARY      = 0x00000200;
+
     public int flags;
 
     /**
@@ -493,6 +502,34 @@
      */
     public String category;
 
+    private String mGroupKey;
+
+    /**
+     * Get the key used to group this notification into a cluster or stack
+     * with other notifications on devices which support such rendering.
+     */
+    public String getGroup() {
+        return mGroupKey;
+    }
+
+    private String mSortKey;
+
+    /**
+     * Get a sort key that orders this notification among other notifications from the
+     * same package. This can be useful if an external sort was already applied and an app
+     * would like to preserve this. Notifications will be sorted lexicographically using this
+     * value, although providing different priorities in addition to providing sort key may
+     * cause this value to be ignored.
+     *
+     * <p>This sort key can also be used to order members of a notification group. See
+     * {@link Builder#setGroup}.
+     *
+     * @see String#compareTo(String)
+     */
+    public String getSortKey() {
+        return mSortKey;
+    }
+
     /**
      * Additional semantic data to be carried around with this Notification.
      * <p>
@@ -659,15 +696,18 @@
      */
     public static class Action implements Parcelable {
         private final Bundle mExtras;
+        private RemoteInput[] mRemoteInputs;
 
         /**
          * Small icon representing the action.
          */
         public int icon;
+
         /**
          * Title of the action.
          */
         public CharSequence title;
+
         /**
          * Intent to send when the user invokes this action. May be null, in which case the action
          * may be rendered in a disabled presentation by the system UI.
@@ -681,19 +721,23 @@
                 actionIntent = PendingIntent.CREATOR.createFromParcel(in);
             }
             mExtras = in.readBundle();
+            mRemoteInputs = in.createTypedArray(RemoteInput.CREATOR);
         }
+
         /**
          * Use {@link Notification.Builder#addAction(int, CharSequence, PendingIntent)}.
          */
         public Action(int icon, CharSequence title, PendingIntent intent) {
-            this(icon, title, intent, new Bundle());
+            this(icon, title, intent, new Bundle(), null);
         }
 
-        private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+        private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+                RemoteInput[] remoteInputs) {
             this.icon = icon;
             this.title = title;
             this.actionIntent = intent;
             this.mExtras = extras != null ? extras : new Bundle();
+            this.mRemoteInputs = remoteInputs;
         }
 
         /**
@@ -704,13 +748,22 @@
         }
 
         /**
+         * Get the list of inputs to be collected from the user when this action is sent.
+         * May return null if no remote inputs were added.
+         */
+        public RemoteInput[] getRemoteInputs() {
+            return mRemoteInputs;
+        }
+
+        /**
          * Builder class for {@link Action} objects.
          */
-        public static class Builder {
+        public static final class Builder {
             private final int mIcon;
             private final CharSequence mTitle;
             private final PendingIntent mIntent;
             private final Bundle mExtras;
+            private ArrayList<RemoteInput> mRemoteInputs;
 
             /**
              * Construct a new builder for {@link Action} object.
@@ -719,7 +772,7 @@
              * @param intent the {@link PendingIntent} to fire when users trigger this action
              */
             public Builder(int icon, CharSequence title, PendingIntent intent) {
-                this(icon, title, intent, new Bundle());
+                this(icon, title, intent, new Bundle(), null);
             }
 
             /**
@@ -728,14 +781,20 @@
              * @param action the action to read fields from.
              */
             public Builder(Action action) {
-                this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras));
+                this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras),
+                        action.getRemoteInputs());
             }
 
-            private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+            private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+                    RemoteInput[] remoteInputs) {
                 mIcon = icon;
                 mTitle = title;
                 mIntent = intent;
                 mExtras = extras;
+                if (remoteInputs != null) {
+                    mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length);
+                    Collections.addAll(mRemoteInputs, remoteInputs);
+                }
             }
 
             /**
@@ -762,22 +821,62 @@
             }
 
             /**
+             * Add an input to be collected from the user when this action is sent.
+             * Response values can be retrieved from the fired intent by using the
+             * {@link RemoteInput#getResultsFromIntent} function.
+             * @param remoteInput a {@link RemoteInput} to add to the action
+             * @return this object for method chaining
+             */
+            public Builder addRemoteInput(RemoteInput remoteInput) {
+                if (mRemoteInputs == null) {
+                    mRemoteInputs = new ArrayList<RemoteInput>();
+                }
+                mRemoteInputs.add(remoteInput);
+                return this;
+            }
+
+            /**
+             * Apply an extender to this action builder. Extenders may be used to add
+             * metadata or change options on this builder.
+             */
+            public Builder apply(Extender extender) {
+                extender.applyTo(this);
+                return this;
+            }
+
+            /**
+             * Extender interface for use with {@link #apply}. Extenders may be used to add
+             * metadata or change options on this builder.
+             */
+            public interface Extender {
+                /**
+                 * Apply this extender to a notification action builder.
+                 * @param builder the builder to be modified.
+                 * @return the build object for chaining.
+                 */
+                public Builder applyTo(Builder builder);
+            }
+
+            /**
              * Combine all of the options that have been set and return a new {@link Action}
              * object.
              * @return the built action
              */
             public Action build() {
-                return new Action(mIcon, mTitle, mIntent, mExtras);
+                RemoteInput[] remoteInputs = mRemoteInputs != null
+                        ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null;
+                return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs);
             }
         }
 
         @Override
         public Action clone() {
             return new Action(
-                this.icon,
-                this.title,
-                this.actionIntent, // safe to alias
-                new Bundle(this.mExtras));
+                    icon,
+                    title,
+                    actionIntent, // safe to alias
+                    new Bundle(mExtras),
+                    getRemoteInputs());
         }
         @Override
         public int describeContents() {
@@ -794,6 +893,7 @@
                 out.writeInt(0);
             }
             out.writeBundle(mExtras);
+            out.writeTypedArray(mRemoteInputs, flags);
         }
         public static final Parcelable.Creator<Action> CREATOR =
                 new Parcelable.Creator<Action>() {
@@ -906,6 +1006,10 @@
 
         category = parcel.readString();
 
+        mGroupKey = parcel.readString();
+
+        mSortKey = parcel.readString();
+
         extras = parcel.readBundle(); // may be null
 
         actions = parcel.createTypedArray(Action.CREATOR); // may be null
@@ -971,6 +1075,10 @@
 
         that.category = this.category;
 
+        that.mGroupKey = this.mGroupKey;
+
+        that.mSortKey = this.mSortKey;
+
         if (this.extras != null) {
             try {
                 that.extras = new Bundle(this.extras);
@@ -1108,6 +1216,10 @@
 
         parcel.writeString(category);
 
+        parcel.writeString(mGroupKey);
+
+        parcel.writeString(mSortKey);
+
         parcel.writeBundle(extras); // null ok
 
         parcel.writeTypedArray(actions, 0); // null ok
@@ -1226,7 +1338,18 @@
         sb.append(Integer.toHexString(this.defaults));
         sb.append(" flags=0x");
         sb.append(Integer.toHexString(this.flags));
-        sb.append(" category="); sb.append(this.category);
+        if (this.category != null) {
+            sb.append(" category=");
+            sb.append(this.category);
+        }
+        if (this.mGroupKey != null) {
+            sb.append(" groupKey=");
+            sb.append(this.mGroupKey);
+        }
+        if (this.mSortKey != null) {
+            sb.append(" sortKey=");
+            sb.append(this.mSortKey);
+        }
         if (actions != null) {
             sb.append(" ");
             sb.append(actions.length);
@@ -1306,6 +1429,8 @@
         private int mProgress;
         private boolean mProgressIndeterminate;
         private String mCategory;
+        private String mGroupKey;
+        private String mSortKey;
         private Bundle mExtras;
         private int mPriority;
         private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
@@ -1718,6 +1843,51 @@
         }
 
         /**
+         * Set this notification to be part of a group of notifications sharing the same key.
+         * Grouped notifications may display in a cluster or stack on devices which
+         * support such rendering.
+         *
+         * <p>To make this notification the summary for its group, also call
+         * {@link #setGroupSummary}. A sort order can be specified for group members by using
+         * {@link #setSortKey}.
+         * @param groupKey The group key of the group.
+         * @return this object for method chaining
+         */
+        public Builder setGroup(String groupKey) {
+            mGroupKey = groupKey;
+            return this;
+        }
+
+        /**
+         * Set this notification to be the group summary for a group of notifications.
+         * Grouped notifications may display in a cluster or stack on devices which
+         * support such rendering. Requires a group key also be set using {@link #setGroup}.
+         * @param isGroupSummary Whether this notification should be a group summary.
+         * @return this object for method chaining
+         */
+        public Builder setGroupSummary(boolean isGroupSummary) {
+            setFlag(FLAG_GROUP_SUMMARY, isGroupSummary);
+            return this;
+        }
+
+        /**
+         * Set a sort key that orders this notification among other notifications from the
+         * same package. This can be useful if an external sort was already applied and an app
+         * would like to preserve this. Notifications will be sorted lexicographically using this
+         * value, although providing different priorities in addition to providing sort key may
+         * cause this value to be ignored.
+         *
+         * <p>This sort key can also be used to order members of a notification group. See
+         * {@link #setGroup}.
+         *
+         * @see String#compareTo(String)
+         */
+        public Builder setSortKey(String sortKey) {
+            mSortKey = sortKey;
+            return this;
+        }
+
+        /**
          * Merge additional metadata into this notification.
          *
          * <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -1826,6 +1996,28 @@
             return this;
         }
 
+        /**
+         * Apply an extender to this notification builder. Extenders may be used to add
+         * metadata or change options on this builder.
+         */
+        public Builder apply(Extender extender) {
+            extender.applyTo(this);
+            return this;
+        }
+
+        /**
+         * Extender interface for use with {@link #apply}. Extenders may be used to add
+         * metadata or change options on this builder.
+         */
+        public interface Extender {
+            /**
+             * Apply this extender to a notification builder.
+             * @param builder the builder to be modified.
+             * @return the build object for chaining.
+             */
+            public Builder applyTo(Builder builder);
+        }
+
         private void setFlag(int mask, boolean value) {
             if (value) {
                 mFlags |= mask;
@@ -2028,12 +2220,13 @@
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
             n.category = mCategory;
+            n.mGroupKey = mGroupKey;
+            n.mSortKey = mSortKey;
             n.priority = mPriority;
             if (mActions.size() > 0) {
                 n.actions = new Action[mActions.size()];
                 mActions.toArray(n.actions);
             }
-
             return n;
         }
 
diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java
new file mode 100644
index 0000000..9cfc541
--- /dev/null
+++ b/core/java/android/app/RemoteInput.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2014 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.app;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A {@code RemoteInput} object specifies input to be collected from a user to be passed along with
+ * an intent inside a {@link android.app.PendingIntent} that is sent.
+ * Always use {@link RemoteInput.Builder} to create instances of this class.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
+ * a Notification</a> for more information on how to use this class.
+ *
+ * <p>The following example adds a {@code RemoteInput} to a {@link Notification.Action},
+ * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}.
+ * Users are prompted to input a response when they trigger the action. The results are sent along
+ * with the intent and can be retrieved with the result key (provided to the {@link Builder}
+ * constructor) from the Bundle returned by {@link #getResultsFromIntent}.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Notification.Action action = new Notification.Action.Builder(
+ *         R.drawable.reply, &quot;Reply&quot;, actionIntent)
+ *         <b>.addRemoteInput(new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT)
+ *                 .setLabel("Quick reply").build()</b>)
+ *         .build();</pre>
+ *
+ * <p>When the {@link android.app.PendingIntent} is fired, the intent inside will contain the
+ * input results if collected. To access these results, use the {@link #getResultsFromIntent}
+ * function. The result values will present under the result key passed to the {@link Builder}
+ * constructor.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Bundle results = RemoteInput.getResultsFromIntent(intent);
+ * if (results != null) {
+ *     CharSequence quickReplyResult = results.getCharSequence(KEY_QUICK_REPLY_TEXT);
+ * }</pre>
+ */
+public final class RemoteInput implements Parcelable {
+    /** Label used to denote the clip data type used for remote input transport */
+    public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+
+    /** Extra added to a clip data intent object to hold the results bundle. */
+    public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+
+    private final String mResultKey;
+    private final CharSequence mLabel;
+    private final CharSequence[] mChoices;
+    private final boolean mAllowFreeFormInput;
+    private final Bundle mExtras;
+
+    private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices,
+            boolean allowFreeFormInput, Bundle extras) {
+        this.mResultKey = resultKey;
+        this.mLabel = label;
+        this.mChoices = choices;
+        this.mAllowFreeFormInput = allowFreeFormInput;
+        this.mExtras = extras;
+    }
+
+    /**
+     * Get the key that the result of this input will be set in from the Bundle returned by
+     * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent.
+     */
+    public String getResultKey() {
+        return mResultKey;
+    }
+
+    /**
+     * Get the label to display to users when collecting this input.
+     */
+    public CharSequence getLabel() {
+        return mLabel;
+    }
+
+    /**
+     * Get possible input choices. This can be {@code null} if there are no choices to present.
+     */
+    public CharSequence[] getChoices() {
+        return mChoices;
+    }
+
+    /**
+     * Get whether or not users can provide an arbitrary value for
+     * input. If you set this to {@code false}, users must select one of the
+     * choices in {@link #getChoices}. An {@link IllegalArgumentException} is thrown
+     * if you set this to false and {@link #getChoices} returns {@code null} or empty.
+     */
+    public boolean getAllowFreeFormInput() {
+        return mAllowFreeFormInput;
+    }
+
+    /**
+     * Get additional metadata carried around with this remote input.
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /**
+     * Builder class for {@link RemoteInput} objects.
+     */
+    public static final class Builder {
+        private final String mResultKey;
+        private CharSequence mLabel;
+        private CharSequence[] mChoices;
+        private boolean mAllowFreeFormInput = true;
+        private Bundle mExtras = new Bundle();
+
+        /**
+         * Create a builder object for {@link RemoteInput} objects.
+         * @param resultKey the Bundle key that refers to this input when collected from the user
+         */
+        public Builder(String resultKey) {
+            if (resultKey == null) {
+                throw new IllegalArgumentException("Result key can't be null");
+            }
+            mResultKey = resultKey;
+        }
+
+        /**
+         * Set a label to be displayed to the user when collecting this input.
+         * @param label The label to show to users when they input a response.
+         * @return this object for method chaining
+         */
+        public Builder setLabel(CharSequence label) {
+            mLabel = Notification.safeCharSequence(label);
+            return this;
+        }
+
+        /**
+         * Specifies choices available to the user to satisfy this input.
+         * @param choices an array of pre-defined choices for users input.
+         *        You must provide a non-null and non-empty array if
+         *        you disabled free form input using {@link #setAllowFreeFormInput}.
+         * @return this object for method chaining
+         */
+        public Builder setChoices(CharSequence[] choices) {
+            if (choices == null) {
+                mChoices = null;
+            } else {
+                mChoices = new CharSequence[choices.length];
+                for (int i = 0; i < choices.length; i++) {
+                    mChoices[i] = Notification.safeCharSequence(choices[i]);
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Specifies whether the user can provide arbitrary values.
+         *
+         * @param allowFreeFormInput The default is {@code true}.
+         *         If you specify {@code false}, you must provide a non-null
+         *         and non-empty array to {@link #setChoices} or an
+         *         {@link IllegalArgumentException} is thrown.
+         * @return this object for method chaining
+         */
+        public Builder setAllowFreeFormInput(boolean allowFreeFormInput) {
+            mAllowFreeFormInput = allowFreeFormInput;
+            return this;
+        }
+
+        /**
+         * Merge additional metadata into this builder.
+         *
+         * <p>Values within the Bundle will replace existing extras values in this Builder.
+         *
+         * @see RemoteInput#getExtras
+         */
+        public Builder addExtras(Bundle extras) {
+            if (extras != null) {
+                mExtras.putAll(extras);
+            }
+            return this;
+        }
+
+        /**
+         * Get the metadata Bundle used by this Builder.
+         *
+         * <p>The returned Bundle is shared with this Builder.
+         */
+        public Bundle getExtras() {
+            return mExtras;
+        }
+
+        /**
+         * Combine all of the options that have been set and return a new {@link RemoteInput}
+         * object.
+         */
+        public RemoteInput build() {
+            return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras);
+        }
+    }
+
+    private RemoteInput(Parcel in) {
+        mResultKey = in.readString();
+        mLabel = in.readCharSequence();
+        mChoices = in.readCharSequenceArray();
+        mAllowFreeFormInput = in.readInt() != 0;
+        mExtras = in.readBundle();
+    }
+
+    /**
+     * Get the remote input results bundle from an intent. The returned Bundle will
+     * contain a key/value for every result key populated by remote input collector.
+     * Use the {@link Bundle#getCharSequence(String)} method to retrieve a value.
+     * @param intent The intent object that fired in response to an action or content intent
+     *               which also had one or more remote input requested.
+     */
+    public static Bundle getResultsFromIntent(Intent intent) {
+        ClipData clipData = intent.getClipData();
+        if (clipData == null) {
+            return null;
+        }
+        ClipDescription clipDescription = clipData.getDescription();
+        if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
+            return null;
+        }
+        if (clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
+            return clipData.getItemAt(0).getIntent().getExtras().getParcelable(EXTRA_RESULTS_DATA);
+        }
+        return null;
+    }
+
+    /**
+     * Populate an intent object with the results gathered from remote input. This method
+     * should only be called by remote input collection services when sending results to a
+     * pending intent.
+     * @param remoteInputs The remote inputs for which results are being provided
+     * @param intent The intent to add remote inputs to. The {@link ClipData}
+     *               field of the intent will be modified to contain the results.
+     * @param results A bundle holding the remote input results. This bundle should
+     *                be populated with keys matching the result keys specified in
+     *                {@code remoteInputs} with values being the result per key.
+     */
+    public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
+            Bundle results) {
+        Bundle resultsBundle = new Bundle();
+        for (RemoteInput remoteInput : remoteInputs) {
+            Object result = results.get(remoteInput.getResultKey());
+            if (result instanceof CharSequence) {
+                resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result);
+            }
+        }
+        Intent clipIntent = new Intent();
+        clipIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
+        intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipIntent));
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mResultKey);
+        out.writeCharSequence(mLabel);
+        out.writeCharSequenceArray(mChoices);
+        out.writeInt(mAllowFreeFormInput ? 1 : 0);
+        out.writeBundle(mExtras);
+    }
+
+    public static final Creator<RemoteInput> CREATOR = new Creator<RemoteInput>() {
+        @Override
+        public RemoteInput createFromParcel(Parcel in) {
+            return new RemoteInput(in);
+        }
+
+        @Override
+        public RemoteInput[] newArray(int size) {
+            return new RemoteInput[size];
+        }
+    };
+}
diff --git a/core/java/android/app/wearable/WearableActionExtensions.java b/core/java/android/app/wearable/WearableActionExtensions.java
new file mode 100644
index 0000000..c296ef2
--- /dev/null
+++ b/core/java/android/app/wearable/WearableActionExtensions.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2014 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.app.wearable;
+
+import android.app.Notification;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Wearable extensions to notification actions. To add extensions to an action,
+ * create a new {@link WearableActionExtensions} object using
+ * {@link WearableActionExtensions.Builder} and apply it to a
+ * {@link android.app.Notification.Action.Builder}.
+ *
+ * <pre class="prettyprint">
+ * Notification.Action action = new Notification.Action.Builder(
+ *         R.drawable.archive_all, "Archive all", actionIntent)
+ *         .apply(new WearableActionExtensions.Builder()
+ *                 .setAvailableOffline(false)
+ *                 .build())
+ *         .build();
+ * </pre>
+ */
+public final class WearableActionExtensions implements Notification.Action.Builder.Extender,
+        Parcelable {
+    /** Notification action extra which contains wearable extensions */
+    private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
+
+    // Flags bitwise-ored to mFlags
+    private static final int FLAG_AVAILABLE_OFFLINE = 1 << 0;
+
+    // Default value for flags integer
+    private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE;
+
+    private final int mFlags;
+
+    private WearableActionExtensions(int flags) {
+        mFlags = flags;
+    }
+
+    private WearableActionExtensions(Parcel in) {
+        mFlags = in.readInt();
+    }
+
+    /**
+     * Create a {@link WearableActionExtensions} by reading wearable extensions present on an
+     * existing notification action.
+     * @param action the notification action to inspect.
+     * @return a new {@link WearableActionExtensions} object.
+     */
+    public static WearableActionExtensions from(Notification.Action action) {
+        WearableActionExtensions extensions = action.getExtras().getParcelable(
+                EXTRA_WEARABLE_EXTENSIONS);
+        if (extensions != null) {
+            return extensions;
+        } else {
+            // Return a WearableActionExtensions with default values.
+            return new Builder().build();
+        }
+    }
+
+    /**
+     * Get whether this action is available when the wearable device is not connected to
+     * a companion device. The user can still trigger this action when the wearable device is
+     * offline, but a visual hint will indicate that the action may not be available.
+     * Defaults to true.
+     */
+    public boolean isAvailableOffline() {
+        return (mFlags & FLAG_AVAILABLE_OFFLINE) != 0;
+    }
+
+    @Override
+    public Notification.Action.Builder applyTo(Notification.Action.Builder builder) {
+        builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this);
+        return builder;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mFlags);
+    }
+
+    /**
+     * Builder for {@link WearableActionExtensions} objects, which adds wearable extensions to
+     * notification actions. To extend an action, create an instance of this class, call the set
+     * methods present, call {@link #build}, and finally apply the options to a
+     * {@link Notification.Action.Builder} using its
+     * {@link android.app.Notification.Action.Builder#apply} method.
+     */
+    public static final class Builder {
+        private int mFlags = DEFAULT_FLAGS;
+
+        /**
+         * Construct a builder to be used for adding wearable extensions to notification actions.
+         *
+         * <pre class="prettyprint">
+         * Notification.Action action = new Notification.Action.Builder(
+         *         R.drawable.archive_all, "Archive all", actionIntent)
+         *         .apply(new WearableActionExtensions.Builder()
+         *                 .setAvailableOffline(false)
+         *                 .build())
+         *         .build();</pre>
+         */
+        public Builder() {
+        }
+
+        /**
+         * Create a {@link Builder} by reading wearable extensions present on an
+         * existing {@code WearableActionExtensions} object.
+         * @param other the existing extensions to inspect.
+         */
+        public Builder(WearableActionExtensions other) {
+            mFlags = other.mFlags;
+        }
+
+        /**
+         * Set whether this action is available when the wearable device is not connected to
+         * a companion device. The user can still trigger this action when the wearable device is
+         * offline, but a visual hint will indicate that the action may not be available.
+         * Defaults to true.
+         */
+        public Builder setAvailableOffline(boolean availableOffline) {
+            setFlag(FLAG_AVAILABLE_OFFLINE, availableOffline);
+            return this;
+        }
+
+        /**
+         * Build a new {@link WearableActionExtensions} object with the extensions
+         * currently present on this builder.
+         * @return the extensions object.
+         */
+        public WearableActionExtensions build() {
+            return new WearableActionExtensions(mFlags);
+        }
+
+        private void setFlag(int mask, boolean value) {
+            if (value) {
+                mFlags |= mask;
+            } else {
+                mFlags &= ~mask;
+            }
+        }
+    }
+
+    public static final Creator<WearableActionExtensions> CREATOR =
+            new Creator<WearableActionExtensions>() {
+        @Override
+        public WearableActionExtensions createFromParcel(Parcel in) {
+            return new WearableActionExtensions(in);
+        }
+
+        @Override
+        public WearableActionExtensions[] newArray(int size) {
+            return new WearableActionExtensions[size];
+        }
+    };
+}
diff --git a/core/java/android/app/wearable/WearableNotificationExtensions.java b/core/java/android/app/wearable/WearableNotificationExtensions.java
new file mode 100644
index 0000000..d433613
--- /dev/null
+++ b/core/java/android/app/wearable/WearableNotificationExtensions.java
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2014 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.app.wearable;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Gravity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Helper class that contains wearable extensions for notifications.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/creating.html">Creating Notifications
+ * for Android Wear</a> for more information on how to use this class.
+ * <p>
+ * To create a notification with wearable extensions:
+ * <ol>
+ *   <li>Create a {@link Notification.Builder}, setting any desired
+ *   properties.
+ *   <li>Create a {@link WearableNotificationExtensions.Builder}.
+ *   <li>Set wearable-specific properties using the
+ *   {@code add} and {@code set} methods of {@link WearableNotificationExtensions.Builder}.
+ *   <li>Call {@link WearableNotificationExtensions.Builder#build} to build the extensions
+ *   object.
+ *   <li>Call {@link Notification.Builder#apply} to apply the extensions to a notification.
+ *   <li>Post the notification to the notification system with the
+ *   {@code NotificationManager.notify(...)} methods.
+ * </ol>
+ *
+ * <pre class="prettyprint">
+ * Notification notif = new Notification.Builder(mContext)
+ *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
+ *         .setContentText(subject)
+ *         .setSmallIcon(R.drawable.new_mail)
+ *         .apply(new new WearableNotificationExtensions.Builder()
+ *                 .setContentIcon(R.drawable.new_mail)
+ *                 .build())
+ *         .build();
+ * NotificationManager notificationManger =
+ *         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ * notificationManger.notify(0, notif);</pre>
+ *
+ * <p>Wearable extensions can be accessed on an existing notification by using the
+ * {@link WearableNotificationExtensions#from} function.
+ *
+ * <pre class="prettyprint">
+ * WearableNotificationExtensions wearableExtensions = WearableNotificationExtensions.from(
+ *         notification);
+ * Notification[] pages = wearableExtensions.getPages();
+ * </pre>
+ */
+public final class WearableNotificationExtensions implements Notification.Builder.Extender,
+        Parcelable {
+    /**
+     * Sentinel value for an action index that is unset.
+     */
+    public static final int UNSET_ACTION_INDEX = -1;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification with
+     * default sizing.
+     * <p>For custom display notifications created using {@link Builder#setDisplayIntent},
+     * the default is {@link #SIZE_LARGE}. All other notifications size automatically based
+     * on their content.
+     */
+    public static final int SIZE_DEFAULT = 0;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with an extra small size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_XSMALL = 1;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with a small size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_SMALL = 2;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with a medium size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_MEDIUM = 3;
+
+    /**
+     * Size value for use with {@link Builder#setCustomSizePreset} to show this notification
+     * with a large size.
+     * <p>This value is only applicable for custom display notifications created using
+     * {@link Builder#setDisplayIntent}.
+     */
+    public static final int SIZE_LARGE = 4;
+
+    /** Notification extra which contains wearable extensions */
+    static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
+
+    // Flags bitwise-ored to mFlags
+    static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 1 << 0;
+    static final int FLAG_HINT_HIDE_ICON = 1 << 1;
+    static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
+    static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
+
+    // Default value for flags integer
+    static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
+
+    private final Notification.Action[] mActions;
+    private final int mFlags;
+    private final PendingIntent mDisplayIntent;
+    private final Notification[] mPages;
+    private final Bitmap mBackground;
+    private final int mContentIcon;
+    private final int mContentIconGravity;
+    private final int mContentActionIndex;
+    private final int mCustomSizePreset;
+    private final int mCustomContentHeight;
+    private final int mGravity;
+
+    private WearableNotificationExtensions(Notification.Action[] actions, int flags,
+            PendingIntent displayIntent, Notification[] pages, Bitmap background,
+            int contentIcon, int contentIconGravity, int contentActionIndex,
+            int customSizePreset, int customContentHeight, int gravity) {
+        mActions = actions;
+        mFlags = flags;
+        mDisplayIntent = displayIntent;
+        mPages = pages;
+        mBackground = background;
+        mContentIcon = contentIcon;
+        mContentIconGravity = contentIconGravity;
+        mContentActionIndex = contentActionIndex;
+        mCustomSizePreset = customSizePreset;
+        mCustomContentHeight = customContentHeight;
+        mGravity = gravity;
+    }
+
+    private WearableNotificationExtensions(Parcel in) {
+        mActions = in.createTypedArray(Notification.Action.CREATOR);
+        mFlags = in.readInt();
+        mDisplayIntent = in.readParcelable(PendingIntent.class.getClassLoader());
+        mPages = in.createTypedArray(Notification.CREATOR);
+        mBackground = in.readParcelable(Bitmap.class.getClassLoader());
+        mContentIcon = in.readInt();
+        mContentIconGravity = in.readInt();
+        mContentActionIndex = in.readInt();
+        mCustomSizePreset = in.readInt();
+        mCustomContentHeight = in.readInt();
+        mGravity = in.readInt();
+    }
+
+    /**
+     * Create a {@link WearableNotificationExtensions} by reading wearable extensions present on an
+     * existing notification.
+     * @param notif the notification to inspect.
+     * @return a new {@link WearableNotificationExtensions} object.
+     */
+    public static WearableNotificationExtensions from(Notification notif) {
+        WearableNotificationExtensions extensions = notif.extras.getParcelable(
+                EXTRA_WEARABLE_EXTENSIONS);
+        if (extensions != null) {
+            return extensions;
+        } else {
+            // Return a WearableNotificationExtensions with default values.
+            return new Builder().build();
+        }
+    }
+
+    /**
+     * Apply wearable extensions to a notification that is being built. This is typically
+     * called by {@link Notification.Builder#apply} method of {@link Notification.Builder}.
+     */
+    @Override
+    public Notification.Builder applyTo(Notification.Builder builder) {
+        builder.getExtras().putParcelable(EXTRA_WEARABLE_EXTENSIONS, this);
+        return builder;
+    }
+
+    /**
+     * Get the number of wearable actions present on this notification.
+     *
+     * @return the number of wearable actions for this notification
+     */
+    public int getActionCount() {
+        return mActions.length;
+    }
+
+    /**
+     * Get a {@link Notification.Action} for the wearable action at {@code actionIndex}.
+     * @param actionIndex the index of the desired wearable action
+     */
+    public Notification.Action getAction(int actionIndex) {
+        return mActions[actionIndex];
+    }
+
+    /**
+     * Get the wearable actions present on this notification.
+     */
+    public Notification.Action[] getActions() {
+        return mActions;
+    }
+
+    /**
+     * Get the intent to launch inside of an activity view when displaying this
+     * notification. This {@code PendingIntent} should be for an activity.
+     */
+    public PendingIntent getDisplayIntent() {
+        return mDisplayIntent;
+    }
+
+    /**
+     * Get the array of additional pages of content for displaying this notification. The
+     * current notification forms the first page, and elements within this array form
+     * subsequent pages. This field can be used to separate a notification into multiple
+     * sections.
+     * @return the pages for this notification
+     */
+    public Notification[] getPages() {
+        return mPages;
+    }
+
+    /**
+     * Get a background image to be displayed behind the notification content.
+     * Contrary to the {@link Notification.BigPictureStyle}, this background
+     * will work with any notification style.
+     *
+     * @return the background image
+     * @see Builder#setBackground
+     */
+    public Bitmap getBackground() {
+        return mBackground;
+    }
+
+    /**
+     * Get an icon that goes with the content of this notification.
+     */
+    public int getContentIcon() {
+        return mContentIcon;
+    }
+
+    /**
+     * Get the gravity that the content icon should have within the notification display.
+     * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default
+     * value is {@link android.view.Gravity#END}.
+     * @see #getContentIcon
+     */
+    public int getContentIconGravity() {
+        return mContentIconGravity;
+    }
+
+    /**
+     * Get the action index of an action from this notification to show as clickable with
+     * the content of this notification page. When the user clicks this notification page,
+     * this action will trigger. This action will no longer display separately from the
+     * notification content. The action's icon will display with optional subtext provided
+     * by the action's title.
+     *
+     * <p>If wearable specific actions are present, this index will apply to that list,
+     * otherwise it will apply to the main notification's actions list.
+     */
+    public int getContentAction() {
+        return mContentActionIndex;
+    }
+
+    /**
+     * Get the gravity that this notification should have within the available viewport space.
+     * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and
+     * {@link android.view.Gravity#BOTTOM}. The default value is
+     * {@link android.view.Gravity#BOTTOM}.
+     */
+    public int getGravity() {
+        return mGravity;
+    }
+
+    /**
+     * Get the custom size preset for the display of this notification out of the available
+     * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}.
+     * <p>Some custom size presets are only applicable for custom display notifications created
+     * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in question.
+     * See also {@link Builder#setCustomContentHeight} and {@link Builder#setCustomSizePreset}.
+     */
+    public int getCustomSizePreset() {
+        return mCustomSizePreset;
+    }
+
+    /**
+     * Get the custom height in pixels for the display of this notification's content.
+     * <p>This option is only available for custom display notifications created
+     * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and
+     * {@link Builder#setCustomContentHeight}.
+     */
+    public int getCustomContentHeight() {
+        return mCustomContentHeight;
+    }
+
+    /**
+     * Get whether the scrolling position for the contents of this notification should start
+     * at the bottom of the contents instead of the top when the contents are too long to
+     * display within the screen. Default is false (start scroll at the top).
+     */
+    public boolean getStartScrollBottom() {
+        return (mFlags & FLAG_START_SCROLL_BOTTOM) != 0;
+    }
+
+    /**
+     * Get whether the content intent is available when the wearable device is not connected
+     * to a companion device.  The user can still trigger this intent when the wearable device is
+     * offline, but a visual hint will indicate that the content intent may not be available.
+     * Defaults to true.
+     */
+    public boolean getContentIntentAvailableOffline() {
+        return (mFlags & FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE) != 0;
+    }
+
+    /**
+     * Get a hint that this notification's icon should not be displayed.
+     * @return {@code true} if this icon should not be displayed, false otherwise.
+     * The default value is {@code false} if this was never set.
+     */
+    public boolean getHintHideIcon() {
+        return (mFlags & FLAG_HINT_HIDE_ICON) != 0;
+    }
+
+    /**
+     * Get a visual hint that only the background image of this notification should be
+     * displayed, and other semantic content should be hidden. This hint is only applicable
+     * to sub-pages added using {@link Builder#addPage}.
+     */
+    public boolean getHintShowBackgroundOnly() {
+        return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeTypedArray(mActions, flags);
+        out.writeInt(mFlags);
+        out.writeParcelable(mDisplayIntent, flags);
+        out.writeTypedArray(mPages, flags);
+        out.writeParcelable(mBackground, flags);
+        out.writeInt(mContentIcon);
+        out.writeInt(mContentIconGravity);
+        out.writeInt(mContentActionIndex);
+        out.writeInt(mCustomSizePreset);
+        out.writeInt(mCustomContentHeight);
+        out.writeInt(mGravity);
+    }
+
+    /**
+     * Builder to apply wearable notification extensions to a {@link Notification.Builder}
+     * object.
+     *
+     * <p>You can chain the "set" methods for this builder in any order,
+     * but you must call the {@link #build} method and then the {@link Notification.Builder#apply}
+     * method to apply your extensions to a notification.
+     *
+     * <pre class="prettyprint">
+     * Notification notif = new Notification.Builder(mContext)
+     *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
+     *         .setContentText(subject)
+     *         .setSmallIcon(R.drawable.new_mail);
+     *         .apply(new WearableNotificationExtensions.Builder()
+     *                 .setContentIcon(R.drawable.new_mail)
+     *                 .build())
+     *         .build();
+     * NotificationManager notificationManger =
+     *         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+     * notificationManager.notify(0, notif);</pre>
+     */
+    public static final class Builder {
+        private final List<Notification.Action> mActions =
+                new ArrayList<Notification.Action>();
+        private int mFlags = DEFAULT_FLAGS;
+        private PendingIntent mDisplayIntent;
+        private final List<Notification> mPages = new ArrayList<Notification>();
+        private Bitmap mBackground;
+        private int mContentIcon;
+        private int mContentIconGravity = Gravity.END;
+        private int mContentActionIndex = UNSET_ACTION_INDEX;
+        private int mCustomContentHeight;
+        private int mCustomSizePreset = SIZE_DEFAULT;
+        private int mGravity = Gravity.BOTTOM;
+
+        /**
+         * Construct a builder to be used for adding wearable extensions to notifications.
+         *
+         * <pre class="prettyprint">
+         * Notification notif = new Notification.Builder(mContext)
+         *         .setContentTitle(&quot;New mail from &quot; + sender.toString())
+         *         .setContentText(subject)
+         *         .setSmallIcon(R.drawable.new_mail);
+         *         .apply(new WearableNotificationExtensions.Builder()
+         *                 .setContentIcon(R.drawable.new_mail)
+         *                 .build())
+         *         .build();
+         * NotificationManager notificationManger =
+         *         (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+         * notificationManager.notify(0, notif);</pre>
+         */
+        public Builder() {
+        }
+
+        /**
+         * Create a {@link Builder} by reading wearable extensions present on an
+         * existing {@code WearableNotificationExtensions} object.
+         * @param other the existing extensions to inspect.
+         */
+        public Builder(WearableNotificationExtensions other) {
+            Collections.addAll(mActions, other.mActions);
+            mFlags = other.mFlags;
+            mDisplayIntent = other.mDisplayIntent;
+            Collections.addAll(mPages, other.mPages);
+            mBackground = other.mBackground;
+            mContentIcon = other.mContentIcon;
+            mContentIconGravity = other.mContentIconGravity;
+            mContentActionIndex = other.mContentActionIndex;
+            mCustomContentHeight = other.mCustomContentHeight;
+            mCustomSizePreset = other.mCustomSizePreset;
+            mGravity = other.mGravity;
+        }
+
+        /**
+         * Add a wearable action to this notification.
+         *
+         * <p>When wearable actions are added using this method, the set of actions that
+         * show on a wearable device splits from devices that only show actions added
+         * using {@link android.app.Notification.Builder#addAction}. This allows for customization
+         * of which actions display on different devices.
+         *
+         * @param action the action to add to this notification
+         * @return this object for method chaining
+         * @see Notification.Action
+         */
+        public Builder addAction(Notification.Action action) {
+            mActions.add(action);
+            return this;
+        }
+
+        /**
+         * Adds wearable actions to this notification.
+         *
+         * <p>When wearable actions are added using this method, the set of actions that
+         * show on a wearable device splits from devices that only show actions added
+         * using {@link android.app.Notification.Builder#addAction}. This allows for customization
+         * of which actions display on different devices.
+         *
+         * @param actions the actions to add to this notification
+         * @return this object for method chaining
+         * @see Notification.Action
+         */
+        public Builder addActions(List<Notification.Action> actions) {
+            mActions.addAll(actions);
+            return this;
+        }
+
+        /**
+         * Clear all wearable actions present on this builder.
+         * @return this object for method chaining.
+         * @see #addAction
+         */
+        public Builder clearActions() {
+            mActions.clear();
+            return this;
+        }
+
+        /**
+         * Set an intent to launch inside of an activity view when displaying
+         * this notification. This {@link android.app.PendingIntent} should be for an activity.
+         *
+         * @param intent the {@link android.app.PendingIntent} for an activity
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getDisplayIntent
+         */
+        public Builder setDisplayIntent(PendingIntent intent) {
+            mDisplayIntent = intent;
+            return this;
+        }
+
+        /**
+         * Add an additional page of content to display with this notification. The current
+         * notification forms the first page, and pages added using this function form
+         * subsequent pages. This field can be used to separate a notification into multiple
+         * sections.
+         *
+         * @param page the notification to add as another page
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getPages
+         */
+        public Builder addPage(Notification page) {
+            mPages.add(page);
+            return this;
+        }
+
+        /**
+         * Add additional pages of content to display with this notification. The current
+         * notification forms the first page, and pages added using this function form
+         * subsequent pages. This field can be used to separate a notification into multiple
+         * sections.
+         *
+         * @param pages a list of notifications
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getPages
+         */
+        public Builder addPages(List<Notification> pages) {
+            mPages.addAll(pages);
+            return this;
+        }
+
+        /**
+         * Clear all additional pages present on this builder.
+         * @return this object for method chaining.
+         * @see #addPage
+         */
+        public Builder clearPages() {
+            mPages.clear();
+            return this;
+        }
+
+        /**
+         * Set a background image to be displayed behind the notification content.
+         * Contrary to the {@link Notification.BigPictureStyle}, this background
+         * will work with any notification style.
+         *
+         * @param background the background bitmap
+         * @return this object for method chaining
+         * @see WearableNotificationExtensions#getBackground
+         */
+        public Builder setBackground(Bitmap background) {
+            mBackground = background;
+            return this;
+        }
+
+        /**
+         * Set an icon that goes with the content of this notification.
+         */
+        public Builder setContentIcon(int icon) {
+            mContentIcon = icon;
+            return this;
+        }
+
+        /**
+         * Set the gravity that the content icon should have within the notification display.
+         * Supported values include {@link Gravity#START} and {@link Gravity#END}. The default
+         * value is {@link android.view.Gravity#END}.
+         * @see #setContentIcon
+         */
+        public Builder setContentIconGravity(int contentIconGravity) {
+            mContentIconGravity = contentIconGravity;
+            return this;
+        }
+
+        /**
+         * Set an action from this notification's actions to be clickable with the content of
+         * this notification page. This action will no longer display separately from the
+         * notification content. This action's icon will display with optional subtext provided
+         * by the action's title.
+         * @param actionIndex The index of the action to hoist on the current notification page.
+         *                    If wearable actions are present, this index will apply to that list,
+         *                    otherwise it will apply to the main notification's actions list.
+         */
+        public Builder setContentAction(int actionIndex) {
+            mContentActionIndex = actionIndex;
+            return this;
+        }
+
+        /**
+         * Set the gravity that this notification should have within the available viewport space.
+         * Supported values include {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL} and
+         * {@link Gravity#BOTTOM}. The default value is {@link Gravity#BOTTOM}.
+         */
+        public Builder setGravity(int gravity) {
+            mGravity = gravity;
+            return this;
+        }
+
+        /**
+         * Set the custom size preset for the display of this notification out of the available
+         * presets found in {@link WearableNotificationExtensions}, e.g. {@link #SIZE_LARGE}.
+         * <p>Some custom size presets are only applicable for custom display notifications created
+         * using {@link Builder#setDisplayIntent}. Check the documentation for the preset in
+         * question. See also {@link Builder#setCustomContentHeight} and
+         * {@link #getCustomSizePreset}.
+         */
+        public Builder setCustomSizePreset(int sizePreset) {
+            mCustomSizePreset = sizePreset;
+            return this;
+        }
+
+        /**
+         * Set the custom height in pixels for the display of this notification's content.
+         * <p>This option is only available for custom display notifications created
+         * using {@link Builder#setDisplayIntent}. See also {@link Builder#setCustomSizePreset} and
+         * {@link #getCustomContentHeight}.
+         */
+        public Builder setCustomContentHeight(int height) {
+            mCustomContentHeight = height;
+            return this;
+        }
+
+        /**
+         * Set whether the scrolling position for the contents of this notification should start
+         * at the bottom of the contents instead of the top when the contents are too long to
+         * display within the screen.  Default is false (start scroll at the top).
+         */
+        public Builder setStartScrollBottom(boolean startScrollBottom) {
+            setFlag(FLAG_START_SCROLL_BOTTOM, startScrollBottom);
+            return this;
+        }
+
+        /**
+         * Set whether the content intent is available when the wearable device is not connected
+         * to a companion device.  The user can still trigger this intent when the wearable device
+         * is offline, but a visual hint will indicate that the content intent may not be available.
+         * Defaults to true.
+         */
+        public Builder setContentIntentAvailableOffline(boolean contentIntentAvailableOffline) {
+            setFlag(FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE, contentIntentAvailableOffline);
+            return this;
+        }
+
+        /**
+         * Set a hint that this notification's icon should not be displayed.
+         * @param hintHideIcon {@code true} to hide the icon, {@code false} otherwise.
+         * @return this object for method chaining
+         */
+        public Builder setHintHideIcon(boolean hintHideIcon) {
+            setFlag(FLAG_HINT_HIDE_ICON, hintHideIcon);
+            return this;
+        }
+
+        /**
+         * Set a visual hint that only the background image of this notification should be
+         * displayed, and other semantic content should be hidden. This hint is only applicable
+         * to sub-pages added using {@link #addPage}.
+         */
+        public Builder setHintShowBackgroundOnly(boolean hintShowBackgroundOnly) {
+            setFlag(FLAG_HINT_SHOW_BACKGROUND_ONLY, hintShowBackgroundOnly);
+            return this;
+        }
+
+        /**
+         * Build a new {@link WearableNotificationExtensions} object with the extensions
+         * currently present on this builder.
+         * @return the extensions object.
+         */
+        public WearableNotificationExtensions build() {
+            return new WearableNotificationExtensions(
+                    mActions.toArray(new Notification.Action[mActions.size()]), mFlags,
+                    mDisplayIntent, mPages.toArray(new Notification[mPages.size()]),
+                    mBackground, mContentIcon, mContentIconGravity, mContentActionIndex,
+                    mCustomSizePreset, mCustomContentHeight, mGravity);
+        }
+
+        private void setFlag(int mask, boolean value) {
+            if (value) {
+                mFlags |= mask;
+            } else {
+                mFlags &= ~mask;
+            }
+        }
+    }
+
+    public static final Creator<WearableNotificationExtensions> CREATOR =
+            new Creator<WearableNotificationExtensions>() {
+        @Override
+        public WearableNotificationExtensions createFromParcel(Parcel in) {
+            return new WearableNotificationExtensions(in);
+        }
+
+        @Override
+        public WearableNotificationExtensions[] newArray(int size) {
+            return new WearableNotificationExtensions[size];
+        }
+    };
+}
diff --git a/docs/html/distribute/essentials/gpfe-guidelines.jd b/docs/html/distribute/essentials/gpfe-guidelines.jd
index 8b47671..799009f 100644
--- a/docs/html/distribute/essentials/gpfe-guidelines.jd
+++ b/docs/html/distribute/essentials/gpfe-guidelines.jd
@@ -115,10 +115,6 @@
   <hr>
 </div>
 
-<div class="figure">
-  <img src="{@docRoot}images/gp-edu-monetize.png">
-</div>
-
 <p>
   In-app purchase is currently not supported with Google Play for Education, so
   a student device will block any transactions. To avoid confusion, be sure to