• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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