blob: 0ef595b76ecbc5516ae4fdbe91361743c50934bb [file] [log] [blame]
Chris Wrenf102e542013-04-30 17:52:57 -04001/*
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
Chris Wrenbcdef182014-09-22 17:56:38 -040017package com.android.cts.verifier.notifications;
Chris Wrenf102e542013-04-30 17:52:57 -040018
Chris Wrenbcdef182014-09-22 17:56:38 -040019import static com.android.cts.verifier.notifications.MockListener.JSON_FLAGS;
20import static com.android.cts.verifier.notifications.MockListener.JSON_ICON;
21import static com.android.cts.verifier.notifications.MockListener.JSON_ID;
22import static com.android.cts.verifier.notifications.MockListener.JSON_PACKAGE;
23import static com.android.cts.verifier.notifications.MockListener.JSON_TAG;
24import static com.android.cts.verifier.notifications.MockListener.JSON_WHEN;
Chris Wren981dfaa2013-05-07 11:40:28 -040025
Chris Wrenf102e542013-04-30 17:52:57 -040026import android.annotation.SuppressLint;
27import android.app.Activity;
28import android.app.Notification;
29import android.app.NotificationManager;
30import android.app.PendingIntent;
31import android.app.Service;
32import android.content.ComponentName;
33import android.content.Context;
34import android.content.Intent;
35import android.content.pm.PackageManager;
36import android.os.Bundle;
37import android.os.IBinder;
38import android.provider.Settings.Secure;
Chris Wren981dfaa2013-05-07 11:40:28 -040039import android.util.Log;
Chris Wrenf102e542013-04-30 17:52:57 -040040import android.view.LayoutInflater;
41import android.view.View;
42import android.view.ViewGroup;
Chris Wrenbcdef182014-09-22 17:56:38 -040043import android.widget.Button;
Chris Wrenf102e542013-04-30 17:52:57 -040044import android.widget.ImageView;
45import android.widget.TextView;
46
47import com.android.cts.verifier.PassFailButtons;
48import com.android.cts.verifier.R;
49import com.android.cts.verifier.nfc.TagVerifierActivity;
50
Chris Wren981dfaa2013-05-07 11:40:28 -040051import org.json.JSONException;
52import org.json.JSONObject;
53
54import java.util.HashSet;
Chris Wrenf102e542013-04-30 17:52:57 -040055import java.util.List;
Chris Wren981dfaa2013-05-07 11:40:28 -040056import java.util.Set;
Chris Wrenf102e542013-04-30 17:52:57 -040057import java.util.UUID;
58import java.util.concurrent.LinkedBlockingQueue;
59
60public class NotificationListenerVerifierActivity extends PassFailButtons.Activity
61implements Runnable {
Chris Wrenbcdef182014-09-22 17:56:38 -040062 private static final String TAG = TagVerifierActivity.class.getSimpleName();
Chris Wrenf102e542013-04-30 17:52:57 -040063 private static final String STATE = "state";
Chris Wrenf102e542013-04-30 17:52:57 -040064 private static LinkedBlockingQueue<String> sDeletedQueue = new LinkedBlockingQueue<String>();
65
Chris Wrenbcdef182014-09-22 17:56:38 -040066 protected static final String LISTENER_PATH = "com.android.cts.verifier/" +
67 "com.android.cts.verifier.notifications.MockListener";
68 protected static final int SETUP = 0;
69 protected static final int PASS = 1;
70 protected static final int FAIL = 2;
71 protected static final int WAIT_FOR_USER = 3;
72 protected static final int CLEARED = 4;
73 protected static final int READY = 5;
74 protected static final int RETRY = 6;
75
76 protected static final int NOTIFICATION_ID = 1001;
77
78 protected int mState;
79 protected int[] mStatus;
80 protected PackageManager mPackageManager;
81 protected NotificationManager mNm;
82 protected Context mContext;
83 protected Runnable mRunner;
84 protected View mHandler;
85 protected String mPackageString;
86
Chris Wrenf102e542013-04-30 17:52:57 -040087 private LayoutInflater mInflater;
88 private ViewGroup mItemList;
Chris Wrenbcdef182014-09-22 17:56:38 -040089
Chris Wrenf102e542013-04-30 17:52:57 -040090 private String mTag1;
91 private String mTag2;
92 private String mTag3;
Chris Wren981dfaa2013-05-07 11:40:28 -040093 private int mIcon1;
94 private int mIcon2;
95 private int mIcon3;
96 private int mId1;
97 private int mId2;
98 private int mId3;
99 private long mWhen1;
100 private long mWhen2;
101 private long mWhen3;
102 private int mFlag1;
103 private int mFlag2;
104 private int mFlag3;
Chris Wrenf102e542013-04-30 17:52:57 -0400105
106 public static class DismissService extends Service {
107 @Override
108 public IBinder onBind(Intent intent) {
109 return null;
110 }
111
112 @Override
113 public void onStart(Intent intent, int startId) {
114 sDeletedQueue.offer(intent.getAction());
115 }
116 }
117
118 @Override
119 protected void onCreate(Bundle savedInstanceState) {
Chris Wrenbcdef182014-09-22 17:56:38 -0400120 onCreate(savedInstanceState, R.layout.nls_main);
121 setInfoResources(R.string.nls_test, R.string.nls_info, -1);
122 }
123
124 protected void onCreate(Bundle savedInstanceState, int layoutId) {
Chris Wrenf102e542013-04-30 17:52:57 -0400125 super.onCreate(savedInstanceState);
126
127 if (savedInstanceState != null) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400128 mState = savedInstanceState.getInt(STATE, 0);
Chris Wrenf102e542013-04-30 17:52:57 -0400129 }
130 mContext = this;
131 mRunner = this;
132 mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
133 mPackageManager = getPackageManager();
134 mInflater = getLayoutInflater();
Chris Wrenbcdef182014-09-22 17:56:38 -0400135 View view = mInflater.inflate(layoutId, null);
Chris Wrenf102e542013-04-30 17:52:57 -0400136 mItemList = (ViewGroup) view.findViewById(R.id.nls_test_items);
137 mHandler = mItemList;
138 createTestItems();
139 mStatus = new int[mItemList.getChildCount()];
140 setContentView(view);
141
142 setPassFailButtonClickListeners();
Chris Wrenf102e542013-04-30 17:52:57 -0400143 getPassButton().setEnabled(false);
144 }
145
146 @Override
147 protected void onSaveInstanceState (Bundle outState) {
148 outState.putInt(STATE, mState);
149 }
150
151 @Override
152 protected void onResume() {
153 super.onResume();
Chris Wren981dfaa2013-05-07 11:40:28 -0400154 next();
Chris Wrenf102e542013-04-30 17:52:57 -0400155 }
156
157 // Interface Utilities
158
Chris Wrenbcdef182014-09-22 17:56:38 -0400159 protected void createTestItems() {
160 createNlsSettingsItem(R.string.nls_enable_service);
Chris Wrenf102e542013-04-30 17:52:57 -0400161 createAutoItem(R.string.nls_service_started);
162 createAutoItem(R.string.nls_note_received);
163 createAutoItem(R.string.nls_payload_intact);
164 createAutoItem(R.string.nls_clear_one);
165 createAutoItem(R.string.nls_clear_all);
Chris Wrenbcdef182014-09-22 17:56:38 -0400166 createNlsSettingsItem(R.string.nls_disable_service);
Chris Wrenf102e542013-04-30 17:52:57 -0400167 createAutoItem(R.string.nls_service_stopped);
168 createAutoItem(R.string.nls_note_missed);
169 }
170
Chris Wrenbcdef182014-09-22 17:56:38 -0400171 protected void setItemState(int index, boolean passed) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400172 ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
173 ImageView status = (ImageView) item.findViewById(R.id.nls_status);
174 status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
Chris Wrenbcdef182014-09-22 17:56:38 -0400175 View button = item.findViewById(R.id.nls_action_button);
Chris Wren981dfaa2013-05-07 11:40:28 -0400176 button.setClickable(false);
177 button.setEnabled(false);
178 status.invalidate();
179 }
180
Chris Wrenbcdef182014-09-22 17:56:38 -0400181 protected void markItemWaiting(int index) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400182 ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
183 ImageView status = (ImageView) item.findViewById(R.id.nls_status);
184 status.setImageResource(R.drawable.fs_warning);
185 status.invalidate();
Chris Wrenf102e542013-04-30 17:52:57 -0400186 }
187
Chris Wrenbcdef182014-09-22 17:56:38 -0400188 protected View createNlsSettingsItem(int messageId) {
189 return createUserItem(messageId, R.string.nls_start_settings);
190 }
191
192 protected View createRetryItem(int messageId) {
193 return createUserItem(messageId, R.string.attention_ready);
194 }
195
196 protected View createUserItem(int messageId, int actionId) {
Chris Wrenf102e542013-04-30 17:52:57 -0400197 View item = mInflater.inflate(R.layout.nls_item, mItemList, false);
198 TextView instructions = (TextView) item.findViewById(R.id.nls_instructions);
Chris Wrenbcdef182014-09-22 17:56:38 -0400199 instructions.setText(messageId);
200 Button button = (Button) item.findViewById(R.id.nls_action_button);
201 button.setText(actionId);
Chris Wrenf102e542013-04-30 17:52:57 -0400202 mItemList.addView(item);
Chris Wrenbcdef182014-09-22 17:56:38 -0400203 button.setTag(actionId);
Chris Wrenf102e542013-04-30 17:52:57 -0400204 return item;
205 }
206
Chris Wrenbcdef182014-09-22 17:56:38 -0400207 protected View createAutoItem(int stringId) {
Chris Wrenf102e542013-04-30 17:52:57 -0400208 View item = mInflater.inflate(R.layout.nls_item, mItemList, false);
209 TextView instructions = (TextView) item.findViewById(R.id.nls_instructions);
210 instructions.setText(stringId);
Chris Wrenbcdef182014-09-22 17:56:38 -0400211 View button = item.findViewById(R.id.nls_action_button);
Chris Wrenf102e542013-04-30 17:52:57 -0400212 button.setVisibility(View.GONE);
213 mItemList.addView(item);
214 return item;
215 }
216
217 // Test management
218
219 public void run() {
Chris Wren981dfaa2013-05-07 11:40:28 -0400220 while (mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
Chris Wrenf102e542013-04-30 17:52:57 -0400221 if (mStatus[mState] == PASS) {
222 setItemState(mState, true);
223 mState++;
224 } else if (mStatus[mState] == FAIL) {
225 setItemState(mState, false);
226 return;
227 } else {
228 break;
229 }
230 }
231
Chris Wren981dfaa2013-05-07 11:40:28 -0400232 if (mState < mStatus.length && mStatus[mState] == WAIT_FOR_USER) {
233 markItemWaiting(mState);
234 }
235
Chris Wrenbcdef182014-09-22 17:56:38 -0400236 updateStateMachine();
237 }
238
239 protected void updateStateMachine() {
Chris Wrenf102e542013-04-30 17:52:57 -0400240 switch (mState) {
Chris Wrenf102e542013-04-30 17:52:57 -0400241 case 0:
Chris Wrenbcdef182014-09-22 17:56:38 -0400242 testIsEnabled(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400243 break;
244 case 1:
Chris Wrenbcdef182014-09-22 17:56:38 -0400245 testIsStarted(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400246 break;
247 case 2:
Chris Wrenbcdef182014-09-22 17:56:38 -0400248 testNotificationRecieved(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400249 break;
250 case 3:
Chris Wrenbcdef182014-09-22 17:56:38 -0400251 testDataIntact(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400252 break;
253 case 4:
Chris Wrenbcdef182014-09-22 17:56:38 -0400254 testDismissOne(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400255 break;
256 case 5:
Chris Wrenbcdef182014-09-22 17:56:38 -0400257 testDismissAll(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400258 break;
259 case 6:
Chris Wrenbcdef182014-09-22 17:56:38 -0400260 testIsDisabled(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400261 break;
262 case 7:
Chris Wrenbcdef182014-09-22 17:56:38 -0400263 testIsStopped(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400264 break;
265 case 8:
Chris Wrenbcdef182014-09-22 17:56:38 -0400266 testNotificationNotRecieved(mState);
Chris Wrenf102e542013-04-30 17:52:57 -0400267 break;
268 case 9:
269 getPassButton().setEnabled(true);
Chris Wren981dfaa2013-05-07 11:40:28 -0400270 mNm.cancelAll();
Chris Wrenf102e542013-04-30 17:52:57 -0400271 break;
272 }
273 }
274
Chris Wrenbcdef182014-09-22 17:56:38 -0400275 public void launchSettings() {
Chris Wrenf102e542013-04-30 17:52:57 -0400276 startActivity(
277 new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
278 }
279
Chris Wrenbcdef182014-09-22 17:56:38 -0400280 public void actionPressed(View v) {
281 Object tag = v.getTag();
282 if (tag instanceof Integer) {
283 int id = ((Integer) tag).intValue();
284 if (id == R.string.nls_start_settings) {
285 launchSettings();
286 } else if (id == R.string.attention_ready) {
287 mStatus[mState] = READY;
288 next();
289 }
290 }
291 }
292
293 protected PendingIntent makeIntent(int code, String tag) {
Chris Wrenf102e542013-04-30 17:52:57 -0400294 Intent intent = new Intent(tag);
295 intent.setComponent(new ComponentName(mContext, DismissService.class));
296 PendingIntent pi = PendingIntent.getService(mContext, code, intent,
297 PendingIntent.FLAG_UPDATE_CURRENT);
298 return pi;
299 }
300
301 @SuppressLint("NewApi")
Chris Wrenbcdef182014-09-22 17:56:38 -0400302 private void sendNotifications() {
Chris Wrenf102e542013-04-30 17:52:57 -0400303 mTag1 = UUID.randomUUID().toString();
304 mTag2 = UUID.randomUUID().toString();
305 mTag3 = UUID.randomUUID().toString();
306
307 mNm.cancelAll();
308
Chris Wren981dfaa2013-05-07 11:40:28 -0400309 mWhen1 = System.currentTimeMillis() + 1;
310 mWhen2 = System.currentTimeMillis() + 2;
311 mWhen3 = System.currentTimeMillis() + 3;
312
313 mIcon1 = R.drawable.fs_good;
314 mIcon2 = R.drawable.fs_error;
315 mIcon3 = R.drawable.fs_warning;
316
317 mId1 = NOTIFICATION_ID + 1;
318 mId2 = NOTIFICATION_ID + 2;
319 mId3 = NOTIFICATION_ID + 3;
320
321 mPackageString = "com.android.cts.verifier";
322
Chris Wrenf102e542013-04-30 17:52:57 -0400323 Notification n1 = new Notification.Builder(mContext)
324 .setContentTitle("ClearTest 1")
325 .setContentText(mTag1.toString())
326 .setPriority(Notification.PRIORITY_LOW)
Chris Wren981dfaa2013-05-07 11:40:28 -0400327 .setSmallIcon(mIcon1)
328 .setWhen(mWhen1)
Chris Wrenf102e542013-04-30 17:52:57 -0400329 .setDeleteIntent(makeIntent(1, mTag1))
Chris Wren981dfaa2013-05-07 11:40:28 -0400330 .setOnlyAlertOnce(true)
Chris Wrenf102e542013-04-30 17:52:57 -0400331 .build();
Chris Wren981dfaa2013-05-07 11:40:28 -0400332 mNm.notify(mTag1, mId1, n1);
333 mFlag1 = Notification.FLAG_ONLY_ALERT_ONCE;
Chris Wrenf102e542013-04-30 17:52:57 -0400334
335 Notification n2 = new Notification.Builder(mContext)
336 .setContentTitle("ClearTest 2")
337 .setContentText(mTag2.toString())
Chris Wren981dfaa2013-05-07 11:40:28 -0400338 .setPriority(Notification.PRIORITY_HIGH)
339 .setSmallIcon(mIcon2)
340 .setWhen(mWhen2)
Chris Wrenf102e542013-04-30 17:52:57 -0400341 .setDeleteIntent(makeIntent(2, mTag2))
Chris Wren981dfaa2013-05-07 11:40:28 -0400342 .setAutoCancel(true)
Chris Wrenf102e542013-04-30 17:52:57 -0400343 .build();
Chris Wren981dfaa2013-05-07 11:40:28 -0400344 mNm.notify(mTag2, mId2, n2);
345 mFlag2 = Notification.FLAG_AUTO_CANCEL;
Chris Wrenf102e542013-04-30 17:52:57 -0400346
347 Notification n3 = new Notification.Builder(mContext)
348 .setContentTitle("ClearTest 3")
349 .setContentText(mTag3.toString())
350 .setPriority(Notification.PRIORITY_LOW)
Chris Wren981dfaa2013-05-07 11:40:28 -0400351 .setSmallIcon(mIcon3)
352 .setWhen(mWhen3)
Chris Wrenf102e542013-04-30 17:52:57 -0400353 .setDeleteIntent(makeIntent(3, mTag3))
Chris Wren981dfaa2013-05-07 11:40:28 -0400354 .setAutoCancel(true)
355 .setOnlyAlertOnce(true)
Chris Wrenf102e542013-04-30 17:52:57 -0400356 .build();
Chris Wren981dfaa2013-05-07 11:40:28 -0400357 mNm.notify(mTag3, mId3, n3);
358 mFlag3 = Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
359 }
360
361 /**
362 * Return to the state machine to progress through the tests.
363 */
Chris Wrenbcdef182014-09-22 17:56:38 -0400364 protected void next() {
365 mHandler.removeCallbacks(mRunner);
Chris Wren981dfaa2013-05-07 11:40:28 -0400366 mHandler.post(mRunner);
367 }
368
369 /**
370 * Wait for things to settle before returning to the state machine.
371 */
Chris Wrenbcdef182014-09-22 17:56:38 -0400372 protected void delay() {
373 delay(2000);
Chris Wren981dfaa2013-05-07 11:40:28 -0400374 }
375
Chris Wrenbcdef182014-09-22 17:56:38 -0400376 /**
377 * Wait for some time.
378 */
379 protected void delay(long waitTime) {
380 mHandler.removeCallbacks(mRunner);
381 mHandler.postDelayed(mRunner, waitTime);
382 }
383
384 protected boolean checkEquals(long expected, long actual, String message) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400385 if (expected == actual) {
386 return true;
387 }
388 logWithStack(String.format(message, expected, actual));
389 return false;
390 }
391
Chris Wrenbcdef182014-09-22 17:56:38 -0400392 protected boolean checkEquals(String expected, String actual, String message) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400393 if (expected.equals(actual)) {
394 return true;
395 }
396 logWithStack(String.format(message, expected, actual));
397 return false;
398 }
399
Chris Wrenbcdef182014-09-22 17:56:38 -0400400 protected boolean checkFlagSet(int expected, int actual, String message) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400401 if ((expected & actual) != 0) {
402 return true;
403 }
404 logWithStack(String.format(message, expected, actual));
405 return false;
406 };
407
Chris Wrenbcdef182014-09-22 17:56:38 -0400408 protected void logWithStack(String message) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400409 Throwable stackTrace = new Throwable();
410 stackTrace.fillInStackTrace();
411 Log.e(TAG, message, stackTrace);
Chris Wrenf102e542013-04-30 17:52:57 -0400412 }
413
414 // Tests
415
416 private void testIsEnabled(int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400417 // no setup required
Chris Wrenf102e542013-04-30 17:52:57 -0400418 Intent settings = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
419 if (settings.resolveActivity(mPackageManager) == null) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400420 logWithStack("failed testIsEnabled: no settings activity");
Chris Wrenf102e542013-04-30 17:52:57 -0400421 mStatus[i] = FAIL;
422 } else {
423 // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
424 String listeners = Secure.getString(getContentResolver(),
425 "enabled_notification_listeners");
426 if (listeners != null && listeners.contains(LISTENER_PATH)) {
427 mStatus[i] = PASS;
428 } else {
429 mStatus[i] = WAIT_FOR_USER;
430 }
431 }
Chris Wren981dfaa2013-05-07 11:40:28 -0400432 next();
Chris Wrenf102e542013-04-30 17:52:57 -0400433 }
434
435 private void testIsStarted(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400436 if (mStatus[i] == SETUP) {
437 mStatus[i] = READY;
438 // wait for the service to start
439 delay();
440 } else {
441 MockListener.probeListenerStatus(mContext,
Chris Wrenbcdef182014-09-22 17:56:38 -0400442 new MockListener.StatusCatcher() {
Chris Wren981dfaa2013-05-07 11:40:28 -0400443 @Override
444 public void accept(int result) {
445 if (result == Activity.RESULT_OK) {
446 mStatus[i] = PASS;
447 } else {
448 logWithStack("failed testIsStarted: " + result);
449 mStatus[i] = FAIL;
450 }
451 next();
Chris Wrenf102e542013-04-30 17:52:57 -0400452 }
Chris Wren981dfaa2013-05-07 11:40:28 -0400453 });
454 }
Chris Wrenf102e542013-04-30 17:52:57 -0400455 }
456
457 private void testNotificationRecieved(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400458 if (mStatus[i] == SETUP) {
459 MockListener.resetListenerData(this);
460 mStatus[i] = CLEARED;
461 // wait for intent to move through the system
462 delay();
463 } else if (mStatus[i] == CLEARED) {
Chris Wrenbcdef182014-09-22 17:56:38 -0400464 sendNotifications();
Chris Wren981dfaa2013-05-07 11:40:28 -0400465 mStatus[i] = READY;
466 // wait for notifications to move through the system
467 delay();
468 } else {
469 MockListener.probeListenerPosted(mContext,
470 new MockListener.StringListResultCatcher() {
471 @Override
472 public void accept(List<String> result) {
Chris Wren28484482014-09-19 17:34:22 -0400473 if (result != null && result.size() > 0 && result.contains(mTag1)) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400474 mStatus[i] = PASS;
475 } else {
476 logWithStack("failed testNotificationRecieved");
477 mStatus[i] = FAIL;
478 }
479 next();
480 }});
481 }
Chris Wrenf102e542013-04-30 17:52:57 -0400482 }
483
484 private void testDataIntact(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400485 // no setup required
Chris Wrenf102e542013-04-30 17:52:57 -0400486 MockListener.probeListenerPayloads(mContext,
487 new MockListener.StringListResultCatcher() {
488 @Override
489 public void accept(List<String> result) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400490 boolean pass = false;
491 Set<String> found = new HashSet<String>();
Chris Wren28484482014-09-19 17:34:22 -0400492 if (result != null && result.size() > 0) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400493 pass = true;
494 for(String payloadData : result) {
495 try {
496 JSONObject payload = new JSONObject(payloadData);
497 pass &= checkEquals(mPackageString, payload.getString(JSON_PACKAGE),
Chris Wrenbcdef182014-09-22 17:56:38 -0400498 "data integrity test fail: notification package (%s, %s)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400499 String tag = payload.getString(JSON_TAG);
500 if (mTag1.equals(tag)) {
501 found.add(mTag1);
502 pass &= checkEquals(mIcon1, payload.getInt(JSON_ICON),
Chris Wrenbcdef182014-09-22 17:56:38 -0400503 "data integrity test fail: notification icon (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400504 pass &= checkFlagSet(mFlag1, payload.getInt(JSON_FLAGS),
Chris Wrenbcdef182014-09-22 17:56:38 -0400505 "data integrity test fail: notification flags (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400506 pass &= checkEquals(mId1, payload.getInt(JSON_ID),
Chris Wrenbcdef182014-09-22 17:56:38 -0400507 "data integrity test fail: notification ID (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400508 pass &= checkEquals(mWhen1, payload.getLong(JSON_WHEN),
Chris Wrenbcdef182014-09-22 17:56:38 -0400509 "data integrity test fail: notification when (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400510 } else if (mTag2.equals(tag)) {
511 found.add(mTag2);
512 pass &= checkEquals(mIcon2, payload.getInt(JSON_ICON),
Chris Wrenbcdef182014-09-22 17:56:38 -0400513 "data integrity test fail: notification icon (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400514 pass &= checkFlagSet(mFlag2, payload.getInt(JSON_FLAGS),
Chris Wrenbcdef182014-09-22 17:56:38 -0400515 "data integrity test fail: notification flags (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400516 pass &= checkEquals(mId2, payload.getInt(JSON_ID),
Chris Wrenbcdef182014-09-22 17:56:38 -0400517 "data integrity test fail: notification ID (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400518 pass &= checkEquals(mWhen2, payload.getLong(JSON_WHEN),
Chris Wrenbcdef182014-09-22 17:56:38 -0400519 "data integrity test fail: notification when (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400520 } else if (mTag3.equals(tag)) {
521 found.add(mTag3);
522 pass &= checkEquals(mIcon3, payload.getInt(JSON_ICON),
Chris Wrenbcdef182014-09-22 17:56:38 -0400523 "data integrity test fail: notification icon (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400524 pass &= checkFlagSet(mFlag3, payload.getInt(JSON_FLAGS),
Chris Wrenbcdef182014-09-22 17:56:38 -0400525 "data integrity test fail: notification flags (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400526 pass &= checkEquals(mId3, payload.getInt(JSON_ID),
Chris Wrenbcdef182014-09-22 17:56:38 -0400527 "data integrity test fail: notification ID (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400528 pass &= checkEquals(mWhen3, payload.getLong(JSON_WHEN),
Chris Wrenbcdef182014-09-22 17:56:38 -0400529 "data integrity test fail: notification when (%d, %d)");
Chris Wren981dfaa2013-05-07 11:40:28 -0400530 } else {
531 pass = false;
532 logWithStack("failed on unexpected notification tag: " + tag);
533 }
534 } catch (JSONException e) {
535 pass = false;
536 Log.e(TAG, "failed to unpack data from mocklistener", e);
Chris Wrenf102e542013-04-30 17:52:57 -0400537 }
538 }
539 }
Chris Wren981dfaa2013-05-07 11:40:28 -0400540 pass &= found.size() == 3;
541 mStatus[i] = pass ? PASS : FAIL;
542 next();
Chris Wrenf102e542013-04-30 17:52:57 -0400543 }});
544 }
545
546 private void testDismissOne(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400547 if (mStatus[i] == SETUP) {
548 MockListener.resetListenerData(this);
549 mStatus[i] = CLEARED;
550 // wait for intent to move through the system
551 delay();
552 } else if (mStatus[i] == CLEARED) {
553 MockListener.clearOne(mContext, mTag1, NOTIFICATION_ID + 1);
554 mStatus[i] = READY;
555 delay();
556 } else {
557 MockListener.probeListenerRemoved(mContext,
558 new MockListener.StringListResultCatcher() {
559 @Override
560 public void accept(List<String> result) {
Chris Wren28484482014-09-19 17:34:22 -0400561 if (result != null && result.size() > 0 && result.contains(mTag1)) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400562 mStatus[i] = PASS;
Chris Wren4c5983a2013-05-10 15:02:40 -0400563 next();
Chris Wren981dfaa2013-05-07 11:40:28 -0400564 } else {
565 if (mStatus[i] == RETRY) {
566 logWithStack("failed testDismissOne");
567 mStatus[i] = FAIL;
Chris Wren4c5983a2013-05-10 15:02:40 -0400568 next();
Chris Wren981dfaa2013-05-07 11:40:28 -0400569 } else {
570 logWithStack("failed testDismissOne, once: retrying");
571 mStatus[i] = RETRY;
Chris Wren4c5983a2013-05-10 15:02:40 -0400572 delay();
Chris Wren981dfaa2013-05-07 11:40:28 -0400573 }
574 }
Chris Wren981dfaa2013-05-07 11:40:28 -0400575 }});
576 }
Chris Wrenf102e542013-04-30 17:52:57 -0400577 }
578
579 private void testDismissAll(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400580 if (mStatus[i] == SETUP) {
581 MockListener.resetListenerData(this);
582 mStatus[i] = CLEARED;
583 // wait for intent to move through the system
584 delay();
585 } else if (mStatus[i] == CLEARED) {
586 MockListener.clearAll(mContext);
587 mStatus[i] = READY;
588 delay();
589 } else {
590 MockListener.probeListenerRemoved(mContext,
591 new MockListener.StringListResultCatcher() {
592 @Override
593 public void accept(List<String> result) {
Chris Wren28484482014-09-19 17:34:22 -0400594 if (result != null && result.size() == 2
595 && result.contains(mTag2) && result.contains(mTag3)) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400596 mStatus[i] = PASS;
Chris Wren4c5983a2013-05-10 15:02:40 -0400597 next();
Chris Wren981dfaa2013-05-07 11:40:28 -0400598 } else {
599 if (mStatus[i] == RETRY) {
600 logWithStack("failed testDismissAll");
601 mStatus[i] = FAIL;
Chris Wren4c5983a2013-05-10 15:02:40 -0400602 next();
Chris Wren981dfaa2013-05-07 11:40:28 -0400603 } else {
604 logWithStack("failed testDismissAll, once: retrying");
605 mStatus[i] = RETRY;
Chris Wren4c5983a2013-05-10 15:02:40 -0400606 delay();
Chris Wren981dfaa2013-05-07 11:40:28 -0400607 }
608 }
Chris Wrenf102e542013-04-30 17:52:57 -0400609 }
Chris Wren981dfaa2013-05-07 11:40:28 -0400610 });
611 }
Chris Wrenf102e542013-04-30 17:52:57 -0400612 }
613
614 private void testIsDisabled(int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400615 // no setup required
Chris Wrenf102e542013-04-30 17:52:57 -0400616 // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
617 String listeners = Secure.getString(getContentResolver(),
618 "enabled_notification_listeners");
619 if (listeners == null || !listeners.contains(LISTENER_PATH)) {
620 mStatus[i] = PASS;
Chris Wren981dfaa2013-05-07 11:40:28 -0400621 next();
Chris Wrenf102e542013-04-30 17:52:57 -0400622 } else {
623 mStatus[i] = WAIT_FOR_USER;
Chris Wren981dfaa2013-05-07 11:40:28 -0400624 delay();
Chris Wrenf102e542013-04-30 17:52:57 -0400625 }
Chris Wrenf102e542013-04-30 17:52:57 -0400626 }
627
628 private void testIsStopped(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400629 if (mStatus[i] == SETUP) {
630 mStatus[i] = READY;
631 // wait for the service to start
632 delay();
633 } else {
634 MockListener.probeListenerStatus(mContext,
Chris Wrenbcdef182014-09-22 17:56:38 -0400635 new MockListener.StatusCatcher() {
Chris Wren981dfaa2013-05-07 11:40:28 -0400636 @Override
637 public void accept(int result) {
638 if (result == Activity.RESULT_OK) {
639 logWithStack("failed testIsStopped");
640 mStatus[i] = FAIL;
641 } else {
642 mStatus[i] = PASS;
643 }
644 next();
Chris Wrenf102e542013-04-30 17:52:57 -0400645 }
Chris Wren981dfaa2013-05-07 11:40:28 -0400646 });
647 }
Chris Wrenf102e542013-04-30 17:52:57 -0400648 }
649
650 private void testNotificationNotRecieved(final int i) {
Chris Wren981dfaa2013-05-07 11:40:28 -0400651 if (mStatus[i] == SETUP) {
652 MockListener.resetListenerData(this);
653 mStatus[i] = CLEARED;
654 // wait for intent to move through the system
655 delay();
656 } else if (mStatus[i] == CLEARED) {
657 // setup for testNotificationRecieved
Chris Wrenbcdef182014-09-22 17:56:38 -0400658 sendNotifications();
Chris Wren981dfaa2013-05-07 11:40:28 -0400659 mStatus[i] = READY;
660 delay();
661 } else {
662 MockListener.probeListenerPosted(mContext,
663 new MockListener.StringListResultCatcher() {
664 @Override
665 public void accept(List<String> result) {
666 if (result == null || result.size() == 0) {
667 mStatus[i] = PASS;
668 } else {
669 logWithStack("failed testNotificationNotRecieved");
670 mStatus[i] = FAIL;
671 }
672 next();
673 }});
674 }
Chris Wrenf102e542013-04-30 17:52:57 -0400675 }
676}