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 private static final String ACTION_OPEN_NOTIFICATION_BOT = 51 "com.android.cts.robot.OPEN_NOTIFICATION_BOT"; 52 53 private static final String EXTRA_NOTIFICATION_TITLE = "EXTRA_NOTIFICATION_TITLE"; 54 private static final String EXTRA_RESET_REPLY_PACKAGE = "EXTRA_RESET_REPLY_PACKAGE"; 55 private static final String EXTRA_RESET_REPLY_ACTION = "EXTRA_RESET_REPLY_ACTION"; 56 private static final String EXTRA_RESET_REPLY_ERROR = "EXTRA_RESET_REPLY_ERROR"; 57 58 private static final String SUCCESS = "**SUCCESS**"; 59 60 private static final int REQUEST_CODE_OPEN_NOTIFICATION_BOT = 1; 61 62 private String mReplyAction; 63 64 private final AtomicReference<Intent> mReplyIntent = new AtomicReference<>(null); 65 66 @Override getTitleResource()67 protected int getTitleResource() { 68 return R.string.shortcut_reset_test; 69 } 70 71 @Override getInstructionsResource()72 protected int getInstructionsResource() { 73 return R.string.shortcut_reset_info; 74 } 75 76 @Override onCreate(Bundle savedState)77 protected void onCreate(Bundle savedState) { 78 super.onCreate(savedState); 79 80 // Generate an unique reply action and register the reply receiver. 81 mReplyAction = "reply_" + new SecureRandom().nextLong(); 82 final IntentFilter replyFilter = new IntentFilter(mReplyAction); 83 registerReceiver(mReplyReceiver, replyFilter, Context.RECEIVER_EXPORTED); 84 } 85 86 @Override onDestroy()87 protected void onDestroy() { 88 unregisterReceiver(mReplyReceiver); 89 super.onDestroy(); 90 } 91 92 @Override createTestItems()93 protected List<InteractiveTestCase> createTestItems() { 94 List<InteractiveTestCase> tests = new ArrayList<>(); 95 tests.add(new CheckForBot()); 96 tests.add(new SetupNotification()); 97 tests.add(new WaitForTestReply()); 98 tests.add(new CheckResult()); 99 return tests; 100 } 101 102 103 private final BroadcastReceiver mReplyReceiver = new BroadcastReceiver() { 104 @Override 105 public void onReceive(Context context, Intent intent) { 106 Log.i(TAG, "Received reply from robot helper: " + intent); 107 mReplyIntent.set(intent); 108 } 109 }; 110 111 112 /** Make sure the helper package is installed. */ 113 protected class CheckForBot extends InteractiveTestCase { 114 @Override inflate(ViewGroup parent)115 protected View inflate(ViewGroup parent) { 116 return createAutoItem(parent, R.string.shortcut_reset_bot); 117 } 118 119 @Override test()120 protected void test() { 121 PackageManager pm = mContext.getPackageManager(); 122 try { 123 pm.getPackageInfo(NOTIFICATION_BOT_PACKAGE, 0); 124 status = PASS; 125 startActivityForResult(new Intent(ACTION_OPEN_NOTIFICATION_BOT), 126 REQUEST_CODE_OPEN_NOTIFICATION_BOT); 127 } catch (PackageManager.NameNotFoundException e) { 128 status = FAIL; 129 logFail("You must install the CTS Robot helper, aka " + NOTIFICATION_BOT_PACKAGE); 130 next(); 131 } 132 } 133 } 134 135 @Override onActivityResult(int requestCode, int resultCode, Intent data)136 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 137 super.onActivityResult(requestCode, resultCode, data); 138 if (requestCode == REQUEST_CODE_OPEN_NOTIFICATION_BOT) { 139 next(); 140 } 141 } 142 143 /** 144 * Request the bot apk to show the notification. 145 */ 146 protected class SetupNotification extends InteractiveTestCase { 147 @Override inflate(ViewGroup parent)148 protected View inflate(ViewGroup parent) { 149 return createAutoItem(parent, R.string.shortcut_reset_start); 150 } 151 152 @Override test()153 protected void test() { 154 final Intent intent = new Intent(ACTION_RESET_SETUP_NOTIFICATION); 155 intent.setPackage(NOTIFICATION_BOT_PACKAGE); 156 157 intent.putExtra(EXTRA_NOTIFICATION_TITLE, getResources().getString(getTitleResource())); 158 159 intent.putExtra(EXTRA_RESET_REPLY_PACKAGE, getPackageName()); 160 intent.putExtra(EXTRA_RESET_REPLY_ACTION, mReplyAction); 161 162 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 163 sendBroadcast(intent); 164 status = PASS; 165 next(); 166 } 167 } 168 169 /** 170 * Let the human tester do an inline reply, and wait for the reply broadcast from the bot apk. 171 */ 172 protected class WaitForTestReply extends InteractiveTestCase { 173 @Override inflate(ViewGroup parent)174 protected View inflate(ViewGroup parent) { 175 return createAutoItem(parent, R.string.shortcut_reset_prompt_inline_reply); 176 } 177 178 @Override test()179 protected void test() { 180 final Intent replyIntent = mReplyIntent.get(); 181 if (replyIntent == null) { 182 // Reply not received yet. 183 status = RETEST; 184 delay(); 185 return; 186 } 187 status = PASS; 188 next(); 189 } 190 } 191 192 /** 193 * Check the reply from the bot apk. 194 */ 195 protected class CheckResult extends InteractiveTestCase { 196 @Override inflate(ViewGroup parent)197 protected View inflate(ViewGroup parent) { 198 return createAutoItem(parent, R.string.shortcut_reset_check_result); 199 } 200 201 @Override test()202 protected void test() { 203 final Intent replyIntent = mReplyIntent.get(); 204 if (replyIntent == null) { 205 logFail("Internal error, replyIntent shouldn't be null here."); 206 status = FAIL; 207 return; 208 } 209 final String error = replyIntent.getStringExtra(EXTRA_RESET_REPLY_ERROR); 210 if (SUCCESS.equals(error)) { 211 status = PASS; 212 next(); 213 return; 214 } 215 logFail("Test failed. Error message=" + error); 216 status = FAIL; 217 next(); 218 } 219 } 220 } 221