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 package com.android.cts.verifier.notifications;
     17 
     18 import android.app.Activity;
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.os.Bundle;
     24 import android.service.notification.NotificationListenerService;
     25 import android.service.notification.StatusBarNotification;
     26 import android.util.ArrayMap;
     27 import android.util.Log;
     28 
     29 import org.json.JSONException;
     30 import org.json.JSONObject;
     31 
     32 import java.lang.reflect.InvocationTargetException;
     33 import java.util.ArrayList;
     34 import java.util.HashSet;
     35 import java.util.List;
     36 import java.util.Set;
     37 
     38 public class MockListener extends NotificationListenerService {
     39     static final String TAG = "MockListener";
     40 
     41     static final String SERVICE_BASE = "android.service.notification.cts.";
     42     static final String SERVICE_CHECK = SERVICE_BASE + "SERVICE_CHECK";
     43     static final String SERVICE_POSTED = SERVICE_BASE + "SERVICE_POSTED";
     44     static final String SERVICE_PAYLOADS = SERVICE_BASE + "SERVICE_PAYLOADS";
     45     static final String SERVICE_REMOVED = SERVICE_BASE + "SERVICE_REMOVED";
     46     static final String SERVICE_RESET = SERVICE_BASE + "SERVICE_RESET";
     47     static final String SERVICE_CLEAR_ONE = SERVICE_BASE + "SERVICE_CLEAR_ONE";
     48     static final String SERVICE_CLEAR_ALL = SERVICE_BASE + "SERVICE_CLEAR_ALL";
     49     public static final String SERVICE_ORDER = SERVICE_BASE + "SERVICE_ORDER";
     50     public static final String SERVICE_DND = SERVICE_BASE + "SERVICE_DND";
     51 
     52     static final String EXTRA_PAYLOAD = "PAYLOAD";
     53     static final String EXTRA_INT = "INT";
     54     static final String EXTRA_TAG = "TAG";
     55     static final String EXTRA_CODE = "CODE";
     56 
     57     static final int RESULT_TIMEOUT = Activity.RESULT_FIRST_USER;
     58     static final int RESULT_NO_SERVER = Activity.RESULT_FIRST_USER + 1;
     59 
     60     public static final String JSON_FLAGS = "flag";
     61     public static final String JSON_ICON = "icon";
     62     public static final String JSON_ID = "id";
     63     public static final String JSON_PACKAGE = "pkg";
     64     public static final String JSON_WHEN = "when";
     65     public static final String JSON_TAG = "tag";
     66     public static final String JSON_RANK = "rank";
     67     public static final String JSON_AMBIENT = "ambient";
     68     public static final String JSON_MATCHES_ZEN_FILTER = "matches_zen_filter";
     69 
     70     private ArrayList<String> mPosted = new ArrayList<String>();
     71     private ArrayMap<String, JSONObject> mNotifications = new ArrayMap<>();
     72     private ArrayMap<String, String> mNotificationKeys = new ArrayMap<>();
     73     private ArrayList<String> mRemoved = new ArrayList<String>();
     74     private ArrayList<String> mOrder = new ArrayList<>();
     75     private Set<String> mTestPackages = new HashSet<>();
     76     private BroadcastReceiver mReceiver;
     77     private int mDND = -1;
     78 
     79     @Override
     80     public void onCreate() {
     81         super.onCreate();
     82         Log.d(TAG, "created");
     83 
     84         mTestPackages.add("com.android.cts.verifier");
     85         mTestPackages.add("com.android.cts.robot");
     86 
     87         mPosted = new ArrayList<String>();
     88         mRemoved = new ArrayList<String>();
     89 
     90         mReceiver = new BroadcastReceiver() {
     91             @Override
     92             public void onReceive(Context context, Intent intent) {
     93                 String action = intent.getAction();
     94                 if (SERVICE_CHECK.equals(action)) {
     95                     Log.d(TAG, "SERVICE_CHECK");
     96                     setResultCode(Activity.RESULT_OK);
     97                 } else if (SERVICE_POSTED.equals(action)) {
     98                     Log.d(TAG, "SERVICE_POSTED");
     99                     Bundle bundle = new Bundle();
    100                     bundle.putStringArrayList(EXTRA_PAYLOAD, mPosted);
    101                     setResultExtras(bundle);
    102                     setResultCode(Activity.RESULT_OK);
    103                 } else if (SERVICE_DND.equals(action)) {
    104                     Log.d(TAG, "SERVICE_DND");
    105                     Bundle bundle = new Bundle();
    106                     bundle.putInt(EXTRA_INT, mDND);
    107                     setResultExtras(bundle);
    108                     setResultCode(Activity.RESULT_OK);
    109                 } else if (SERVICE_ORDER.equals(action)) {
    110                     Log.d(TAG, "SERVICE_ORDER");
    111                     Bundle bundle = new Bundle();
    112                     bundle.putStringArrayList(EXTRA_PAYLOAD, mOrder);
    113                     setResultExtras(bundle);
    114                     setResultCode(Activity.RESULT_OK);
    115                 } else if (SERVICE_PAYLOADS.equals(action)) {
    116                     Log.d(TAG, "SERVICE_PAYLOADS");
    117                     Bundle bundle = new Bundle();
    118                     ArrayList<String> payloadData = new ArrayList<>(mNotifications.size());
    119                     for (JSONObject payload: mNotifications.values()) {
    120                         payloadData.add(payload.toString());
    121                     }
    122                     bundle.putStringArrayList(EXTRA_PAYLOAD, payloadData);
    123                     setResultExtras(bundle);
    124                     setResultCode(Activity.RESULT_OK);
    125                 } else if (SERVICE_REMOVED.equals(action)) {
    126                     Log.d(TAG, "SERVICE_REMOVED");
    127                     Bundle bundle = new Bundle();
    128                     bundle.putStringArrayList(EXTRA_PAYLOAD, mRemoved);
    129                     setResultExtras(bundle);
    130                     setResultCode(Activity.RESULT_OK);
    131                 } else if (SERVICE_CLEAR_ONE.equals(action)) {
    132                     Log.d(TAG, "SERVICE_CLEAR_ONE");
    133                     String tag = intent.getStringExtra(EXTRA_TAG);
    134                     String key = mNotificationKeys.get(tag);
    135                     if (key != null) {
    136                         MockListener.this.cancelNotification(key);
    137                     } else {
    138                         Log.w(TAG, "Notification does not exist: " + tag);
    139                     }
    140                 } else if (SERVICE_CLEAR_ALL.equals(action)) {
    141                     Log.d(TAG, "SERVICE_CLEAR_ALL");
    142                     MockListener.this.cancelAllNotifications();
    143                 } else if (SERVICE_RESET.equals(action)) {
    144                     Log.d(TAG, "SERVICE_RESET");
    145                     resetData();
    146                 } else {
    147                     Log.w(TAG, "unknown action");
    148                     setResultCode(Activity.RESULT_CANCELED);
    149                 }
    150             }
    151         };
    152         IntentFilter filter = new IntentFilter();
    153         filter.addAction(SERVICE_CHECK);
    154         filter.addAction(SERVICE_DND);
    155         filter.addAction(SERVICE_POSTED);
    156         filter.addAction(SERVICE_ORDER);
    157         filter.addAction(SERVICE_PAYLOADS);
    158         filter.addAction(SERVICE_REMOVED);
    159         filter.addAction(SERVICE_CLEAR_ONE);
    160         filter.addAction(SERVICE_CLEAR_ALL);
    161         filter.addAction(SERVICE_RESET);
    162         registerReceiver(mReceiver, filter);
    163     }
    164 
    165     @Override
    166     public void onDestroy() {
    167         super.onDestroy();
    168         unregisterReceiver(mReceiver);
    169         mReceiver = null;
    170         Log.d(TAG, "destroyed");
    171     }
    172 
    173     @Override
    174     public void onListenerConnected() {
    175         super.onListenerConnected();
    176         mDND = getCurrentInterruptionFilter();
    177         Log.d(TAG, "initial value of CurrentInterruptionFilter is " + mDND);
    178     }
    179 
    180     @Override
    181     public void onInterruptionFilterChanged(int interruptionFilter) {
    182         super.onInterruptionFilterChanged(interruptionFilter);
    183         mDND = interruptionFilter;
    184         Log.d(TAG, "value of CurrentInterruptionFilter changed to " + mDND);
    185     }
    186 
    187     public void resetData() {
    188         mPosted.clear();
    189         mNotifications.clear();
    190         mRemoved.clear();
    191         mOrder.clear();
    192     }
    193 
    194     @Override
    195     public void onNotificationRankingUpdate(RankingMap rankingMap) {
    196         String[] orderedKeys = rankingMap.getOrderedKeys();
    197         mOrder.clear();
    198         Ranking rank = new Ranking();
    199         for( int i = 0; i < orderedKeys.length; i++) {
    200             String key = orderedKeys[i];
    201             mOrder.add(key);
    202             rankingMap.getRanking(key, rank);
    203             JSONObject note = mNotifications.get(key);
    204             if (note != null) {
    205                 try {
    206                     note.put(JSON_RANK, rank.getRank());
    207                     note.put(JSON_AMBIENT, rank.isAmbient());
    208                     note.put(JSON_MATCHES_ZEN_FILTER, rank.matchesInterruptionFilter());
    209                 } catch (JSONException e) {
    210                     Log.e(TAG, "failed to pack up notification payload", e);
    211                 }
    212             }
    213         }
    214     }
    215 
    216     @Override
    217     public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
    218         if (!mTestPackages.contains(sbn.getPackageName())) { return; }
    219         Log.d(TAG, "posted: " + sbn.getTag());
    220         mPosted.add(sbn.getTag());
    221         JSONObject notification = new JSONObject();
    222         try {
    223             notification.put(JSON_TAG, sbn.getTag());
    224             notification.put(JSON_ID, sbn.getId());
    225             notification.put(JSON_PACKAGE, sbn.getPackageName());
    226             notification.put(JSON_WHEN, sbn.getNotification().when);
    227             notification.put(JSON_ICON, sbn.getNotification().icon);
    228             notification.put(JSON_FLAGS, sbn.getNotification().flags);
    229             mNotifications.put(sbn.getKey(), notification);
    230             mNotificationKeys.put(sbn.getTag(), sbn.getKey());
    231         } catch (JSONException e) {
    232             Log.e(TAG, "failed to pack up notification payload", e);
    233         }
    234         onNotificationRankingUpdate(rankingMap);
    235     }
    236 
    237     @Override
    238     public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
    239         Log.d(TAG, "removed: " + sbn.getTag());
    240         mRemoved.add(sbn.getTag());
    241         mNotifications.remove(sbn.getKey());
    242         mNotificationKeys.remove(sbn.getTag());
    243         onNotificationRankingUpdate(rankingMap);
    244     }
    245 
    246     public static void resetListenerData(Context context) {
    247         sendCommand(context, SERVICE_RESET, null, 0);
    248     }
    249 
    250     public static void probeListenerStatus(Context context, StatusCatcher catcher) {
    251         requestStatus(context, SERVICE_CHECK, catcher);
    252     }
    253 
    254     public static void probeFilter(Context context, IntegerResultCatcher catcher) {
    255         requestIntegerResult(context, SERVICE_DND, catcher);
    256     }
    257 
    258     public static void probeListenerPosted(Context context, StringListResultCatcher catcher) {
    259         requestStringListResult(context, SERVICE_POSTED, catcher);
    260     }
    261 
    262     public static void probeListenerOrder(Context context, StringListResultCatcher catcher) {
    263         requestStringListResult(context, SERVICE_ORDER, catcher);
    264     }
    265 
    266     public static void probeListenerPayloads(Context context, StringListResultCatcher catcher) {
    267         requestStringListResult(context, SERVICE_PAYLOADS, catcher);
    268     }
    269 
    270     public static void probeListenerRemoved(Context context, StringListResultCatcher catcher) {
    271         requestStringListResult(context, SERVICE_REMOVED, catcher);
    272     }
    273 
    274     public static void clearOne(Context context, String tag, int code) {
    275         sendCommand(context, SERVICE_CLEAR_ONE, tag, code);
    276     }
    277 
    278     public static void clearAll(Context context) {
    279         sendCommand(context, SERVICE_CLEAR_ALL, null, 0);
    280     }
    281 
    282     private static void sendCommand(Context context, String action, String tag, int code) {
    283         Intent broadcast = new Intent(action);
    284         if (tag != null) {
    285             broadcast.putExtra(EXTRA_TAG, tag);
    286             broadcast.putExtra(EXTRA_CODE, code);
    287         }
    288         context.sendBroadcast(broadcast);
    289     }
    290 
    291     public abstract static class StatusCatcher extends BroadcastReceiver {
    292         @Override
    293         public void onReceive(Context context, Intent intent) {
    294             accept(Integer.valueOf(getResultCode()));
    295         }
    296 
    297         abstract public void accept(int result);
    298     }
    299 
    300     private static void requestStatus(Context context, String action,
    301             StatusCatcher catcher) {
    302         Intent broadcast = new Intent(action);
    303         context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
    304     }
    305 
    306     public abstract static class IntegerResultCatcher extends BroadcastReceiver {
    307         @Override
    308         public void onReceive(Context context, Intent intent) {
    309             accept(getResultExtras(true).getInt(EXTRA_INT, -1));
    310         }
    311 
    312         abstract public void accept(int result);
    313     }
    314 
    315     private static void requestIntegerResult(Context context, String action,
    316             IntegerResultCatcher catcher) {
    317         Intent broadcast = new Intent(action);
    318         context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
    319     }
    320 
    321     public abstract static class StringListResultCatcher extends BroadcastReceiver {
    322         @Override
    323         public void onReceive(Context context, Intent intent) {
    324             accept(getResultExtras(true).getStringArrayList(EXTRA_PAYLOAD));
    325         }
    326 
    327         abstract public void accept(List<String> result);
    328     }
    329 
    330     private static void requestStringListResult(Context context, String action,
    331             StringListResultCatcher catcher) {
    332         Intent broadcast = new Intent(action);
    333         context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
    334     }
    335 }
    336