Home | History | Annotate | Download | only in notifications
      1 /*
      2  * Copyright (C) 2013 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.cts.verifier.notifications;
     18 
     19 import android.annotation.SuppressLint;
     20 import android.app.Activity;
     21 import android.app.Notification;
     22 import android.provider.Settings.Secure;
     23 import android.util.Log;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 
     27 import com.android.cts.verifier.R;
     28 
     29 import org.json.JSONException;
     30 import org.json.JSONObject;
     31 
     32 import java.util.ArrayList;
     33 import java.util.HashSet;
     34 import java.util.List;
     35 import java.util.Set;
     36 import java.util.UUID;
     37 
     38 import static com.android.cts.verifier.notifications.MockListener.*;
     39 
     40 public class NotificationListenerVerifierActivity extends InteractiveVerifierActivity
     41         implements Runnable {
     42     private static final String TAG = "NoListenerVerifier";
     43 
     44     private String mTag1;
     45     private String mTag2;
     46     private String mTag3;
     47     private int mIcon1;
     48     private int mIcon2;
     49     private int mIcon3;
     50     private int mId1;
     51     private int mId2;
     52     private int mId3;
     53     private long mWhen1;
     54     private long mWhen2;
     55     private long mWhen3;
     56     private int mFlag1;
     57     private int mFlag2;
     58     private int mFlag3;
     59 
     60     @Override
     61     int getTitleResource() {
     62         return R.string.nls_test;
     63     }
     64 
     65     @Override
     66     int getInstructionsResource() {
     67         return R.string.nls_info;
     68     }
     69 
     70     // Test Setup
     71 
     72     @Override
     73     protected List<InteractiveTestCase> createTestItems() {
     74         List<InteractiveTestCase> tests = new ArrayList<>(9);
     75         tests.add(new IsEnabledTest());
     76         tests.add(new ServiceStartedTest());
     77         tests.add(new NotificationRecievedTest());
     78         tests.add(new DataIntactTest());
     79         tests.add(new DismissOneTest());
     80         tests.add(new DismissAllTest());
     81         tests.add(new IsDisabledTest());
     82         tests.add(new ServiceStoppedTest());
     83         tests.add(new NotificationNotReceivedTest());
     84         return tests;
     85     }
     86 
     87     @SuppressLint("NewApi")
     88     private void sendNotifications() {
     89         mTag1 = UUID.randomUUID().toString();
     90         mTag2 = UUID.randomUUID().toString();
     91         mTag3 = UUID.randomUUID().toString();
     92 
     93         mNm.cancelAll();
     94 
     95         mWhen1 = System.currentTimeMillis() + 1;
     96         mWhen2 = System.currentTimeMillis() + 2;
     97         mWhen3 = System.currentTimeMillis() + 3;
     98 
     99         mIcon1 = R.drawable.ic_stat_alice;
    100         mIcon2 = R.drawable.ic_stat_bob;
    101         mIcon3 = R.drawable.ic_stat_charlie;
    102 
    103         mId1 = NOTIFICATION_ID + 1;
    104         mId2 = NOTIFICATION_ID + 2;
    105         mId3 = NOTIFICATION_ID + 3;
    106 
    107         mPackageString = "com.android.cts.verifier";
    108 
    109         Notification n1 = new Notification.Builder(mContext)
    110                 .setContentTitle("ClearTest 1")
    111                 .setContentText(mTag1.toString())
    112                 .setPriority(Notification.PRIORITY_LOW)
    113                 .setSmallIcon(mIcon1)
    114                 .setWhen(mWhen1)
    115                 .setDeleteIntent(makeIntent(1, mTag1))
    116                 .setOnlyAlertOnce(true)
    117                 .build();
    118         mNm.notify(mTag1, mId1, n1);
    119         mFlag1 = Notification.FLAG_ONLY_ALERT_ONCE;
    120 
    121         Notification n2 = new Notification.Builder(mContext)
    122                 .setContentTitle("ClearTest 2")
    123                 .setContentText(mTag2.toString())
    124                 .setPriority(Notification.PRIORITY_HIGH)
    125                 .setSmallIcon(mIcon2)
    126                 .setWhen(mWhen2)
    127                 .setDeleteIntent(makeIntent(2, mTag2))
    128                 .setAutoCancel(true)
    129                 .build();
    130         mNm.notify(mTag2, mId2, n2);
    131         mFlag2 = Notification.FLAG_AUTO_CANCEL;
    132 
    133         Notification n3 = new Notification.Builder(mContext)
    134                 .setContentTitle("ClearTest 3")
    135                 .setContentText(mTag3.toString())
    136                 .setPriority(Notification.PRIORITY_LOW)
    137                 .setSmallIcon(mIcon3)
    138                 .setWhen(mWhen3)
    139                 .setDeleteIntent(makeIntent(3, mTag3))
    140                 .setAutoCancel(true)
    141                 .setOnlyAlertOnce(true)
    142                 .build();
    143         mNm.notify(mTag3, mId3, n3);
    144         mFlag3 = Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
    145     }
    146 
    147     // Tests
    148 
    149     private class NotificationRecievedTest extends InteractiveTestCase {
    150         @Override
    151         View inflate(ViewGroup parent) {
    152             return createAutoItem(parent, R.string.nls_note_received);
    153 
    154         }
    155 
    156         @Override
    157         void setUp() {
    158             sendNotifications();
    159             status = READY;
    160             // wait for notifications to move through the system
    161             delay();
    162         }
    163 
    164         @Override
    165         void test() {
    166             MockListener.probeListenerPosted(mContext,
    167                     new MockListener.StringListResultCatcher() {
    168                         @Override
    169                         public void accept(List<String> result) {
    170                             if (result != null && result.size() > 0 && result.contains(mTag1)) {
    171                                 status = PASS;
    172                             } else {
    173                                 logFail();
    174                                 status = FAIL;
    175                             }
    176                             next();
    177                         }
    178                     });
    179             delay();  // in case the catcher never returns
    180         }
    181     }
    182 
    183     private class DataIntactTest extends InteractiveTestCase {
    184         @Override
    185         View inflate(ViewGroup parent) {
    186             return createAutoItem(parent, R.string.nls_payload_intact);
    187         }
    188 
    189         @Override
    190         void test() {
    191             MockListener.probeListenerPayloads(mContext,
    192                     new MockListener.StringListResultCatcher() {
    193                         @Override
    194                         public void accept(List<String> result) {
    195                             Set<String> found = new HashSet<String>();
    196                             if (result == null || result.size() == 0) {
    197                                 status = FAIL;
    198                                 return;
    199                             }
    200                             boolean pass = true;
    201                             for (String payloadData : result) {
    202                                 try {
    203                                     JSONObject payload = new JSONObject(payloadData);
    204                                     pass &= checkEquals(mPackageString,
    205                                             payload.getString(JSON_PACKAGE),
    206                                             "data integrity test: notification package (%s, %s)");
    207                                     String tag = payload.getString(JSON_TAG);
    208                                     if (mTag1.equals(tag)) {
    209                                         found.add(mTag1);
    210                                         pass &= checkEquals(mIcon1, payload.getInt(JSON_ICON),
    211                                                 "data integrity test: notification icon (%d, %d)");
    212                                         pass &= checkFlagSet(mFlag1, payload.getInt(JSON_FLAGS),
    213                                                 "data integrity test: notification flags (%d, %d)");
    214                                         pass &= checkEquals(mId1, payload.getInt(JSON_ID),
    215                                                 "data integrity test: notification ID (%d, %d)");
    216                                         pass &= checkEquals(mWhen1, payload.getLong(JSON_WHEN),
    217                                                 "data integrity test: notification when (%d, %d)");
    218                                     } else if (mTag2.equals(tag)) {
    219                                         found.add(mTag2);
    220                                         pass &= checkEquals(mIcon2, payload.getInt(JSON_ICON),
    221                                                 "data integrity test: notification icon (%d, %d)");
    222                                         pass &= checkFlagSet(mFlag2, payload.getInt(JSON_FLAGS),
    223                                                 "data integrity test: notification flags (%d, %d)");
    224                                         pass &= checkEquals(mId2, payload.getInt(JSON_ID),
    225                                                 "data integrity test: notification ID (%d, %d)");
    226                                         pass &= checkEquals(mWhen2, payload.getLong(JSON_WHEN),
    227                                                 "data integrity test: notification when (%d, %d)");
    228                                     } else if (mTag3.equals(tag)) {
    229                                         found.add(mTag3);
    230                                         pass &= checkEquals(mIcon3, payload.getInt(JSON_ICON),
    231                                                 "data integrity test: notification icon (%d, %d)");
    232                                         pass &= checkFlagSet(mFlag3, payload.getInt(JSON_FLAGS),
    233                                                 "data integrity test: notification flags (%d, %d)");
    234                                         pass &= checkEquals(mId3, payload.getInt(JSON_ID),
    235                                                 "data integrity test: notification ID (%d, %d)");
    236                                         pass &= checkEquals(mWhen3, payload.getLong(JSON_WHEN),
    237                                                 "data integrity test: notification when (%d, %d)");
    238                                     } else {
    239                                         pass = false;
    240                                         logFail("unexpected notification tag: " + tag);
    241                                     }
    242                                 } catch (JSONException e) {
    243                                     pass = false;
    244                                     Log.e(TAG, "failed to unpack data from mocklistener", e);
    245                                 }
    246                             }
    247 
    248                             pass &= found.size() == 3;
    249                             status = pass ? PASS : FAIL;
    250                             next();
    251                         }
    252                     });
    253             delay();  // in case the catcher never returns
    254         }
    255 
    256         @Override
    257         void tearDown() {
    258             mNm.cancelAll();
    259             MockListener.resetListenerData(mContext);
    260             delay();
    261         }
    262     }
    263 
    264     private class DismissOneTest extends InteractiveTestCase {
    265         @Override
    266         View inflate(ViewGroup parent) {
    267             return createAutoItem(parent, R.string.nls_clear_one);
    268         }
    269 
    270         @Override
    271         void setUp() {
    272             sendNotifications();
    273             status = READY;
    274             delay();
    275         }
    276 
    277         @Override
    278         void test() {
    279             if (status == READY) {
    280                 MockListener.clearOne(mContext, mTag1, mId1);
    281                 status = RETEST;
    282             } else {
    283                 MockListener.probeListenerRemoved(mContext,
    284                         new MockListener.StringListResultCatcher() {
    285                             @Override
    286                             public void accept(List<String> result) {
    287                                 if (result != null && result.size() != 0
    288                                         && result.contains(mTag1)
    289                                         && !result.contains(mTag2)
    290                                         && !result.contains(mTag3)) {
    291                                     status = PASS;
    292                                 } else {
    293                                     logFail();
    294                                     status = FAIL;
    295                                 }
    296                                 next();
    297                             }
    298                         });
    299             }
    300             delay();
    301         }
    302 
    303         @Override
    304         void tearDown() {
    305             mNm.cancelAll();
    306             MockListener.resetListenerData(mContext);
    307             delay();
    308         }
    309     }
    310 
    311     private class DismissAllTest extends InteractiveTestCase {
    312         @Override
    313         View inflate(ViewGroup parent) {
    314             return createAutoItem(parent, R.string.nls_clear_all);
    315         }
    316 
    317         @Override
    318         void setUp() {
    319             sendNotifications();
    320             status = READY;
    321             delay();
    322         }
    323 
    324         @Override
    325         void test() {
    326             if (status == READY) {
    327                 MockListener.clearAll(mContext);
    328                 status = RETEST;
    329             } else {
    330                 MockListener.probeListenerRemoved(mContext,
    331                         new MockListener.StringListResultCatcher() {
    332                             @Override
    333                             public void accept(List<String> result) {
    334                                 if (result != null && result.size() != 0
    335                                         && result.contains(mTag1)
    336                                         && result.contains(mTag2)
    337                                         && result.contains(mTag3)) {
    338                                     status = PASS;
    339                                 } else {
    340                                     logFail();
    341                                     status = FAIL;
    342                                 }
    343                                 next();
    344                             }
    345                         });
    346             }
    347             delay();  // in case the catcher never returns
    348         }
    349 
    350         @Override
    351         void tearDown() {
    352             mNm.cancelAll();
    353             MockListener.resetListenerData(mContext);
    354             delay();
    355         }
    356     }
    357 
    358     private class IsDisabledTest extends InteractiveTestCase {
    359         @Override
    360         View inflate(ViewGroup parent) {
    361             return createNlsSettingsItem(parent, R.string.nls_disable_service);
    362         }
    363 
    364         @Override
    365         boolean autoStart() {
    366             return true;
    367         }
    368 
    369         @Override
    370         void test() {
    371             String listeners = Secure.getString(getContentResolver(),
    372                     ENABLED_NOTIFICATION_LISTENERS);
    373             if (listeners == null || !listeners.contains(LISTENER_PATH)) {
    374                 status = PASS;
    375             } else {
    376                 status = WAIT_FOR_USER;
    377             }
    378             next();
    379         }
    380 
    381         @Override
    382         void tearDown() {
    383             MockListener.resetListenerData(mContext);
    384             delay();
    385         }
    386     }
    387 
    388     private class ServiceStoppedTest extends InteractiveTestCase {
    389         @Override
    390         View inflate(ViewGroup parent) {
    391             return createAutoItem(parent, R.string.nls_service_stopped);
    392         }
    393 
    394         @Override
    395         void test() {
    396             MockListener.probeListenerStatus(mContext,
    397                     new MockListener.StatusCatcher() {
    398                         @Override
    399                         public void accept(int result) {
    400                             if (result == Activity.RESULT_OK) {
    401                                 logFail();
    402                                 status = FAIL;
    403                             } else {
    404                                 status = PASS;
    405                             }
    406                             next();
    407                         }
    408                     });
    409             delay();  // in case the catcher never returns
    410         }
    411 
    412         @Override
    413         void tearDown() {
    414             // wait for intent to move through the system
    415             delay();
    416         }
    417     }
    418 
    419     private class NotificationNotReceivedTest extends InteractiveTestCase {
    420         @Override
    421         View inflate(ViewGroup parent) {
    422             return createAutoItem(parent, R.string.nls_note_missed);
    423 
    424         }
    425 
    426         @Override
    427         void setUp() {
    428             sendNotifications();
    429             status = READY;
    430             delay();
    431         }
    432 
    433         @Override
    434         void test() {
    435             MockListener.probeListenerPosted(mContext,
    436                     new MockListener.StringListResultCatcher() {
    437                         @Override
    438                         public void accept(List<String> result) {
    439                             if (result == null || result.size() == 0) {
    440                                 status = PASS;
    441                             } else {
    442                                 logFail();
    443                                 status = FAIL;
    444                             }
    445                             next();
    446                         }
    447                     });
    448             delay();  // in case the catcher never returns
    449         }
    450 
    451         @Override
    452         void tearDown() {
    453             mNm.cancelAll();
    454             MockListener.resetListenerData(mContext);
    455             delay();
    456         }
    457     }
    458 }
    459