Home | History | Annotate | Download | only in cts
      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      */
     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. */
     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 
    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 
    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
    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 
    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 
    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 
    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 
    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