1 /* 2 * Copyright (C) 2009 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 android.app.cts; 18 19 import android.app.Activity; 20 import android.app.Instrumentation; 21 import android.app.Instrumentation.ActivityMonitor; 22 import android.app.Instrumentation.ActivityResult; 23 import android.app.stubs.ActivityMonitorTestActivity; 24 import android.app.stubs.InstrumentationTestActivity; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.test.InstrumentationTestCase; 29 import android.util.Log; 30 31 import java.util.concurrent.CountDownLatch; 32 import java.util.concurrent.TimeUnit; 33 34 public class Instrumentation_ActivityMonitorTest extends InstrumentationTestCase { 35 private static final String TAG = "ActivityMonitorTest"; 36 37 private static final long TIMEOUT_FOR_ACTIVITY_LAUNCH_MS = 5000; // 5 sec 38 private static final long CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS = 100; // 0.1 sec 39 40 /** 41 * check points: 42 * 1 Constructor with blocking true and false 43 * 2 waitForActivity with timeout and no timeout 44 * 3 get info about ActivityMonitor 45 */ 46 public void testActivityMonitor() throws Exception { 47 ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent()); 48 Instrumentation instrumentation = getInstrumentation(); 49 ActivityMonitor am = instrumentation.addMonitor( 50 InstrumentationTestActivity.class.getName(), result, false); 51 Context context = instrumentation.getTargetContext(); 52 Intent intent = new Intent(context, InstrumentationTestActivity.class); 53 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 54 context.startActivity(intent); 55 Activity lastActivity = am.getLastActivity(); 56 long timeout = System.currentTimeMillis() + TIMEOUT_FOR_ACTIVITY_LAUNCH_MS; 57 while (lastActivity == null && System.currentTimeMillis() < timeout) { 58 Thread.sleep(CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS); 59 lastActivity = am.getLastActivity(); 60 } 61 Activity activity = am.waitForActivity(); 62 assertSame(activity, lastActivity); 63 assertEquals(1, am.getHits()); 64 assertTrue(activity instanceof InstrumentationTestActivity); 65 activity.finish(); 66 instrumentation.waitForIdleSync(); 67 context.startActivity(intent); 68 timeout = System.currentTimeMillis() + TIMEOUT_FOR_ACTIVITY_LAUNCH_MS; 69 activity = null; 70 while (activity == null && System.currentTimeMillis() < timeout) { 71 Thread.sleep(CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS); 72 activity = am.waitForActivityWithTimeout(CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS); 73 } 74 assertNotNull(activity); 75 activity.finish(); 76 instrumentation.removeMonitor(am); 77 78 am = new ActivityMonitor(InstrumentationTestActivity.class.getName(), result, true); 79 assertSame(result, am.getResult()); 80 assertTrue(am.isBlocking()); 81 IntentFilter which = new IntentFilter(); 82 am = new ActivityMonitor(which, result, false); 83 assertSame(which, am.getFilter()); 84 assertFalse(am.isBlocking()); 85 } 86 87 /** 88 * Verifies that 89 * - when ActivityMonitor.onStartActivity returs non-null, then there is monitor hit. 90 * - when ActivityMonitor.onStartActivity returns null, then the activity start is not blocked. 91 */ 92 public void testActivityMonitor_onStartActivity() throws Exception { 93 final ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent()); 94 final Instrumentation instrumentation = getInstrumentation(); 95 final Context context = instrumentation.getTargetContext(); 96 final Intent intent = new Intent(context, InstrumentationTestActivity.class); 97 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 98 99 // Verify when ActivityMonitor.onStartActivity returns non-null, then there is a monitor hit. 100 final CustomActivityMonitor cam1 = new CustomActivityMonitor(result); 101 instrumentation.addMonitor(cam1); 102 context.startActivity(intent); 103 final Activity activity1 = cam1.waitForActivityWithTimeout( 104 CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS * 2); 105 try { 106 assertNull("Activity should not have been started", activity1); 107 assertEquals("There should be 1 monitor hit", 1, cam1.getHits()); 108 } finally { 109 instrumentation.removeMonitor(cam1); 110 } 111 112 // Verify when ActivityMonitor.onStartActivity returns null, then activity start is not 113 // blocked and there is no monitor hit. 114 final CustomActivityMonitor cam2 = new CustomActivityMonitor(null); 115 instrumentation.addMonitor(cam2); 116 Activity activity2 = instrumentation.startActivitySync(intent); 117 try { 118 assertNotNull("Activity should not be null", activity2); 119 assertTrue("Activity returned should be of instance InstrumentationTestActivity", 120 activity2 instanceof InstrumentationTestActivity); 121 assertTrue("InstrumentationTestActivity should have been started", 122 ((InstrumentationTestActivity) activity2).isOnCreateCalled()); 123 assertEquals("There should be no monitor hits", 0, cam2.getHits()); 124 } finally { 125 activity2.finish(); 126 instrumentation.removeMonitor(cam2); 127 } 128 } 129 130 /** 131 * Verifies that when ActivityMonitor.onStartActivity returns non-null, activity start is blocked. 132 */ 133 public void testActivityMonitor_onStartActivityBlocks() throws Exception { 134 final Instrumentation instrumentation = getInstrumentation(); 135 final Context context = instrumentation.getTargetContext(); 136 137 // Start ActivityMonitorTestActivity 138 final Intent intent = new Intent(context, ActivityMonitorTestActivity.class) 139 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 140 ActivityMonitorTestActivity amTestActivity = 141 (ActivityMonitorTestActivity) instrumentation.startActivitySync(intent); 142 143 // Initialize and set activity monitor. 144 final int expectedResultCode = 1111; 145 final String expectedAction = "matched_using_onStartActivity"; 146 final CustomActivityMonitor cam = new CustomActivityMonitor( 147 new ActivityResult(expectedResultCode, new Intent(expectedAction))); 148 instrumentation.addMonitor(cam); 149 150 // Start InstrumentationTestActivity from ActivityMonitorTestActivity and verify 151 // it is intercepted using onStartActivity as expected. 152 try { 153 final CountDownLatch latch = new CountDownLatch(1); 154 amTestActivity.setOnActivityResultListener( 155 new ActivityMonitorTestActivity.OnActivityResultListener() { 156 @Override 157 public void onActivityResult(int requestCode, int resultCode, Intent data) { 158 assertEquals("Result code is not same as expected", 159 expectedResultCode, resultCode); 160 assertNotNull("Data from activity result is null", data); 161 assertEquals("Data action is not same as expected", 162 expectedAction, data.getAction()); 163 latch.countDown(); 164 } 165 }); 166 amTestActivity.startInstrumentationTestActivity(false); 167 if (!latch.await(TIMEOUT_FOR_ACTIVITY_LAUNCH_MS, TimeUnit.MILLISECONDS)) { 168 fail("Timed out waiting for the activity result from " 169 + ActivityMonitorTestActivity.class.getName()); 170 } 171 assertEquals("There should be 1 monitor hit", 1, cam.getHits()); 172 } finally { 173 amTestActivity.finish(); 174 instrumentation.removeMonitor(cam); 175 } 176 } 177 178 /** 179 * Verifies that when the activity monitor is created using by passing IntentFilter, 180 * then onStartActivity return value is ignored. 181 */ 182 public void testActivityMonitor_onStartActivityAndIntentFilter() throws Exception { 183 final Instrumentation instrumentation = getInstrumentation(); 184 final Context context = instrumentation.getTargetContext(); 185 186 // Start ActivityMonitorTestActivity 187 final Intent intent = new Intent(context, ActivityMonitorTestActivity.class) 188 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 189 ActivityMonitorTestActivity amTestActivity = 190 (ActivityMonitorTestActivity) instrumentation.startActivitySync(intent); 191 192 // Initialize and set activity monitor. 193 final int expectedResultCode = 1122; 194 final String expectedAction = "matched_using_intent_filter"; 195 final CustomActivityMonitor cam = new CustomActivityMonitor( 196 new IntentFilter(InstrumentationTestActivity.START_INTENT), 197 new ActivityResult(expectedResultCode, new Intent(expectedAction)), 198 true); 199 cam.setResultToReturn(new ActivityResult(1111, new Intent("matched_using_onStartActivity"))); 200 instrumentation.addMonitor(cam); 201 202 // Start explicit InstrumentationTestActivity from ActivityMonitorTestActivity and verify 203 // it is intercepted using the intentFilter as expected. 204 try { 205 final CountDownLatch latch = new CountDownLatch(1); 206 amTestActivity.setOnActivityResultListener( 207 new ActivityMonitorTestActivity.OnActivityResultListener() { 208 @Override 209 public void onActivityResult(int requestCode, int resultCode, Intent data) { 210 assertEquals("Result code is not same as expected", 211 expectedResultCode, resultCode); 212 assertNotNull("Data from activity result is null", data); 213 assertEquals("Data action is not same as expected", 214 expectedAction, data.getAction()); 215 latch.countDown(); 216 } 217 }); 218 amTestActivity.startInstrumentationTestActivity(false); 219 if (!latch.await(TIMEOUT_FOR_ACTIVITY_LAUNCH_MS, TimeUnit.MILLISECONDS)) { 220 fail("Timed out waiting for the activity result from " 221 + ActivityMonitorTestActivity.class.getName()); 222 } 223 assertEquals("There should be 1 monitor hit", 1, cam.getHits()); 224 } finally { 225 amTestActivity.finish(); 226 instrumentation.removeMonitor(cam); 227 } 228 } 229 230 /** 231 * Verifies that when the activity monitor is created using by passing activity class, 232 * then onStartActivity return value is ignored. 233 */ 234 public void testActivityMonitor_onStartActivityAndActivityClass() throws Exception { 235 final Instrumentation instrumentation = getInstrumentation(); 236 final Context context = instrumentation.getTargetContext(); 237 238 // Start ActivityMonitorTestActivity 239 final Intent intent = new Intent(context, ActivityMonitorTestActivity.class) 240 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 241 ActivityMonitorTestActivity amTestActivity = 242 (ActivityMonitorTestActivity) instrumentation.startActivitySync(intent); 243 244 // Initialize and set activity monitor. 245 final int expectedResultCode = 2244; 246 final String expectedAction = "matched_using_activity_class"; 247 final CustomActivityMonitor cam = new CustomActivityMonitor( 248 InstrumentationTestActivity.class.getName(), 249 new ActivityResult(expectedResultCode, new Intent(expectedAction)), 250 true); 251 cam.setResultToReturn(new ActivityResult(2222, new Intent("matched_using_onStartActivity"))); 252 instrumentation.addMonitor(cam); 253 254 // Start implicit InstrumentationTestActivity from ActivityMonitorTestActivity and verify 255 // it is intercepted using the activity class as expected. 256 try { 257 final CountDownLatch latch = new CountDownLatch(1); 258 amTestActivity.setOnActivityResultListener( 259 new ActivityMonitorTestActivity.OnActivityResultListener() { 260 @Override 261 public void onActivityResult(int requestCode, int resultCode, Intent data) { 262 assertEquals("Result code is not same as expected", 263 expectedResultCode, resultCode); 264 assertNotNull("Data from activity result is null", data); 265 assertEquals("Data action is not same as expected", 266 expectedAction, data.getAction()); 267 latch.countDown(); 268 } 269 }); 270 amTestActivity.startInstrumentationTestActivity(true); 271 if (!latch.await(TIMEOUT_FOR_ACTIVITY_LAUNCH_MS, TimeUnit.MILLISECONDS)) { 272 fail("Timed out waiting for the activity result from " 273 + ActivityMonitorTestActivity.class.getName()); 274 } 275 assertEquals("There should be 1 monitor hit", 1, cam.getHits()); 276 } finally { 277 amTestActivity.finish(); 278 instrumentation.removeMonitor(cam); 279 } 280 } 281 282 private class CustomActivityMonitor extends ActivityMonitor { 283 private ActivityResult mResultToReturn; 284 285 public CustomActivityMonitor(ActivityResult resultToReturn) { 286 super(); 287 mResultToReturn = resultToReturn; 288 } 289 290 public CustomActivityMonitor(IntentFilter intentFilter, ActivityResult result, 291 boolean blocked) { 292 super(intentFilter, result, blocked); 293 } 294 295 public CustomActivityMonitor(String activityClass, ActivityResult result, 296 boolean blocked) { 297 super(activityClass, result, blocked); 298 } 299 300 public void setResultToReturn(ActivityResult resultToReturn) { 301 mResultToReturn = resultToReturn; 302 } 303 304 @Override 305 public ActivityResult onStartActivity(Intent intent) { 306 final boolean implicitInstrumentationTestActivity = intent.getAction() != null && 307 InstrumentationTestActivity.START_INTENT.equals(intent.getAction()); 308 final boolean explicitInstrumentationTestActivity = intent.getComponent() != null && 309 InstrumentationTestActivity.class.getName().equals( 310 intent.getComponent().getClassName()); 311 if (implicitInstrumentationTestActivity || explicitInstrumentationTestActivity) { 312 return mResultToReturn; 313 } 314 return null; 315 } 316 } 317 } 318