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