1976b6a8c18550ace670e0410453741d11dafa474Ian Lake/*
2976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Copyright (C) 2015 The Android Open Source Project
3976b6a8c18550ace670e0410453741d11dafa474Ian Lake *
4976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Licensed under the Apache License, Version 2.0 (the "License");
5976b6a8c18550ace670e0410453741d11dafa474Ian Lake * you may not use this file except in compliance with the License.
6976b6a8c18550ace670e0410453741d11dafa474Ian Lake * You may obtain a copy of the License at
7976b6a8c18550ace670e0410453741d11dafa474Ian Lake *
8976b6a8c18550ace670e0410453741d11dafa474Ian Lake *      http://www.apache.org/licenses/LICENSE-2.0
9976b6a8c18550ace670e0410453741d11dafa474Ian Lake *
10976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Unless required by applicable law or agreed to in writing, software
11976b6a8c18550ace670e0410453741d11dafa474Ian Lake * distributed under the License is distributed on an "AS IS" BASIS,
12976b6a8c18550ace670e0410453741d11dafa474Ian Lake * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13976b6a8c18550ace670e0410453741d11dafa474Ian Lake * See the License for the specific language governing permissions and
14976b6a8c18550ace670e0410453741d11dafa474Ian Lake * limitations under the License
15976b6a8c18550ace670e0410453741d11dafa474Ian Lake */
16976b6a8c18550ace670e0410453741d11dafa474Ian Lake
1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banespackage android.support.v7.app;
18976b6a8c18550ace670e0410453741d11dafa474Ian Lake
19976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.app.Notification;
20976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.app.PendingIntent;
21976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.content.Context;
22976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.content.res.Resources;
23976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.graphics.Bitmap;
243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.Canvas;
253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.Color;
263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.PorterDuff;
273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.PorterDuffColorFilter;
283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.graphics.drawable.Drawable;
29976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.os.Build;
30976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.os.SystemClock;
31976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.support.v4.app.NotificationBuilderWithBuilderAccessor;
323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport android.support.v4.app.NotificationCompat;
33976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.support.v4.app.NotificationCompatBase;
3466698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.appcompat.R;
35976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.util.TypedValue;
36976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.view.View;
37976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport android.widget.RemoteViews;
38976b6a8c18550ace670e0410453741d11dafa474Ian Lake
39976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport java.text.NumberFormat;
403b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinekimport java.util.ArrayList;
41976b6a8c18550ace670e0410453741d11dafa474Ian Lakeimport java.util.List;
42976b6a8c18550ace670e0410453741d11dafa474Ian Lake
43976b6a8c18550ace670e0410453741d11dafa474Ian Lake/**
44976b6a8c18550ace670e0410453741d11dafa474Ian Lake * Helper class to generate MediaStyle notifications for pre-Lollipop platforms. Overrides
45976b6a8c18550ace670e0410453741d11dafa474Ian Lake * contentView and bigContentView of the notification.
46976b6a8c18550ace670e0410453741d11dafa474Ian Lake */
4766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesclass NotificationCompatImplBase {
48976b6a8c18550ace670e0410453741d11dafa474Ian Lake
49976b6a8c18550ace670e0410453741d11dafa474Ian Lake    static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3;
50976b6a8c18550ace670e0410453741d11dafa474Ian Lake    static final int MAX_MEDIA_BUTTONS = 5;
513b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static final int MAX_ACTION_BUTTONS = 3;
52976b6a8c18550ace670e0410453741d11dafa474Ian Lake
533b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static <T extends NotificationCompatBase.Action> RemoteViews overrideContentViewMedia(
54976b6a8c18550ace670e0410453741d11dafa474Ian Lake            NotificationBuilderWithBuilderAccessor builder,
55976b6a8c18550ace670e0410453741d11dafa474Ian Lake            Context context, CharSequence contentTitle, CharSequence contentText,
56976b6a8c18550ace670e0410453741d11dafa474Ian Lake            CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText,
573b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean useChronometer, long when, int priority, List<T> actions,
583b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            int[] actionsToShowInCompact, boolean showCancelButton,
593b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            PendingIntent cancelButtonIntent, boolean isDecoratedCustomView) {
603b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        RemoteViews views = generateContentViewMedia(context, contentTitle, contentText, contentInfo,
613b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                number, largeIcon, subText, useChronometer, when, priority, actions,
623b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                actionsToShowInCompact, showCancelButton, cancelButtonIntent,
633b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                isDecoratedCustomView);
64976b6a8c18550ace670e0410453741d11dafa474Ian Lake        builder.getBuilder().setContent(views);
65976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (showCancelButton) {
66976b6a8c18550ace670e0410453741d11dafa474Ian Lake            builder.getBuilder().setOngoing(true);
67976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
683b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return views;
69976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
70976b6a8c18550ace670e0410453741d11dafa474Ian Lake
713b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static <T extends NotificationCompatBase.Action> RemoteViews generateContentViewMedia(
72976b6a8c18550ace670e0410453741d11dafa474Ian Lake            Context context, CharSequence contentTitle, CharSequence contentText,
73976b6a8c18550ace670e0410453741d11dafa474Ian Lake            CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText,
743b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean useChronometer, long when, int priority, List<T> actions,
753b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            int[] actionsToShowInCompact, boolean showCancelButton,
763b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            PendingIntent cancelButtonIntent, boolean isDecoratedCustomView) {
77976b6a8c18550ace670e0410453741d11dafa474Ian Lake        RemoteViews view = applyStandardTemplate(context, contentTitle, contentText, contentInfo,
783b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                number, 0 /* smallIcon */, largeIcon, subText, useChronometer, when, priority,
793b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                0 /* color is unused on media */,
803b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                isDecoratedCustomView ? R.layout.notification_template_media_custom
813b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        : R.layout.notification_template_media,
823b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                true /* fitIn1U */);
83976b6a8c18550ace670e0410453741d11dafa474Ian Lake
84976b6a8c18550ace670e0410453741d11dafa474Ian Lake        final int numActions = actions.size();
85976b6a8c18550ace670e0410453741d11dafa474Ian Lake        final int N = actionsToShowInCompact == null
86976b6a8c18550ace670e0410453741d11dafa474Ian Lake                ? 0
87976b6a8c18550ace670e0410453741d11dafa474Ian Lake                : Math.min(actionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
88976b6a8c18550ace670e0410453741d11dafa474Ian Lake        view.removeAllViews(R.id.media_actions);
89976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (N > 0) {
90976b6a8c18550ace670e0410453741d11dafa474Ian Lake            for (int i = 0; i < N; i++) {
91976b6a8c18550ace670e0410453741d11dafa474Ian Lake                if (i >= numActions) {
92976b6a8c18550ace670e0410453741d11dafa474Ian Lake                    throw new IllegalArgumentException(String.format(
93976b6a8c18550ace670e0410453741d11dafa474Ian Lake                            "setShowActionsInCompactView: action %d out of bounds (max %d)",
94976b6a8c18550ace670e0410453741d11dafa474Ian Lake                            i, numActions - 1));
95976b6a8c18550ace670e0410453741d11dafa474Ian Lake                }
96976b6a8c18550ace670e0410453741d11dafa474Ian Lake
97976b6a8c18550ace670e0410453741d11dafa474Ian Lake                final NotificationCompatBase.Action action = actions.get(actionsToShowInCompact[i]);
98976b6a8c18550ace670e0410453741d11dafa474Ian Lake                final RemoteViews button = generateMediaActionButton(context, action);
99976b6a8c18550ace670e0410453741d11dafa474Ian Lake                view.addView(R.id.media_actions, button);
100976b6a8c18550ace670e0410453741d11dafa474Ian Lake            }
101976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
102976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (showCancelButton) {
103976b6a8c18550ace670e0410453741d11dafa474Ian Lake            view.setViewVisibility(R.id.end_padder, View.GONE);
104976b6a8c18550ace670e0410453741d11dafa474Ian Lake            view.setViewVisibility(R.id.cancel_action, View.VISIBLE);
105976b6a8c18550ace670e0410453741d11dafa474Ian Lake            view.setOnClickPendingIntent(R.id.cancel_action, cancelButtonIntent);
106976b6a8c18550ace670e0410453741d11dafa474Ian Lake            view.setInt(R.id.cancel_action, "setAlpha",
107976b6a8c18550ace670e0410453741d11dafa474Ian Lake                    context.getResources().getInteger(R.integer.cancel_button_image_alpha));
108976b6a8c18550ace670e0410453741d11dafa474Ian Lake        } else {
109976b6a8c18550ace670e0410453741d11dafa474Ian Lake            view.setViewVisibility(R.id.end_padder, View.VISIBLE);
110976b6a8c18550ace670e0410453741d11dafa474Ian Lake            view.setViewVisibility(R.id.cancel_action, View.GONE);
111976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
112976b6a8c18550ace670e0410453741d11dafa474Ian Lake        return view;
113976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
114976b6a8c18550ace670e0410453741d11dafa474Ian Lake
1153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static <T extends NotificationCompatBase.Action> void overrideMediaBigContentView(
116976b6a8c18550ace670e0410453741d11dafa474Ian Lake            Notification n, Context context, CharSequence contentTitle, CharSequence contentText,
117976b6a8c18550ace670e0410453741d11dafa474Ian Lake            CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText,
1183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean useChronometer, long when, int priority, int color, List<T> actions,
1193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean showCancelButton, PendingIntent cancelButtonIntent,
1203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean decoratedCustomView) {
1213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        n.bigContentView = generateMediaBigView(context, contentTitle, contentText, contentInfo,
1223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                number, largeIcon, subText, useChronometer, when, priority, color,
1233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                actions, showCancelButton, cancelButtonIntent, decoratedCustomView);
124976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (showCancelButton) {
125976b6a8c18550ace670e0410453741d11dafa474Ian Lake            n.flags |= Notification.FLAG_ONGOING_EVENT;
126976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
127976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
128976b6a8c18550ace670e0410453741d11dafa474Ian Lake
1293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static <T extends NotificationCompatBase.Action> RemoteViews generateMediaBigView(
130976b6a8c18550ace670e0410453741d11dafa474Ian Lake            Context context, CharSequence contentTitle, CharSequence contentText,
131976b6a8c18550ace670e0410453741d11dafa474Ian Lake            CharSequence contentInfo, int number, Bitmap largeIcon, CharSequence subText,
1323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean useChronometer, long when, int priority, int color, List<T> actions,
1333b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean showCancelButton, PendingIntent cancelButtonIntent,
1343b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean decoratedCustomView) {
135976b6a8c18550ace670e0410453741d11dafa474Ian Lake        final int actionCount = Math.min(actions.size(), MAX_MEDIA_BUTTONS);
136976b6a8c18550ace670e0410453741d11dafa474Ian Lake        RemoteViews big = applyStandardTemplate(context, contentTitle, contentText, contentInfo,
1373b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                number, 0 /* smallIcon */, largeIcon, subText, useChronometer, when, priority,
1383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                color,  /* fitIn1U */getBigMediaLayoutResource(decoratedCustomView, actionCount),
1393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                false);
140976b6a8c18550ace670e0410453741d11dafa474Ian Lake
141976b6a8c18550ace670e0410453741d11dafa474Ian Lake        big.removeAllViews(R.id.media_actions);
142976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (actionCount > 0) {
143976b6a8c18550ace670e0410453741d11dafa474Ian Lake            for (int i = 0; i < actionCount; i++) {
144976b6a8c18550ace670e0410453741d11dafa474Ian Lake                final RemoteViews button = generateMediaActionButton(context, actions.get(i));
145976b6a8c18550ace670e0410453741d11dafa474Ian Lake                big.addView(R.id.media_actions, button);
146976b6a8c18550ace670e0410453741d11dafa474Ian Lake            }
147976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
148976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (showCancelButton) {
149976b6a8c18550ace670e0410453741d11dafa474Ian Lake            big.setViewVisibility(R.id.cancel_action, View.VISIBLE);
150976b6a8c18550ace670e0410453741d11dafa474Ian Lake            big.setInt(R.id.cancel_action, "setAlpha",
151976b6a8c18550ace670e0410453741d11dafa474Ian Lake                    context.getResources().getInteger(R.integer.cancel_button_image_alpha));
152976b6a8c18550ace670e0410453741d11dafa474Ian Lake            big.setOnClickPendingIntent(R.id.cancel_action, cancelButtonIntent);
153976b6a8c18550ace670e0410453741d11dafa474Ian Lake        } else {
154976b6a8c18550ace670e0410453741d11dafa474Ian Lake            big.setViewVisibility(R.id.cancel_action, View.GONE);
155976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
156976b6a8c18550ace670e0410453741d11dafa474Ian Lake        return big;
157976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
158976b6a8c18550ace670e0410453741d11dafa474Ian Lake
159976b6a8c18550ace670e0410453741d11dafa474Ian Lake    private static RemoteViews generateMediaActionButton(Context context,
160976b6a8c18550ace670e0410453741d11dafa474Ian Lake            NotificationCompatBase.Action action) {
161976b6a8c18550ace670e0410453741d11dafa474Ian Lake        final boolean tombstone = (action.getActionIntent() == null);
162976b6a8c18550ace670e0410453741d11dafa474Ian Lake        RemoteViews button = new RemoteViews(context.getPackageName(),
163976b6a8c18550ace670e0410453741d11dafa474Ian Lake                R.layout.notification_media_action);
164976b6a8c18550ace670e0410453741d11dafa474Ian Lake        button.setImageViewResource(R.id.action0, action.getIcon());
165976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (!tombstone) {
166976b6a8c18550ace670e0410453741d11dafa474Ian Lake            button.setOnClickPendingIntent(R.id.action0, action.getActionIntent());
167976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
168956192ae5d9dd882c91c9cb607954f0eebcb7976Ian Lake        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
169956192ae5d9dd882c91c9cb607954f0eebcb7976Ian Lake            button.setContentDescription(R.id.action0, action.getTitle());
170956192ae5d9dd882c91c9cb607954f0eebcb7976Ian Lake        }
171976b6a8c18550ace670e0410453741d11dafa474Ian Lake        return button;
172976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
173976b6a8c18550ace670e0410453741d11dafa474Ian Lake
1743b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static int getBigMediaLayoutResource(boolean decoratedCustomView, int actionCount) {
175976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (actionCount <= 3) {
1763b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            return decoratedCustomView
1773b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    ? R.layout.notification_template_big_media_narrow_custom
1783b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    : R.layout.notification_template_big_media_narrow;
179976b6a8c18550ace670e0410453741d11dafa474Ian Lake        } else {
1803b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            return decoratedCustomView
1813b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    ? R.layout.notification_template_big_media_custom
1823b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    : R.layout.notification_template_big_media;
183976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
184976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
185976b6a8c18550ace670e0410453741d11dafa474Ian Lake
1863b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static RemoteViews applyStandardTemplateWithActions(Context context,
187976b6a8c18550ace670e0410453741d11dafa474Ian Lake            CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
1883b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            int number, int smallIcon, Bitmap largeIcon, CharSequence subText,
1893b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean useChronometer, long when, int priority, int color, int resId, boolean fitIn1U,
1903b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            ArrayList<NotificationCompat.Action> actions) {
1913b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        RemoteViews remoteViews = applyStandardTemplate(context, contentTitle, contentText,
1923b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentInfo, number, smallIcon, largeIcon, subText, useChronometer, when, priority,
1933b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                color, resId, fitIn1U);
1943b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        remoteViews.removeAllViews(R.id.actions);
1953b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        boolean actionsVisible = false;
1963b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (actions != null) {
1973b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            int N = actions.size();
1983b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            if (N > 0) {
1993b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                actionsVisible = true;
2003b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                if (N > MAX_ACTION_BUTTONS) N = MAX_ACTION_BUTTONS;
2013b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                for (int i = 0; i < N; i++) {
2023b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    final RemoteViews button = generateActionButton(context, actions.get(i));
2033b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    remoteViews.addView(R.id.actions, button);
2043b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                }
2053b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            }
2063b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        }
2073b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        int actionVisibility = actionsVisible ? View.VISIBLE : View.GONE;
2083b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        remoteViews.setViewVisibility(R.id.actions, actionVisibility);
2093b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        remoteViews.setViewVisibility(R.id.action_divider, actionVisibility);
2103b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return remoteViews;
2113b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
2123b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2133b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static RemoteViews generateActionButton(Context context,
2143b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            NotificationCompat.Action action) {
2153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        final boolean tombstone = (action.actionIntent == null);
2163b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        RemoteViews button =  new RemoteViews(context.getPackageName(),
2173b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                tombstone ? getActionTombstoneLayoutResource()
2183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        : getActionLayoutResource());
2193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        button.setImageViewBitmap(R.id.action_image,
2203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                createColoredBitmap(context, action.getIcon(),
2213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        context.getResources().getColor(R.color.notification_action_color_filter)));
2223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        button.setTextViewText(R.id.action_text, action.title);
2233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (!tombstone) {
2243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            button.setOnClickPendingIntent(R.id.action_container, action.actionIntent);
2253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        }
2263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        button.setContentDescription(R.id.action_container, action.title);
2273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return button;
2283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
2293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2303b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static Bitmap createColoredBitmap(Context context, int iconId, int color) {
2313b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return createColoredBitmap(context, iconId, color, 0);
2323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
2333b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2343b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static Bitmap createColoredBitmap(Context context, int iconId, int color, int size) {
2353b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Drawable drawable = context.getResources().getDrawable(iconId);
2363b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        int width = size == 0 ? drawable.getIntrinsicWidth() : size;
2373b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        int height = size == 0 ? drawable.getIntrinsicHeight() : size;
2383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Bitmap resultBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
2393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        drawable.setBounds(0, 0, width, height);
2403b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (color != 0) {
2413b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            drawable.mutate().setColorFilter(
2423b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
2433b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        }
2443b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Canvas canvas = new Canvas(resultBitmap);
2453b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        drawable.draw(canvas);
2463b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return resultBitmap;
2473b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
2483b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2493b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static int getActionLayoutResource() {
2503b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return R.layout.notification_action;
2513b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
2523b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2533b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static int getActionTombstoneLayoutResource() {
2543b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return R.layout.notification_action_tombstone;
2553b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
2563b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2573b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static RemoteViews applyStandardTemplate(Context context,
2583b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
2593b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            int number, int smallIcon, Bitmap largeIcon, CharSequence subText,
2603b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean useChronometer, long when, int priority, int color, int resId,
2613b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            boolean fitIn1U) {
2623b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Resources res = context.getResources();
263976b6a8c18550ace670e0410453741d11dafa474Ian Lake        RemoteViews contentView = new RemoteViews(context.getPackageName(), resId);
264976b6a8c18550ace670e0410453741d11dafa474Ian Lake        boolean showLine3 = false;
265976b6a8c18550ace670e0410453741d11dafa474Ian Lake        boolean showLine2 = false;
266976b6a8c18550ace670e0410453741d11dafa474Ian Lake
2673b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        boolean minPriority = priority < NotificationCompat.PRIORITY_LOW;
2683b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        boolean afterJellyBean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
2693b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        boolean afterLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
2703b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (afterJellyBean && !afterLollipop) {
2713b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            // lets color the backgrounds
2723b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            if (minPriority) {
2733b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setInt(R.id.notification_background,
2743b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        "setBackgroundResource", R.drawable.notification_bg_low);
2753b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setInt(R.id.icon,
2763b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        "setBackgroundResource", R.drawable.notification_template_icon_low_bg);
2773b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            } else {
2783b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setInt(R.id.notification_background,
2793b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        "setBackgroundResource", R.drawable.notification_bg);
2803b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setInt(R.id.icon,
2813b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        "setBackgroundResource", R.drawable.notification_template_icon_bg);
2823b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            }
2833b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        }
2843b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
2853b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (largeIcon != null) {
2863b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            // On versions before Jellybean, the large icon was shown by SystemUI, so we need to hide
2873b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            // it here.
2883b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            if (afterJellyBean) {
2893b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setViewVisibility(R.id.icon, View.VISIBLE);
2903b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setImageViewBitmap(R.id.icon, largeIcon);
2913b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            } else {
2923b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setViewVisibility(R.id.icon, View.GONE);
2933b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            }
2943b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            if (smallIcon != 0) {
2953b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                int backgroundSize = res.getDimensionPixelSize(
2963b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        R.dimen.notification_right_icon_size);
2973b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                int iconSize = backgroundSize - res.getDimensionPixelSize(
2983b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        R.dimen.notification_small_icon_background_padding) * 2;
2993b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                if (afterLollipop) {
3003b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    Bitmap smallBit = createIconWithBackground(context,
3013b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                            smallIcon,
3023b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                            backgroundSize,
3033b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                            iconSize,
3043b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                            color);
3053b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    contentView.setImageViewBitmap(R.id.right_icon, smallBit);
3063b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                } else {
3073b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    contentView.setImageViewBitmap(R.id.right_icon,
3083b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                            createColoredBitmap(context, smallIcon, Color.WHITE));
3093b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                }
3103b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
3113b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            }
3123b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        } else if (smallIcon != 0) { // small icon at left
313b5d323aec7885d728503cc080c6c5e5a20e5850cIan Lake            contentView.setViewVisibility(R.id.icon, View.VISIBLE);
3143b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            if (afterLollipop) {
3153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                int backgroundSize = res.getDimensionPixelSize(
3163b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        R.dimen.notification_large_icon_width)
3173b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        - res.getDimensionPixelSize(R.dimen.notification_big_circle_margin);
3183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                int iconSize = res.getDimensionPixelSize(
3193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        R.dimen.notification_small_icon_size_as_large);
3203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                Bitmap smallBit = createIconWithBackground(context,
3213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        smallIcon,
3223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        backgroundSize,
3233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        iconSize,
3243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        color);
3253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setImageViewBitmap(R.id.icon, smallBit);
3263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            } else {
3273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setImageViewBitmap(R.id.icon,
3283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        createColoredBitmap(context, smallIcon, Color.WHITE));
3293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            }
330976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
331976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (contentTitle != null) {
332976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setTextViewText(R.id.title, contentTitle);
333976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
334976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (contentText != null) {
335976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setTextViewText(R.id.text, contentText);
336976b6a8c18550ace670e0410453741d11dafa474Ian Lake            showLine3 = true;
337976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
3383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        // If there is a large icon we have a right side
3393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        boolean hasRightSide = !afterLollipop && largeIcon != null;
340976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (contentInfo != null) {
341976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setTextViewText(R.id.info, contentInfo);
342976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setViewVisibility(R.id.info, View.VISIBLE);
343976b6a8c18550ace670e0410453741d11dafa474Ian Lake            showLine3 = true;
3443b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            hasRightSide = true;
345976b6a8c18550ace670e0410453741d11dafa474Ian Lake        } else if (number > 0) {
3463b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            final int tooBig = res.getInteger(
347976b6a8c18550ace670e0410453741d11dafa474Ian Lake                    R.integer.status_bar_notification_info_maxnum);
348976b6a8c18550ace670e0410453741d11dafa474Ian Lake            if (number > tooBig) {
3493b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                contentView.setTextViewText(R.id.info, ((Resources) res).getString(
350976b6a8c18550ace670e0410453741d11dafa474Ian Lake                        R.string.status_bar_notification_info_overflow));
351976b6a8c18550ace670e0410453741d11dafa474Ian Lake            } else {
352976b6a8c18550ace670e0410453741d11dafa474Ian Lake                NumberFormat f = NumberFormat.getIntegerInstance();
353976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setTextViewText(R.id.info, f.format(number));
354976b6a8c18550ace670e0410453741d11dafa474Ian Lake            }
355976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setViewVisibility(R.id.info, View.VISIBLE);
356976b6a8c18550ace670e0410453741d11dafa474Ian Lake            showLine3 = true;
3573b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            hasRightSide = true;
358976b6a8c18550ace670e0410453741d11dafa474Ian Lake        } else {
359976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setViewVisibility(R.id.info, View.GONE);
360976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
361976b6a8c18550ace670e0410453741d11dafa474Ian Lake
362976b6a8c18550ace670e0410453741d11dafa474Ian Lake        // Need to show three lines? Only allow on Jellybean+
3633b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (subText != null && afterJellyBean) {
364976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setTextViewText(R.id.text, subText);
365976b6a8c18550ace670e0410453741d11dafa474Ian Lake            if (contentText != null) {
366976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setTextViewText(R.id.text2, contentText);
367976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setViewVisibility(R.id.text2, View.VISIBLE);
368976b6a8c18550ace670e0410453741d11dafa474Ian Lake                showLine2 = true;
369976b6a8c18550ace670e0410453741d11dafa474Ian Lake            } else {
370976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setViewVisibility(R.id.text2, View.GONE);
371976b6a8c18550ace670e0410453741d11dafa474Ian Lake            }
372976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
373976b6a8c18550ace670e0410453741d11dafa474Ian Lake
374976b6a8c18550ace670e0410453741d11dafa474Ian Lake        // RemoteViews.setViewPadding and RemoteViews.setTextViewTextSize is not available on ICS-
3753b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (showLine2 && afterJellyBean) {
376976b6a8c18550ace670e0410453741d11dafa474Ian Lake            if (fitIn1U) {
377976b6a8c18550ace670e0410453741d11dafa474Ian Lake                // need to shrink all the type to make sure everything fits
378976b6a8c18550ace670e0410453741d11dafa474Ian Lake                final float subTextSize = res.getDimensionPixelSize(
379976b6a8c18550ace670e0410453741d11dafa474Ian Lake                        R.dimen.notification_subtext_size);
380976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX, subTextSize);
381976b6a8c18550ace670e0410453741d11dafa474Ian Lake            }
382976b6a8c18550ace670e0410453741d11dafa474Ian Lake            // vertical centering
383976b6a8c18550ace670e0410453741d11dafa474Ian Lake            contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
384976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
385976b6a8c18550ace670e0410453741d11dafa474Ian Lake
386976b6a8c18550ace670e0410453741d11dafa474Ian Lake        if (when != 0) {
3873b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            if (useChronometer && afterJellyBean) {
388976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
389976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setLong(R.id.chronometer, "setBase",
390976b6a8c18550ace670e0410453741d11dafa474Ian Lake                        when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
391976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setBoolean(R.id.chronometer, "setStarted", true);
392976b6a8c18550ace670e0410453741d11dafa474Ian Lake            } else {
393976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setViewVisibility(R.id.time, View.VISIBLE);
394976b6a8c18550ace670e0410453741d11dafa474Ian Lake                contentView.setLong(R.id.time, "setTime", when);
395976b6a8c18550ace670e0410453741d11dafa474Ian Lake            }
3963b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            hasRightSide = true;
397976b6a8c18550ace670e0410453741d11dafa474Ian Lake        }
3983b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        contentView.setViewVisibility(R.id.right_side, hasRightSide ? View.VISIBLE : View.GONE);
399976b6a8c18550ace670e0410453741d11dafa474Ian Lake        contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
400976b6a8c18550ace670e0410453741d11dafa474Ian Lake        return contentView;
401976b6a8c18550ace670e0410453741d11dafa474Ian Lake    }
4023b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
4033b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static Bitmap createIconWithBackground(Context ctx, int iconId, int size, int iconSize,
4043b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            int color) {
4053b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Bitmap coloredBitmap = createColoredBitmap(ctx, R.drawable.notification_icon_background,
4063b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                        color == NotificationCompat.COLOR_DEFAULT ? 0 : color, size);
4073b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Canvas canvas = new Canvas(coloredBitmap);
4083b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        Drawable icon = ctx.getResources().getDrawable(iconId).mutate();
4093b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        icon.setFilterBitmap(true);
4103b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        int inset = (size - iconSize) / 2;
4113b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        icon.setBounds(inset, inset, iconSize + inset, iconSize + inset);
4123b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        icon.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP));
4133b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        icon.draw(canvas);
4143b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return coloredBitmap;
4153b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
4163b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
4173b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static void buildIntoRemoteViews(Context ctx, RemoteViews outerView,
4183b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            RemoteViews innerView) {
4193b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        // this needs to be done fore the other calls, since otherwise we might hide the wrong
4203b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        // things if our ids collide.
4213b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        hideNormalContent(outerView);
4223b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        outerView.removeAllViews(R.id.notification_main_column);
4233b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        outerView.addView(R.id.notification_main_column, innerView.clone());
4243b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        outerView.setViewVisibility(R.id.notification_main_column, View.VISIBLE);
4253b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
4263b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            // Adjust padding depending on font size.
4273b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek            outerView.setViewPadding(R.id.notification_main_column_container,
4283b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                    0, calculateTopPadding(ctx), 0, 0);
4293b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        }
4303b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
4313b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
4323b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    private static void hideNormalContent(RemoteViews outerView) {
4333b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        outerView.setViewVisibility(R.id.title, View.GONE);
4343b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        outerView.setViewVisibility(R.id.text2, View.GONE);
4353b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        outerView.setViewVisibility(R.id.text, View.GONE);
4363b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
4373b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
4383b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static int calculateTopPadding(Context ctx) {
4393b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        int padding = ctx.getResources().getDimensionPixelSize(R.dimen.notification_top_pad);
4403b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        int largePadding = ctx.getResources().getDimensionPixelSize(
4413b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek                R.dimen.notification_top_pad_large_text);
4423b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        float fontScale = ctx.getResources().getConfiguration().fontScale;
4433b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        float largeFactor = (constrain(fontScale, 1.0f, 1.3f) - 1f) / (1.3f - 1f);
4443b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
4453b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        // Linearly interpolate the padding between large and normal with the font scale ranging
4463b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        // from 1f to LARGE_TEXT_SCALE
4473b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
4483b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
4493b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek
4503b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    public static float constrain(float amount, float low, float high) {
4513b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek        return amount < low ? low : (amount > high ? high : amount);
4523b3e1c4da1c0a710a74204a6ba44389a6f26b27aSelim Cinek    }
453976b6a8c18550ace670e0410453741d11dafa474Ian Lake}
454