16fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek/*
26fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * Copyright (C) 2017 The Android Open Source Project
36fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek *
46fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * Licensed under the Apache License, Version 2.0 (the "License");
56fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * you may not use this file except in compliance with the License.
66fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * You may obtain a copy of the License at
76fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek *
86fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek *      http://www.apache.org/licenses/LICENSE-2.0
96fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek *
106fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * Unless required by applicable law or agreed to in writing, software
116fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * distributed under the License is distributed on an "AS IS" BASIS,
126fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * See the License for the specific language governing permissions and
146fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek * limitations under the License
156fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek */
166fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
176fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekpackage com.android.systemui.statusbar;
186fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
19524cf7b68df47b39509cee59523458efb7611210Rohan Shahimport android.annotation.Nullable;
206fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.app.ActivityManager;
215ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinekimport android.app.Instrumentation;
226fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.app.Notification;
236fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.content.Context;
246fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.os.UserHandle;
256fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.service.notification.StatusBarNotification;
265ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinekimport android.support.test.InstrumentationRegistry;
27524cf7b68df47b39509cee59523458efb7611210Rohan Shahimport android.text.TextUtils;
286fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.view.LayoutInflater;
296fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport android.widget.RemoteViews;
306fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
316fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport com.android.systemui.R;
325ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinekimport com.android.systemui.statusbar.notification.NotificationInflaterTest;
334e30e763473859bbe1755e446af08fc7325267b4yoshiki iguchiimport com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
346fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekimport com.android.systemui.statusbar.phone.NotificationGroupManager;
355cf1d0589a0045ee5f01802975f394847e891215Selim Cinekimport com.android.systemui.statusbar.policy.HeadsUpManager;
366fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
376fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek/**
38524cf7b68df47b39509cee59523458efb7611210Rohan Shah * A helper class to create {@link ExpandableNotificationRow} (for both individual and group
39524cf7b68df47b39509cee59523458efb7611210Rohan Shah * notifications).
406fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek */
416fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinekpublic class NotificationTestHelper {
426fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
43524cf7b68df47b39509cee59523458efb7611210Rohan Shah    static final String PKG = "com.android.systemui";
44524cf7b68df47b39509cee59523458efb7611210Rohan Shah    static final int UID = 1000;
45524cf7b68df47b39509cee59523458efb7611210Rohan Shah    private static final String GROUP_KEY = "gruKey";
46524cf7b68df47b39509cee59523458efb7611210Rohan Shah
476fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek    private final Context mContext;
485ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinek    private final Instrumentation mInstrumentation;
496fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek    private int mId;
506fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek    private final NotificationGroupManager mGroupManager = new NotificationGroupManager();
515ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinek    private ExpandableNotificationRow mRow;
525cf1d0589a0045ee5f01802975f394847e891215Selim Cinek    private HeadsUpManager mHeadsUpManager;
536fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
546fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek    public NotificationTestHelper(Context context) {
556fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek        mContext = context;
565ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinek        mInstrumentation = InstrumentationRegistry.getInstrumentation();
574e30e763473859bbe1755e446af08fc7325267b4yoshiki iguchi        mHeadsUpManager = new HeadsUpManagerPhone(mContext, null, mGroupManager, null, null);
586fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek    }
596fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
60524cf7b68df47b39509cee59523458efb7611210Rohan Shah    public ExpandableNotificationRow createRow() throws Exception {
61524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return createRow(PKG, UID);
62524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
63524cf7b68df47b39509cee59523458efb7611210Rohan Shah
64fc64001126c62581447b4b0e9c843d60af5c14c6Julia Reynolds    public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception {
65524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */);
66524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
67524cf7b68df47b39509cee59523458efb7611210Rohan Shah
68524cf7b68df47b39509cee59523458efb7611210Rohan Shah    public ExpandableNotificationRow createRow(Notification notification) throws Exception {
69524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return generateRow(notification, PKG, UID, false /* isGroupRow */);
70524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
71524cf7b68df47b39509cee59523458efb7611210Rohan Shah
72524cf7b68df47b39509cee59523458efb7611210Rohan Shah    /**
73524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * Returns an {@link ExpandableNotificationRow} group with the given number of child
74524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * notifications.
75524cf7b68df47b39509cee59523458efb7611210Rohan Shah     */
76524cf7b68df47b39509cee59523458efb7611210Rohan Shah    public ExpandableNotificationRow createGroup(int numChildren) throws Exception {
77524cf7b68df47b39509cee59523458efb7611210Rohan Shah        ExpandableNotificationRow row = createGroupSummary(GROUP_KEY);
78524cf7b68df47b39509cee59523458efb7611210Rohan Shah        for (int i = 0; i < numChildren; i++) {
79524cf7b68df47b39509cee59523458efb7611210Rohan Shah            ExpandableNotificationRow childRow = createGroupChild(GROUP_KEY);
80524cf7b68df47b39509cee59523458efb7611210Rohan Shah            row.addChildNotification(childRow);
81524cf7b68df47b39509cee59523458efb7611210Rohan Shah        }
82524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return row;
83524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
84524cf7b68df47b39509cee59523458efb7611210Rohan Shah
85524cf7b68df47b39509cee59523458efb7611210Rohan Shah    /** Returns a group notification with 2 child notifications. */
86524cf7b68df47b39509cee59523458efb7611210Rohan Shah    public ExpandableNotificationRow createGroup() throws Exception {
87524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return createGroup(2);
88524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
89524cf7b68df47b39509cee59523458efb7611210Rohan Shah
90524cf7b68df47b39509cee59523458efb7611210Rohan Shah    private ExpandableNotificationRow createGroupSummary(String groupkey) throws Exception {
91524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return createRow(PKG, UID, true /* isGroupSummary */, groupkey);
92524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
93524cf7b68df47b39509cee59523458efb7611210Rohan Shah
94524cf7b68df47b39509cee59523458efb7611210Rohan Shah    private ExpandableNotificationRow createGroupChild(String groupkey) throws Exception {
95524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return createRow(PKG, UID, false /* isGroupSummary */, groupkey);
96524cf7b68df47b39509cee59523458efb7611210Rohan Shah    }
97524cf7b68df47b39509cee59523458efb7611210Rohan Shah
98524cf7b68df47b39509cee59523458efb7611210Rohan Shah    /**
99524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * Creates a notification row with the given details.
100524cf7b68df47b39509cee59523458efb7611210Rohan Shah     *
101524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * @param pkg package used for creating a {@link StatusBarNotification}
102524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * @param uid uid used for creating a {@link StatusBarNotification}
103524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * @param isGroupSummary whether the notification row is a group summary
104524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * @param groupKey the group key for the notification group used across notifications
105524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * @return a row with that's either a standalone notification or a group notification if the
106524cf7b68df47b39509cee59523458efb7611210Rohan Shah     *         groupKey is non-null
107524cf7b68df47b39509cee59523458efb7611210Rohan Shah     * @throws Exception
108524cf7b68df47b39509cee59523458efb7611210Rohan Shah     */
109524cf7b68df47b39509cee59523458efb7611210Rohan Shah    private ExpandableNotificationRow createRow(
110524cf7b68df47b39509cee59523458efb7611210Rohan Shah            String pkg,
111524cf7b68df47b39509cee59523458efb7611210Rohan Shah            int uid,
112524cf7b68df47b39509cee59523458efb7611210Rohan Shah            boolean isGroupSummary,
113524cf7b68df47b39509cee59523458efb7611210Rohan Shah            @Nullable String groupKey)
114524cf7b68df47b39509cee59523458efb7611210Rohan Shah            throws Exception {
1156fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek        Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
1166fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek                R.drawable.ic_person)
1176fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek                .setCustomContentView(new RemoteViews(mContext.getPackageName(),
1186fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek                        R.layout.custom_view_dark))
1196fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek                .build();
120524cf7b68df47b39509cee59523458efb7611210Rohan Shah        Notification.Builder notificationBuilder =
121524cf7b68df47b39509cee59523458efb7611210Rohan Shah                new Notification.Builder(mContext)
122524cf7b68df47b39509cee59523458efb7611210Rohan Shah                        .setSmallIcon(R.drawable.ic_person)
123524cf7b68df47b39509cee59523458efb7611210Rohan Shah                        .setContentTitle("Title")
124524cf7b68df47b39509cee59523458efb7611210Rohan Shah                        .setContentText("Text")
125524cf7b68df47b39509cee59523458efb7611210Rohan Shah                        .setPublicVersion(publicVersion);
126fc64001126c62581447b4b0e9c843d60af5c14c6Julia Reynolds
127524cf7b68df47b39509cee59523458efb7611210Rohan Shah        // Group notification setup
128524cf7b68df47b39509cee59523458efb7611210Rohan Shah        if (isGroupSummary) {
129524cf7b68df47b39509cee59523458efb7611210Rohan Shah            notificationBuilder.setGroupSummary(true);
130524cf7b68df47b39509cee59523458efb7611210Rohan Shah        }
131524cf7b68df47b39509cee59523458efb7611210Rohan Shah        if (!TextUtils.isEmpty(groupKey)) {
132524cf7b68df47b39509cee59523458efb7611210Rohan Shah            notificationBuilder.setGroup(groupKey);
133524cf7b68df47b39509cee59523458efb7611210Rohan Shah        }
13410790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek
135524cf7b68df47b39509cee59523458efb7611210Rohan Shah        return generateRow(notificationBuilder.build(), pkg, uid, !TextUtils.isEmpty(groupKey));
136fc64001126c62581447b4b0e9c843d60af5c14c6Julia Reynolds    }
137fc64001126c62581447b4b0e9c843d60af5c14c6Julia Reynolds
138524cf7b68df47b39509cee59523458efb7611210Rohan Shah    private ExpandableNotificationRow generateRow(
139524cf7b68df47b39509cee59523458efb7611210Rohan Shah            Notification notification,
140524cf7b68df47b39509cee59523458efb7611210Rohan Shah            String pkg,
141524cf7b68df47b39509cee59523458efb7611210Rohan Shah            int uid,
142524cf7b68df47b39509cee59523458efb7611210Rohan Shah            boolean isGroupRow)
143fc64001126c62581447b4b0e9c843d60af5c14c6Julia Reynolds            throws Exception {
14410790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
14510790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek                mContext.LAYOUT_INFLATER_SERVICE);
1466dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk        mRow = (ExpandableNotificationRow) inflater.inflate(
1476dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk                R.layout.status_bar_notification_row,
1486dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk                null /* root */,
1496dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk                false /* attachToRoot */);
1505ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinek        ExpandableNotificationRow row = mRow;
15110790672a98debafb8882971e94ff26aec9a6bfaSelim Cinek        row.setGroupManager(mGroupManager);
1525cf1d0589a0045ee5f01802975f394847e891215Selim Cinek        row.setHeadsUpManager(mHeadsUpManager);
1535cf1d0589a0045ee5f01802975f394847e891215Selim Cinek        row.setAboveShelfChangedListener(aboveShelf -> {});
1546fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek        UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
155524cf7b68df47b39509cee59523458efb7611210Rohan Shah        StatusBarNotification sbn = new StatusBarNotification(
156524cf7b68df47b39509cee59523458efb7611210Rohan Shah                pkg,
157524cf7b68df47b39509cee59523458efb7611210Rohan Shah                pkg,
158524cf7b68df47b39509cee59523458efb7611210Rohan Shah                mId++,
159524cf7b68df47b39509cee59523458efb7611210Rohan Shah                null /* tag */,
160524cf7b68df47b39509cee59523458efb7611210Rohan Shah                uid,
161524cf7b68df47b39509cee59523458efb7611210Rohan Shah                2000 /* initialPid */,
162524cf7b68df47b39509cee59523458efb7611210Rohan Shah                notification,
163524cf7b68df47b39509cee59523458efb7611210Rohan Shah                mUser,
164524cf7b68df47b39509cee59523458efb7611210Rohan Shah                null /* overrideGroupKey */,
165524cf7b68df47b39509cee59523458efb7611210Rohan Shah                System.currentTimeMillis());
1666fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek        NotificationData.Entry entry = new NotificationData.Entry(sbn);
1676fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek        entry.row = row;
1685ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinek        entry.createIcons(mContext, sbn);
169524cf7b68df47b39509cee59523458efb7611210Rohan Shah        NotificationInflaterTest.runThenWaitForInflation(
170524cf7b68df47b39509cee59523458efb7611210Rohan Shah                () -> row.updateNotification(entry),
1715ba2254df1cb71355efb0a3831581e2f2babcdbeSelim Cinek                row.getNotificationInflater());
1726fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek
173524cf7b68df47b39509cee59523458efb7611210Rohan Shah        // This would be done as part of onAsyncInflationFinished, but we skip large amounts of
174524cf7b68df47b39509cee59523458efb7611210Rohan Shah        // the callback chain, so we need to make up for not adding it to the group manager
175524cf7b68df47b39509cee59523458efb7611210Rohan Shah        // here.
176524cf7b68df47b39509cee59523458efb7611210Rohan Shah        mGroupManager.onEntryAdded(entry);
1776fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek        return row;
1786fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek    }
1796fd06b5b8089952a7fa6e3286d246ab910090b79Selim Cinek}
180