1 /* 2 * Copyright (C) 2016 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.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.content.pm.PackageManager; 24 import android.os.Bundle; 25 import android.util.Log; 26 import android.view.View; 27 import android.view.ViewGroup; 28 29 import com.android.cts.verifier.R; 30 31 import java.security.SecureRandom; 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.concurrent.atomic.AtomicReference; 35 36 /** 37 * Test to make sure, when an inline reply happens, the shortcut manager rate-limiting must 38 * be reset. 39 * 40 * We use the "BOT" apk here, because rate-limiting will be reset when an app shows an activity 41 * too -- so as long as this (or any) test activity is shown, CTS verifier won't be rate-limited. 42 */ 43 public class ShortcutThrottlingResetActivity extends InteractiveVerifierActivity { 44 private static final String TAG = "ShortcutThrottlingReset"; 45 46 private static final String NOTIFICATION_BOT_PACKAGE = "com.android.cts.robot"; 47 48 private static final String ACTION_RESET_SETUP_NOTIFICATION = 49 "com.android.cts.robot.ACTION_RESET_SETUP_NOTIFICATION"; 50 51 private static final String EXTRA_NOTIFICATION_TITLE = "EXTRA_NOTIFICATION_TITLE"; 52 private static final String EXTRA_RESET_REPLY_PACKAGE = "EXTRA_RESET_REPLY_PACKAGE"; 53 private static final String EXTRA_RESET_REPLY_ACTION = "EXTRA_RESET_REPLY_ACTION"; 54 private static final String EXTRA_RESET_REPLY_ERROR = "EXTRA_RESET_REPLY_ERROR"; 55 56 private static final String SUCCESS = "**SUCCESS**"; 57 58 private String mReplyAction; 59 60 private final AtomicReference<Intent> mReplyIntent = new AtomicReference<>(null); 61 62 @Override getTitleResource()63 protected int getTitleResource() { 64 return R.string.shortcut_reset_test; 65 } 66 67 @Override getInstructionsResource()68 protected int getInstructionsResource() { 69 return R.string.shortcut_reset_info; 70 } 71 72 @Override onCreate(Bundle savedState)73 protected void onCreate(Bundle savedState) { 74 super.onCreate(savedState); 75 76 // Generate an unique reply action and register the reply receiver. 77 mReplyAction = "reply_" + new SecureRandom().nextLong(); 78 final IntentFilter replyFilter = new IntentFilter(mReplyAction); 79 registerReceiver(mReplyReceiver, replyFilter); 80 } 81 82 @Override onDestroy()83 protected void onDestroy() { 84 unregisterReceiver(mReplyReceiver); 85 super.onDestroy(); 86 } 87 88 @Override createTestItems()89 protected List<InteractiveTestCase> createTestItems() { 90 List<InteractiveTestCase> tests = new ArrayList<>(); 91 tests.add(new CheckForBot()); 92 tests.add(new SetupNotification()); 93 tests.add(new WaitForTestReply()); 94 tests.add(new CheckResult()); 95 return tests; 96 } 97 98 99 private final BroadcastReceiver mReplyReceiver = new BroadcastReceiver() { 100 @Override 101 public void onReceive(Context context, Intent intent) { 102 Log.i(TAG, "Received reply from robot helper: " + intent); 103 mReplyIntent.set(intent); 104 } 105 }; 106 107 108 /** Make sure the helper package is installed. */ 109 protected class CheckForBot extends InteractiveTestCase { 110 @Override inflate(ViewGroup parent)111 protected View inflate(ViewGroup parent) { 112 return createAutoItem(parent, R.string.shortcut_reset_bot); 113 } 114 115 @Override test()116 protected void test() { 117 PackageManager pm = mContext.getPackageManager(); 118 try { 119 pm.getPackageInfo(NOTIFICATION_BOT_PACKAGE, 0); 120 status = PASS; 121 } catch (PackageManager.NameNotFoundException e) { 122 status = FAIL; 123 logFail("You must install the CTS Robot helper, aka " + NOTIFICATION_BOT_PACKAGE); 124 } 125 next(); 126 } 127 } 128 129 /** 130 * Request the bot apk to show the notification. 131 */ 132 protected class SetupNotification extends InteractiveTestCase { 133 @Override inflate(ViewGroup parent)134 protected View inflate(ViewGroup parent) { 135 return createAutoItem(parent, R.string.shortcut_reset_start); 136 } 137 138 @Override test()139 protected void test() { 140 final Intent intent = new Intent(ACTION_RESET_SETUP_NOTIFICATION); 141 intent.setPackage(NOTIFICATION_BOT_PACKAGE); 142 143 intent.putExtra(EXTRA_NOTIFICATION_TITLE, getResources().getString(getTitleResource())); 144 145 intent.putExtra(EXTRA_RESET_REPLY_PACKAGE, getPackageName()); 146 intent.putExtra(EXTRA_RESET_REPLY_ACTION, mReplyAction); 147 148 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 149 sendBroadcast(intent); 150 status = PASS; 151 next(); 152 } 153 } 154 155 /** 156 * Let the human tester do an inline reply, and wait for the reply broadcast from the bot apk. 157 */ 158 protected class WaitForTestReply extends InteractiveTestCase { 159 @Override inflate(ViewGroup parent)160 protected View inflate(ViewGroup parent) { 161 return createAutoItem(parent, R.string.shortcut_reset_prompt_inline_reply); 162 } 163 164 @Override test()165 protected void test() { 166 final Intent replyIntent = mReplyIntent.get(); 167 if (replyIntent == null) { 168 // Reply not received yet. 169 status = RETEST; 170 delay(); 171 return; 172 } 173 status = PASS; 174 next(); 175 } 176 } 177 178 /** 179 * Check the reply from the bot apk. 180 */ 181 protected class CheckResult extends InteractiveTestCase { 182 @Override inflate(ViewGroup parent)183 protected View inflate(ViewGroup parent) { 184 return createAutoItem(parent, R.string.shortcut_reset_check_result); 185 } 186 187 @Override test()188 protected void test() { 189 final Intent replyIntent = mReplyIntent.get(); 190 if (replyIntent == null) { 191 logFail("Internal error, replyIntent shouldn't be null here."); 192 status = FAIL; 193 return; 194 } 195 final String error = replyIntent.getStringExtra(EXTRA_RESET_REPLY_ERROR); 196 if (SUCCESS.equals(error)) { 197 status = PASS; 198 next(); 199 return; 200 } 201 logFail("Test failed. Error message=" + error); 202 status = FAIL; 203 next(); 204 } 205 } 206 } 207