Added the possibility to show custom notifications decorated.

Bug: 26961842
Change-Id: I3966a4e6ecb05b9f284ec5b244b2594f78bcb337
diff --git a/api/current.txt b/api/current.txt
index dc7e280..1b67c95 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5131,6 +5131,11 @@
     method public android.app.PendingIntent getReplyPendingIntent();
   }
 
+  public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style {
+    ctor public Notification.DecoratedCustomViewStyle();
+    ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder);
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 61f72f3..55863d4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5263,6 +5263,11 @@
     method public android.app.PendingIntent getReplyPendingIntent();
   }
 
+  public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style {
+    ctor public Notification.DecoratedCustomViewStyle();
+    ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder);
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 17d788f..b1fca9e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5131,6 +5131,11 @@
     method public android.app.PendingIntent getReplyPendingIntent();
   }
 
+  public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style {
+    ctor public Notification.DecoratedCustomViewStyle();
+    ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder);
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 35b7c39..01a9ff98 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3338,7 +3338,7 @@
          *   3. Standard template view
          */
         public RemoteViews makeContentView() {
-            if (mN.contentView != null) {
+            if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
                 return mN.contentView;
             } else if (mStyle != null) {
                 final RemoteViews styleView = mStyle.makeContentView();
@@ -3354,7 +3354,8 @@
          */
         public RemoteViews makeBigContentView() {
             RemoteViews result = null;
-            if (mN.bigContentView != null) {
+            if (mN.bigContentView != null
+                    && (mStyle == null || !mStyle.displayCustomViewInline())) {
                 return mN.bigContentView;
             } else if (mStyle != null) {
                 result = mStyle.makeBigContentView();
@@ -3395,7 +3396,8 @@
          * Construct a RemoteViews for the final heads-up notification layout.
          */
         public RemoteViews makeHeadsUpContentView() {
-            if (mN.headsUpContentView != null) {
+            if (mN.headsUpContentView != null
+                    && (mStyle == null ||  !mStyle.displayCustomViewInline())) {
                 return mN.headsUpContentView;
             } else if (mStyle != null) {
                     final RemoteViews styleView = mStyle.makeHeadsUpContentView();
@@ -3556,8 +3558,9 @@
         }
 
         private static Class<? extends Style> getNotificationStyleClass(String templateClass) {
-            Class<? extends Style>[] classes = new Class[]{
-                    BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class};
+            Class<? extends Style>[] classes = new Class[] {
+                    BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
+                    DecoratedCustomViewStyle.class };
             for (Class<? extends Style> innerClass : classes) {
                 if (templateClass.equals(innerClass.getName())) {
                     return innerClass;
@@ -3819,6 +3822,14 @@
         public boolean hasSummaryInHeader() {
             return true;
         }
+
+        /**
+         * @hide
+         * @return Whether custom content views are displayed inline in the style
+         */
+        public boolean displayCustomViewInline() {
+            return false;
+        }
     }
 
     /**
@@ -4455,6 +4466,115 @@
         }
     }
 
+    /**
+     * Notification style for custom views that are decorated by the system
+     *
+     * <p>Instead of providing a notification that is completely custom, a developer can set this
+     * style and still obtain system decorations like the notification header with the expand
+     * affordance and actions.
+     *
+     * <p>Use {@link android.app.Notification.Builder#setCustomContentView(RemoteViews)},
+     * {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and
+     * {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the
+     * corresponding custom views to display.
+     *
+     * To use this style with your Notification, feed it to
+     * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
+     * <pre class="prettyprint">
+     * Notification noti = new Notification.Builder()
+     *     .setSmallIcon(R.drawable.ic_stat_player)
+     *     .setLargeIcon(albumArtBitmap))
+     *     .setCustomContentView(contentView);
+     *     .setStyle(<b>new Notification.DecoratedCustomViewStyle()</b>)
+     *     .build();
+     * </pre>
+     */
+    public static class DecoratedCustomViewStyle extends Style {
+
+        public DecoratedCustomViewStyle() {
+        }
+
+        public DecoratedCustomViewStyle(Builder builder) {
+            setBuilder(builder);
+        }
+
+        /**
+         * @hide
+         */
+        public boolean displayCustomViewInline() {
+            return true;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public RemoteViews makeContentView() {
+            return makeStandardTemplateWithCustomContent(mBuilder.mN.contentView);
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public RemoteViews makeBigContentView() {
+            return makeDecoratedBigContentView();
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public RemoteViews makeHeadsUpContentView() {
+            return makeDecoratedHeadsUpContentView();
+        }
+
+        /**
+         * @hide
+         */
+        private RemoteViews makeDecoratedHeadsUpContentView() {
+            RemoteViews headsUpContentView = mBuilder.mN.headsUpContentView == null
+                    ? mBuilder.mN.contentView
+                    : mBuilder.mN.headsUpContentView;
+            if (mBuilder.mActions.size() == 0) {
+               return makeStandardTemplateWithCustomContent(headsUpContentView);
+            }
+            RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
+                        mBuilder.getBigBaseLayoutResource());
+            remoteViews.removeAllViews(R.id.notification_main_column);
+            remoteViews.addView(R.id.notification_main_column, headsUpContentView);
+            return remoteViews;
+        }
+
+        /**
+         * @hide
+         */
+        private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) {
+            RemoteViews remoteViews = mBuilder.applyStandardTemplate(
+                    mBuilder.getBaseLayoutResource());
+            remoteViews.removeAllViews(R.id.notification_main_column);
+            remoteViews.addView(R.id.notification_main_column, customContent);
+            return remoteViews;
+        }
+
+        /**
+         * @hide
+         */
+        private RemoteViews makeDecoratedBigContentView() {
+            RemoteViews bigContentView = mBuilder.mN.bigContentView == null
+                    ? mBuilder.mN.contentView
+                    : mBuilder.mN.bigContentView;
+            if (mBuilder.mActions.size() == 0) {
+                return makeStandardTemplateWithCustomContent(bigContentView);
+            }
+            RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
+                    mBuilder.getBigBaseLayoutResource());
+            remoteViews.removeAllViews(R.id.notification_main_column);
+            remoteViews.addView(R.id.notification_main_column, bigContentView);
+            return remoteViews;
+        }
+    }
+
     // When adding a new Style subclass here, don't forget to update
     // Builder.getNotificationStyleClass.