1826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
3826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake *
4826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * Licensed under the Apache License, Version 2.0 (the "License");
5826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * you may not use this file except in compliance with the License.
6826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * You may obtain a copy of the License at
7826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake *
8826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake *      http://www.apache.org/licenses/LICENSE-2.0
9826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake *
10826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * Unless required by applicable law or agreed to in writing, software
11826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * distributed under the License is distributed on an "AS IS" BASIS,
12826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * See the License for the specific language governing permissions and
14826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake * limitations under the License.
15826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake */
16826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.media.app;
18826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.core.app.NotificationCompat.COLOR_DEFAULT;
21826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
22826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.app.Notification;
23826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.app.PendingIntent;
24826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.media.session.MediaSession;
25826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.os.Build;
26826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.os.Bundle;
27826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.os.IBinder;
28826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakeimport android.os.Parcel;
2989febf83e2bd3720923474006bcdf6c91a3b88f2Aurimas Liutikasimport android.support.v4.media.session.MediaSessionCompat;
3089febf83e2bd3720923474006bcdf6c91a3b88f2Aurimas Liutikasimport android.view.View;
3189febf83e2bd3720923474006bcdf6c91a3b88f2Aurimas Liutikasimport android.widget.RemoteViews;
3289febf83e2bd3720923474006bcdf6c91a3b88f2Aurimas Liutikas
33ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RequiresApi;
34ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo;
35ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.app.BundleCompat;
36ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.app.NotificationBuilderWithBuilderAccessor;
3789febf83e2bd3720923474006bcdf6c91a3b88f2Aurimas Liutikasimport androidx.media.R;
38826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
39826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake/**
40ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Class containing media specfic {@link androidx.core.app.NotificationCompat.Style styles}
41ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * that you can use with {@link androidx.core.app.NotificationCompat.Builder#setStyle}.
42826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake */
43826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lakepublic class NotificationCompat {
44826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
45826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    private NotificationCompat() {
46826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    }
47826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
48826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    /**
49826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Notification style for media playback notifications.
50826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
51826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * In the expanded form, up to 5
52ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Action actions} specified with
53ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder
54826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * #addAction(int, CharSequence, PendingIntent) addAction} will be shown as icon-only
55826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * pushbuttons, suitable for transport controls. The Bitmap given to
56ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder
57826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * #setLargeIcon(android.graphics.Bitmap) setLargeIcon()} will
58826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * be treated as album artwork.
59826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
60826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Unlike the other styles provided here, MediaStyle can also modify the standard-size
61826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * content view; by providing action indices to
62826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * {@link #setShowActionsInCompactView(int...)} you can promote up to 3 actions to be displayed
63826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * in the standard view alongside the usual content.
64826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
65826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Notifications created with MediaStyle will have their category set to
66ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat#CATEGORY_TRANSPORT CATEGORY_TRANSPORT}
67826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * unless you set a different category using
68ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder#setCategory(String)
69826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * setCategory()}.
70826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
71826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Finally, if you attach a {@link MediaSession.Token} using
72ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link NotificationCompat.MediaStyle#setMediaSession}, the
73826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * System UI can identify this as a notification representing an active media session and
74826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * respond accordingly (by showing album artwork in the lockscreen, for example).
75826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
76826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * To use this style with your Notification, feed it to
77ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder#setStyle} like so:
78826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * <pre class="prettyprint">
79826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Notification noti = new NotificationCompat.Builder()
80826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setSmallIcon(R.drawable.ic_stat_player)
81826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setContentTitle(&quot;Track title&quot;)
82826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setContentText(&quot;Artist - Album&quot;)
83826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setLargeIcon(albumArtBitmap))
84826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setStyle(<b>new NotificationCompat.MediaStyle()</b>
85826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *         .setMediaSession(mySession))
86826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .build();
87826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * </pre>
88826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
89826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * @see Notification#bigContentView
90826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     */
91ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas    public static class MediaStyle extends androidx.core.app.NotificationCompat.Style {
92826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
93826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
94826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * Extracts a {@link MediaSessionCompat.Token} from the extra values
95826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * in the {@link MediaStyle} {@link Notification notification}.
96826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
97826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @param notification The notification to extract a {@link MediaSessionCompat.Token} from.
98826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @return The {@link MediaSessionCompat.Token} in the {@code notification} if it contains,
99826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *         null otherwise.
100826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
101826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public static MediaSessionCompat.Token getMediaSession(Notification notification) {
102ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas            Bundle extras = androidx.core.app.NotificationCompat.getExtras(notification);
103826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (extras != null) {
104826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                if (Build.VERSION.SDK_INT >= 21) {
105826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    Object tokenInner = extras.getParcelable(
106ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                            androidx.core.app.NotificationCompat.EXTRA_MEDIA_SESSION);
107826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    if (tokenInner != null) {
108826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        return MediaSessionCompat.Token.fromToken(tokenInner);
109826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    }
110826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                } else {
111826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    IBinder tokenInner = BundleCompat.getBinder(extras,
112ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                            androidx.core.app.NotificationCompat.EXTRA_MEDIA_SESSION);
113826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    if (tokenInner != null) {
114826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        Parcel p = Parcel.obtain();
115826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        p.writeStrongBinder(tokenInner);
116826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        p.setDataPosition(0);
117826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        MediaSessionCompat.Token token =
118826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                                MediaSessionCompat.Token.CREATOR.createFromParcel(p);
119826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        p.recycle();
120826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        return token;
121826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    }
122826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                }
123826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
124826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return null;
125826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
126826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
127826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        private static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3;
128826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        private static final int MAX_MEDIA_BUTTONS = 5;
129826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
130826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        int[] mActionsToShowInCompact = null;
131826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        MediaSessionCompat.Token mToken;
132826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        boolean mShowCancelButton;
133826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        PendingIntent mCancelButtonIntent;
134826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
135826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public MediaStyle() {
136826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
137826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
138ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas        public MediaStyle(androidx.core.app.NotificationCompat.Builder builder) {
139826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            setBuilder(builder);
140826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
141826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
142826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
143826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * Requests up to 3 actions (by index in the order of addition) to be shown in the compact
144826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * notification view.
145826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
146826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @param actions the indices of the actions to show in the compact notification view
147826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
148826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public MediaStyle setShowActionsInCompactView(int...actions) {
149826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            mActionsToShowInCompact = actions;
150826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return this;
151826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
152826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
153826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
154826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * Attaches a {@link MediaSessionCompat.Token} to this Notification
155826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * to provide additional playback information and control to the SystemUI.
156826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
157826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public MediaStyle setMediaSession(MediaSessionCompat.Token token) {
158826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            mToken = token;
159826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return this;
160826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
161826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
162826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
163826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * Sets whether a cancel button at the top right should be shown in the notification on
164826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * platforms before Lollipop.
165826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
166826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * <p>Prior to Lollipop, there was a bug in the framework which prevented the developer to
167826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * make a notification dismissable again after having used the same notification as the
168826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * ongoing notification for a foreground service. When the notification was posted by
169826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * {@link android.app.Service#startForeground}, but then the service exited foreground mode
170826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * via {@link android.app.Service#stopForeground}, without removing the notification, the
171826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * notification stayed ongoing, and thus not dismissable.
172826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
173826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * <p>This is a common scenario for media notifications, as this is exactly the service
174826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * lifecycle that happens when playing/pausing media. Thus, a workaround is provided by the
175826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * support library: Instead of making the notification ongoing depending on the playback
176826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * state, the support library provides the ability to add an explicit cancel button to the
177826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * notification.
178826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
179826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * <p>Note that the notification is enforced to be ongoing if a cancel button is shown to
180826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * provide a consistent user experience.
181826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
182826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * <p>Also note that this method is a no-op when running on Lollipop and later.
183826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
184826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @param show whether to show a cancel button
185826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
186826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public MediaStyle setShowCancelButton(boolean show) {
187826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT < 21) {
188826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                mShowCancelButton = show;
189826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
190826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return this;
191826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
192826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
193826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
194826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * Sets the pending intent to be sent when the cancel button is pressed. See {@link
195826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * #setShowCancelButton}.
196826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         *
197826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @param pendingIntent the intent to be sent when the cancel button is pressed
198826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
199826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public MediaStyle setCancelButtonIntent(PendingIntent pendingIntent) {
200826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            mCancelButtonIntent = pendingIntent;
201826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return this;
202826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
203826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
204826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
205826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
206826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
207826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
208826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
209826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public void apply(NotificationBuilderWithBuilderAccessor builder) {
210826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 21) {
211826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                builder.getBuilder().setStyle(
212826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        fillInMediaStyle(new Notification.MediaStyle()));
213826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            } else if (mShowCancelButton) {
214826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                builder.getBuilder().setOngoing(true);
215826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
216826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
217826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
218826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RequiresApi(21)
219826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        Notification.MediaStyle fillInMediaStyle(Notification.MediaStyle style) {
220826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (mActionsToShowInCompact != null) {
221826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                style.setShowActionsInCompactView(mActionsToShowInCompact);
222826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
223826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (mToken != null) {
224826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                style.setMediaSession((MediaSession.Token) mToken.getToken());
225826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
226826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return style;
227826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
228826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
229826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
230826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
231826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
232826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
233826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
234826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) {
235826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 21) {
236826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No custom content view required
237826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
238826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
239826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return generateContentView();
240826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
241826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
242826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        RemoteViews generateContentView() {
243826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews view = applyStandardTemplate(false /* showSmallIcon */,
244826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    getContentViewLayoutResource(), true /* fitIn1U */);
245826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
246826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            final int numActions = mBuilder.mActions.size();
247826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            final int numActionsInCompact = mActionsToShowInCompact == null
248826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? 0
249826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
250826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            view.removeAllViews(R.id.media_actions);
251826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (numActionsInCompact > 0) {
252826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                for (int i = 0; i < numActionsInCompact; i++) {
253826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    if (i >= numActions) {
254826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        throw new IllegalArgumentException(String.format(
255826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                                "setShowActionsInCompactView: action %d out of bounds (max %d)",
256826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                                i, numActions - 1));
257826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    }
258826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
259ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                    final androidx.core.app.NotificationCompat.Action action =
260826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                            mBuilder.mActions.get(mActionsToShowInCompact[i]);
261826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    final RemoteViews button = generateMediaActionButton(action);
262826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    view.addView(R.id.media_actions, button);
263826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                }
264826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
265826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (mShowCancelButton) {
266826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                view.setViewVisibility(R.id.end_padder, View.GONE);
267826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                view.setViewVisibility(R.id.cancel_action, View.VISIBLE);
268826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                view.setOnClickPendingIntent(R.id.cancel_action, mCancelButtonIntent);
269826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                view.setInt(R.id.cancel_action, "setAlpha", mBuilder.mContext
270826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        .getResources().getInteger(R.integer.cancel_button_image_alpha));
271826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            } else {
272826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                view.setViewVisibility(R.id.end_padder, View.VISIBLE);
273826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                view.setViewVisibility(R.id.cancel_action, View.GONE);
274826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
275826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return view;
276826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
277826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
278826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        private RemoteViews generateMediaActionButton(
279ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                androidx.core.app.NotificationCompat.Action action) {
280826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            final boolean tombstone = (action.getActionIntent() == null);
281826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews button = new RemoteViews(mBuilder.mContext.getPackageName(),
282826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    R.layout.notification_media_action);
283826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            button.setImageViewResource(R.id.action0, action.getIcon());
284826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (!tombstone) {
285826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                button.setOnClickPendingIntent(R.id.action0, action.getActionIntent());
286826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
287826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 15) {
288826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                button.setContentDescription(R.id.action0, action.getTitle());
289826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
290826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return button;
291826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
292826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
293826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        int getContentViewLayoutResource() {
294826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return R.layout.notification_template_media;
295826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
296826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
297826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
298826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
299826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
300826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
301826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
302826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) {
303826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 21) {
304826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No custom content view required
305826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
306826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
307826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return generateBigContentView();
308826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
309826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
310826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        RemoteViews generateBigContentView() {
311826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            final int actionCount = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS);
312826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews big = applyStandardTemplate(false /* showSmallIcon */,
313826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    getBigContentViewLayoutResource(actionCount), false /* fitIn1U */);
314826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
315826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            big.removeAllViews(R.id.media_actions);
316826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (actionCount > 0) {
317826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                for (int i = 0; i < actionCount; i++) {
318826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i));
319826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    big.addView(R.id.media_actions, button);
320826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                }
321826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
322826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (mShowCancelButton) {
323826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                big.setViewVisibility(R.id.cancel_action, View.VISIBLE);
324826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                big.setInt(R.id.cancel_action, "setAlpha", mBuilder.mContext
325826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        .getResources().getInteger(R.integer.cancel_button_image_alpha));
326826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                big.setOnClickPendingIntent(R.id.cancel_action, mCancelButtonIntent);
327826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            } else {
328826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                big.setViewVisibility(R.id.cancel_action, View.GONE);
329826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
330826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return big;
331826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
332826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
333826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        int getBigContentViewLayoutResource(int actionCount) {
334826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return actionCount <= 3
335826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? R.layout.notification_template_big_media_narrow
336826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : R.layout.notification_template_big_media;
337826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
338826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    }
339826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
340826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    /**
341826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Notification style for media custom views that are decorated by the system.
342826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
343826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * <p>Instead of providing a media notification that is completely custom, a developer can set
344826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * this style and still obtain system decorations like the notification header with the expand
345826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * affordance and actions.
346826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
347ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * <p>Use {@link androidx.core.app.NotificationCompat.Builder
348826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * #setCustomContentView(RemoteViews)},
349ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder
350826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * #setCustomBigContentView(RemoteViews)} and
351ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder
352826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * #setCustomHeadsUpContentView(RemoteViews)} to set the
353826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * corresponding custom views to display.
354826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
355826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * <p>To use this style with your Notification, feed it to
356ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.core.app.NotificationCompat.Builder
357ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * #setStyle(androidx.core.app.NotificationCompat.Style)} like so:
358826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * <pre class="prettyprint">
359826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * Notification noti = new NotificationCompat.Builder()
360826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setSmallIcon(R.drawable.ic_stat_player)
361826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setLargeIcon(albumArtBitmap))
362826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setCustomContentView(contentView)
363826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .setStyle(<b>new NotificationCompat.DecoratedMediaCustomViewStyle()</b>
364826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *          .setMediaSession(mySession))
365826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *     .build();
366826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * </pre>
367826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
368826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * <p>If you are using this style, consider using the corresponding styles like
369ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * {@link androidx.media.R.style#TextAppearance_Compat_Notification_Media} or
370826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * {@link
371ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * androidx.media.R.style#TextAppearance_Compat_Notification_Title_Media} in
372826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * your custom views in order to get the correct styling on each platform version.
373826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     *
374ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * @see androidx.core.app.NotificationCompat.DecoratedCustomViewStyle
375826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     * @see MediaStyle
376826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake     */
377826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    public static class DecoratedMediaCustomViewStyle extends MediaStyle {
378826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
379826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public DecoratedMediaCustomViewStyle() {
380826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
381826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
382826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
383826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
384826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
385826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
386826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
387826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public void apply(NotificationBuilderWithBuilderAccessor builder) {
388826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 24) {
389826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                builder.getBuilder().setStyle(
390826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        fillInMediaStyle(new Notification.DecoratedMediaCustomViewStyle()));
391826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            } else {
392826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                super.apply(builder);
393826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
394826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
395826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
396826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
397826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
398826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
399826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
400826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
401826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) {
402826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 24) {
403826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No custom content view required
404826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
405826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
406826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            boolean hasContentView = mBuilder.getContentView() != null;
407826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 21) {
408826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // If we are on L/M the media notification will only be colored if the expanded
409826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // version is of media style, so we have to create a custom view for the collapsed
410826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // version as well in that case.
411826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                boolean createCustomContent = hasContentView
412826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        || mBuilder.getBigContentView() != null;
413826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                if (createCustomContent) {
414826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    RemoteViews contentView = generateContentView();
415826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    if (hasContentView) {
416826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                        buildIntoRemoteViews(contentView, mBuilder.getContentView());
417826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    }
418826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    setBackgroundColor(contentView);
419826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    return contentView;
420826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                }
421826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            } else {
422826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                RemoteViews contentView = generateContentView();
423826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                if (hasContentView) {
424826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    buildIntoRemoteViews(contentView, mBuilder.getContentView());
425826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    return contentView;
426826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                }
427826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
428826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return null;
429826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
430826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
431826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
432826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        int getContentViewLayoutResource() {
433826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return mBuilder.getContentView() != null
434826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? R.layout.notification_template_media_custom
435826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : super.getContentViewLayoutResource();
436826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
437826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
438826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
439826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
440826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
441826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
442826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
443826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) {
444826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 24) {
445826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No custom big content view required
446826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
447826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
448826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews innerView = mBuilder.getBigContentView() != null
449826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? mBuilder.getBigContentView()
450826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : mBuilder.getContentView();
451826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (innerView == null) {
452826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No expandable notification
453826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
454826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
455826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews bigContentView = generateBigContentView();
456826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            buildIntoRemoteViews(bigContentView, innerView);
457826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 21) {
458826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                setBackgroundColor(bigContentView);
459826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
460826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return bigContentView;
461826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
462826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
463826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
464826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        int getBigContentViewLayoutResource(int actionCount) {
465826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return actionCount <= 3
466826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? R.layout.notification_template_big_media_narrow_custom
467826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : R.layout.notification_template_big_media_custom;
468826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
469826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
470826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        /**
471826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         * @hide
472826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake         */
473826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @RestrictTo(LIBRARY_GROUP)
474826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        @Override
475826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        public RemoteViews makeHeadsUpContentView(NotificationBuilderWithBuilderAccessor builder) {
476826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 24) {
477826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No custom heads up content view required
478826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
479826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
480826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews innerView = mBuilder.getHeadsUpContentView() != null
481826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? mBuilder.getHeadsUpContentView()
482826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : mBuilder.getContentView();
483826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (innerView == null) {
484826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                // No expandable notification
485826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                return null;
486826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
487826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            RemoteViews headsUpContentView = generateBigContentView();
488826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            buildIntoRemoteViews(headsUpContentView, innerView);
489826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            if (Build.VERSION.SDK_INT >= 21) {
490826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                setBackgroundColor(headsUpContentView);
491826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            }
492826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            return headsUpContentView;
493826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
494826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake
495826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        private void setBackgroundColor(RemoteViews views) {
496826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            int color = mBuilder.getColor() != COLOR_DEFAULT
497826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    ? mBuilder.getColor()
498826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                    : mBuilder.mContext.getResources().getColor(
499826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake                            R.color.notification_material_background_media_default_color);
500826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake            views.setInt(R.id.status_bar_latest_event_content, "setBackgroundColor", color);
501826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake        }
502826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake    }
503826ed4f84805a4aeae559d8ec6e2d54fda40153fIan Lake}
504