1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.cts; 18 19 import android.app.PolicyProto; 20 import android.service.notification.ConditionProto; 21 import android.service.notification.ManagedServicesProto; 22 import android.service.notification.NotificationRecordProto; 23 import android.service.notification.NotificationServiceDumpProto; 24 import android.service.notification.RankingHelperProto; 25 import android.service.notification.RankingHelperProto.RecordProto; 26 import android.service.notification.ZenMode; 27 import android.service.notification.ZenModeProto; 28 import android.service.notification.ZenRuleProto; 29 30 import java.util.List; 31 32 /** 33 * Test to check that the notification service properly outputs its dump state. 34 * 35 * make -j32 CtsIncidentHostTestCases 36 * cts-tradefed run singleCommand cts-dev -d --module CtsIncidentHostTestCases 37 */ 38 public class NotificationIncidentTest extends ProtoDumpTestCase { 39 // Constants from android.app.NotificationManager 40 private static final int IMPORTANCE_UNSPECIFIED = -1000; 41 private static final int IMPORTANCE_NONE = 0; 42 private static final int IMPORTANCE_MAX = 5; 43 private static final int VISIBILITY_NO_OVERRIDE = -1000; 44 // Constants from android.app.Notification 45 private static final int PRIORITY_MIN = -2; 46 private static final int PRIORITY_MAX = 2; 47 private static final int VISIBILITY_SECRET = -1; 48 private static final int VISIBILITY_PUBLIC = 1; 49 // These constants are those in PackageManager. 50 public static final String FEATURE_WATCH = "android.hardware.type.watch"; 51 52 private static final String DEVICE_SIDE_TEST_APK = "CtsNotificationIncidentTestApp.apk"; 53 private static final String TEST_APP_TAG = "NotificationIncidentTestActivity"; 54 private static final String TEST_APP_LOG = "Notification posted."; 55 private static final String TEST_ACTIVITY = 56 "com.android.server.cts.notifications/.NotificationIncidentTestActivity"; 57 private static final int WAIT_MS = 1000; 58 59 /** 60 * Tests that at least one notification is posted, and verify its properties are plausible. 61 */ testNotificationRecords()62 public void testNotificationRecords() throws Exception { 63 installPackage(DEVICE_SIDE_TEST_APK, /* grantPermissions= */ true); 64 int retries = 3; 65 do { 66 getDevice().executeShellCommand("am start -n " + TEST_ACTIVITY); 67 } while (!checkLogcatForText(TEST_APP_TAG, TEST_APP_LOG, WAIT_MS) && retries-- > 0); 68 69 final NotificationServiceDumpProto dump = getDump(NotificationServiceDumpProto.parser(), 70 "dumpsys notification --proto"); 71 72 assertTrue(dump.getRecordsCount() > 0); 73 boolean found = false; 74 for (NotificationRecordProto record : dump.getRecordsList()) { 75 if (record.getKey().contains("android")) { 76 found = true; 77 assertTrue(record.getImportance() > IMPORTANCE_NONE); 78 79 // Ensure these fields exist, at least 80 record.getFlags(); 81 record.getChannelId(); 82 record.getSound(); 83 record.getAudioAttributes(); 84 record.getCanVibrate(); 85 record.getCanShowLight(); 86 record.getGroupKey(); 87 } 88 assertTrue( 89 NotificationRecordProto.State.getDescriptor() 90 .getValues() 91 .contains(record.getState().getValueDescriptor())); 92 } 93 94 assertTrue(found); 95 } 96 97 /** Test valid values from the RankingHelper. */ testRankingConfig()98 public void testRankingConfig() throws Exception { 99 final NotificationServiceDumpProto dump = getDump(NotificationServiceDumpProto.parser(), 100 "dumpsys notification --proto"); 101 102 verifyRankingHelperProto(dump.getRankingConfig(), PRIVACY_NONE); 103 } 104 verifyRankingHelperProto(RankingHelperProto rhProto, final int filterLevel)105 private static void verifyRankingHelperProto(RankingHelperProto rhProto, final int filterLevel) throws Exception { 106 for (RecordProto rp : rhProto.getRecordsList()) { 107 verifyRecordProto(rp); 108 } 109 for (RecordProto rp : rhProto.getRecordsRestoredWithoutUidList()) { 110 verifyRecordProto(rp); 111 } 112 } 113 verifyRecordProto(RecordProto rp)114 private static void verifyRecordProto(RecordProto rp) throws Exception { 115 assertTrue(!rp.getPackage().isEmpty()); 116 assertTrue(rp.getUid() == -10000 || rp.getUid() >= 0); 117 assertTrue("Record importance is an invalid value: " + rp.getImportance(), 118 rp.getImportance() == IMPORTANCE_UNSPECIFIED || 119 (rp.getImportance() >= IMPORTANCE_NONE && rp.getImportance() <= IMPORTANCE_MAX)); 120 assertTrue(rp.getPriority() >= PRIORITY_MIN && rp.getPriority() <= PRIORITY_MAX); 121 assertTrue("Record visibility is an invalid value: " + rp.getVisibility(), 122 rp.getVisibility() == VISIBILITY_NO_OVERRIDE || 123 (rp.getVisibility() >= VISIBILITY_SECRET && 124 rp.getVisibility() <= VISIBILITY_PUBLIC)); 125 } 126 127 // Tests default state: zen mode is a valid/expected value testZenMode()128 public void testZenMode() throws Exception { 129 final NotificationServiceDumpProto dump = getDump(NotificationServiceDumpProto.parser(), 130 "dumpsys notification --proto"); 131 132 verifyZenModeProto(dump.getZen(), PRIVACY_NONE); 133 } 134 verifyZenModeProto(ZenModeProto zenProto, final int filterLevel)135 private static void verifyZenModeProto(ZenModeProto zenProto, final int filterLevel) throws Exception { 136 assertTrue("Unexpected ZenMode value", 137 ZenMode.getDescriptor().getValues().contains(zenProto.getZenMode().getValueDescriptor())); 138 139 List<ZenRuleProto> zenRules = zenProto.getEnabledActiveConditionsList(); 140 for (int i = 0; i < zenRules.size(); ++i) { 141 ZenRuleProto zr = zenRules.get(i); 142 ConditionProto cp = zr.getCondition(); 143 if (filterLevel == PRIVACY_AUTO) { 144 assertTrue(zr.getId().isEmpty()); 145 assertTrue(zr.getName().isEmpty()); 146 assertTrue(zr.getConditionId().isEmpty()); 147 148 assertTrue(cp.getId().isEmpty()); 149 assertTrue(cp.getSummary().isEmpty()); 150 assertTrue(cp.getLine1().isEmpty()); 151 assertTrue(cp.getLine2().isEmpty()); 152 } else if (i > 0) { 153 // There will be at most one manual rule, the rest will be automatic. The fields 154 // tested here are required for automatic rules. 155 assertFalse(zr.getId().isEmpty()); 156 assertFalse(zr.getName().isEmpty()); 157 assertTrue(zr.getCreationTimeMs() > 0); 158 assertFalse(zr.getConditionId().isEmpty()); 159 } 160 161 assertTrue(ConditionProto.State.getDescriptor().getValues() 162 .contains(cp.getState().getValueDescriptor())); 163 } 164 165 PolicyProto policy = zenProto.getPolicy(); 166 for (PolicyProto.Category c : policy.getPriorityCategoriesList()) { 167 assertTrue(PolicyProto.Category.getDescriptor().getValues() 168 .contains(c.getValueDescriptor())); 169 } 170 assertTrue(PolicyProto.Sender.getDescriptor().getValues() 171 .contains(policy.getPriorityCallSender().getValueDescriptor())); 172 assertTrue(PolicyProto.Sender.getDescriptor().getValues() 173 .contains(policy.getPriorityMessageSender().getValueDescriptor())); 174 for (PolicyProto.SuppressedVisualEffect sve : policy.getSuppressedVisualEffectsList()) { 175 assertTrue(PolicyProto.SuppressedVisualEffect.getDescriptor().getValues() 176 .contains(sve.getValueDescriptor())); 177 } 178 } 179 verifyNotificationServiceDumpProto(NotificationServiceDumpProto dump, final int filterLevel)180 static void verifyNotificationServiceDumpProto(NotificationServiceDumpProto dump, final int filterLevel) throws Exception { 181 for (NotificationRecordProto nr : dump.getRecordsList()) { 182 verifyNotificationRecordProto(nr, filterLevel); 183 } 184 verifyZenModeProto(dump.getZen(), filterLevel); 185 verifyManagedServicesProto(dump.getNotificationListeners(), filterLevel); 186 verifyManagedServicesProto(dump.getNotificationAssistants(), filterLevel); 187 verifyManagedServicesProto(dump.getConditionProviders(), filterLevel); 188 verifyRankingHelperProto(dump.getRankingConfig(), filterLevel); 189 } 190 verifyManagedServicesProto(ManagedServicesProto ms, final int filterLevel)191 private static void verifyManagedServicesProto(ManagedServicesProto ms, final int filterLevel) throws Exception { 192 for (ManagedServicesProto.ServiceProto sp : ms.getApprovedList()) { 193 for (String n : sp.getNameList()) { 194 assertFalse(n.isEmpty()); 195 } 196 assertTrue(sp.getUserId() >= 0); 197 } 198 } 199 verifyNotificationRecordProto(NotificationRecordProto record, final int filterLevel)200 private static void verifyNotificationRecordProto(NotificationRecordProto record, final int filterLevel) throws Exception { 201 // Ensure these fields exist, at least 202 record.getFlags(); 203 record.getChannelId(); 204 record.getSound(); 205 record.getAudioAttributes(); 206 record.getCanVibrate(); 207 record.getCanShowLight(); 208 record.getGroupKey(); 209 210 if (filterLevel == PRIVACY_AUTO) { 211 assertTrue(record.getChannelId().isEmpty()); 212 assertTrue(record.getSound().isEmpty()); 213 assertTrue(record.getGroupKey().isEmpty()); 214 } 215 216 assertTrue(NotificationRecordProto.State.getDescriptor().getValues() 217 .contains(record.getState().getValueDescriptor())); 218 } 219 } 220