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.Notification;
19 import android.content.ComponentName;
20 import android.service.notification.NotificationListenerService;
21 import android.service.notification.NotificationStats;
22 import android.service.notification.StatusBarNotification;
23 import android.util.ArrayMap;
24 import android.util.Log;
25 
26 import org.json.JSONException;
27 import org.json.JSONObject;
28 
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashSet;
32 import java.util.Set;
33 
34 public class MockListener extends NotificationListenerService {
35     static final String TAG = "MockListener";
36 
37     public static final ComponentName COMPONENT_NAME =
38             new ComponentName("com.android.cts.verifier", MockListener.class.getName());
39 
40 
41     public static final String JSON_FLAGS = "flag";
42     public static final String JSON_ICON = "icon";
43     public static final String JSON_ID = "id";
44     public static final String JSON_PACKAGE = "pkg";
45     public static final String JSON_WHEN = "when";
46     public static final String JSON_TAG = "tag";
47     public static final String JSON_RANK = "rank";
48     public static final String JSON_AMBIENT = "ambient";
49     public static final String JSON_MATCHES_ZEN_FILTER = "matches_zen_filter";
50     public static final String JSON_REASON = "reason";
51     public static final String JSON_STATS = "stats";
52     public static final String JSON_LAST_AUDIBLY_ALERTED = "last_audibly_alerted";
53 
54     ArrayList<StatusBarNotification> mPosted = new ArrayList<>();
55     ArrayMap<String, JSONObject> mNotifications = new ArrayMap<>();
56     ArrayMap<String, String> mNotificationKeys = new ArrayMap<>();
57     ArrayList<String> mRemoved = new ArrayList<String>();
58     ArrayMap<String, JSONObject> mRemovedReason = new ArrayMap<>();
59     ArrayList<String> mSnoozed = new ArrayList<>();
60     ArrayList<String> mOrder = new ArrayList<>();
61     Set<String> mTestPackages = new HashSet<>();
62     int mDND = -1;
63     ArrayList<Notification> mPostedNotifications = new ArrayList<Notification>();
64     private static MockListener sNotificationListenerInstance = null;
65     boolean isConnected;
66 
67     @Override
onCreate()68     public void onCreate() {
69         super.onCreate();
70         Log.d(TAG, "created");
71 
72         mTestPackages.add("com.android.cts.verifier");
73         mTestPackages.add("com.android.cts.robot");
74     }
75 
getPosted()76     protected Collection<JSONObject> getPosted() {
77         return mNotifications.values();
78     }
79 
getPosted(String tag)80     protected StatusBarNotification getPosted(String tag) {
81         for (StatusBarNotification sbn : mPosted) {
82             if (sbn.getTag().equals(tag)) {
83                 return sbn;
84             }
85         }
86         return null;
87     }
88 
getKeyForTag(String tag)89     protected String getKeyForTag(String tag) {
90         return mNotificationKeys.get(tag);
91     }
92 
93     @Override
onDestroy()94     public void onDestroy() {
95         super.onDestroy();
96         Log.d(TAG, "destroyed");
97     }
98 
99     @Override
onListenerConnected()100     public void onListenerConnected() {
101         super.onListenerConnected();
102         mDND = getCurrentInterruptionFilter();
103         Log.d(TAG, "initial value of CurrentInterruptionFilter is " + mDND);
104         sNotificationListenerInstance = this;
105         isConnected = true;
106     }
107 
108     @Override
onListenerDisconnected()109     public void onListenerDisconnected() {
110         isConnected = false;
111     }
112 
113     @Override
onInterruptionFilterChanged(int interruptionFilter)114     public void onInterruptionFilterChanged(int interruptionFilter) {
115         super.onInterruptionFilterChanged(interruptionFilter);
116         mDND = interruptionFilter;
117         Log.d(TAG, "value of CurrentInterruptionFilter changed to " + mDND);
118     }
119 
getInstance()120     public static MockListener getInstance() {
121         return sNotificationListenerInstance;
122     }
123 
resetData()124     public void resetData() {
125         mPosted.clear();
126         mNotifications.clear();
127         mRemoved.clear();
128         mOrder.clear();
129         mRemovedReason.clear();
130         mSnoozed.clear();
131         mPostedNotifications.clear();
132     }
133 
134     @Override
onNotificationRankingUpdate(RankingMap rankingMap)135     public void onNotificationRankingUpdate(RankingMap rankingMap) {
136         String[] orderedKeys = rankingMap.getOrderedKeys();
137         mOrder.clear();
138         Ranking rank = new Ranking();
139         for( int i = 0; i < orderedKeys.length; i++) {
140             String key = orderedKeys[i];
141             mOrder.add(key);
142             rankingMap.getRanking(key, rank);
143             JSONObject note = mNotifications.get(key);
144             if (note != null) {
145                 try {
146                     note.put(JSON_RANK, rank.getRank());
147                     note.put(JSON_AMBIENT, rank.isAmbient());
148                     note.put(JSON_MATCHES_ZEN_FILTER, rank.matchesInterruptionFilter());
149                     note.put(JSON_LAST_AUDIBLY_ALERTED, rank.getLastAudiblyAlertedMillis());
150                 } catch (JSONException e) {
151                     Log.e(TAG, "failed to pack up notification payload", e);
152                 }
153             }
154         }
155     }
156 
157     @Override
onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap)158     public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
159         if (!mTestPackages.contains(sbn.getPackageName())) { return; }
160         Log.d(TAG, "posted: " + sbn.getTag());
161         mPosted.add(sbn);
162         mPostedNotifications.add(sbn.getNotification());
163         JSONObject notification = new JSONObject();
164         try {
165             notification.put(JSON_TAG, sbn.getTag());
166             notification.put(JSON_ID, sbn.getId());
167             notification.put(JSON_PACKAGE, sbn.getPackageName());
168             notification.put(JSON_WHEN, sbn.getNotification().when);
169             notification.put(JSON_ICON, sbn.getNotification().icon);
170             notification.put(JSON_FLAGS, sbn.getNotification().flags);
171             mNotifications.put(sbn.getKey(), notification);
172             mNotificationKeys.put(sbn.getTag(), sbn.getKey());
173         } catch (JSONException e) {
174             Log.e(TAG, "failed to pack up notification payload", e);
175         }
176         onNotificationRankingUpdate(rankingMap);
177     }
178 
179     @Override
onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap)180     public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
181         Log.d(TAG, "removed: " + sbn.getTag());
182         mRemoved.add(sbn.getTag());
183         mNotifications.remove(sbn.getKey());
184         mNotificationKeys.remove(sbn.getTag());
185         onNotificationRankingUpdate(rankingMap);
186     }
187 
188     @Override
onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, NotificationStats stats, int reason)189     public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
190             NotificationStats stats, int reason) {
191         Log.d(TAG, "removed: " + sbn.getTag() + " for reason " + reason);
192         mRemoved.add(sbn.getTag());
193         JSONObject removed = new JSONObject();
194         try {
195             removed.put(JSON_TAG, sbn.getTag());
196             removed.put(JSON_REASON, reason);
197             removed.put(JSON_STATS, stats != null);
198         } catch (JSONException e) {
199             Log.e(TAG, "failed to pack up notification payload", e);
200         }
201         mNotifications.remove(sbn.getKey());
202         mNotificationKeys.remove(sbn.getTag());
203         mRemovedReason.put(sbn.getTag(), removed);
204         onNotificationRankingUpdate(rankingMap);
205     }
206 }
207