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.broadcasts; 18 19 import static android.content.Context.RECEIVER_EXPORTED; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertNull; 25 import static org.junit.Assert.assertTrue; 26 27 import android.content.BroadcastReceiver; 28 import android.content.BroadcastReceiver.PendingResult; 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.content.pm.PackageManager; 34 import android.hardware.Camera; 35 import android.os.Bundle; 36 import android.os.FileUtils; 37 import android.os.IBinder; 38 import android.os.ParcelFileDescriptor; 39 import android.platform.test.annotations.AppModeFull; 40 import android.platform.test.annotations.AppModeSdkSandbox; 41 42 import androidx.test.platform.app.InstrumentationRegistry; 43 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 47 import java.io.ByteArrayOutputStream; 48 import java.io.FileInputStream; 49 import java.util.concurrent.CompletableFuture; 50 import java.util.concurrent.TimeUnit; 51 52 @RunWith(BroadcastsTestRunner.class) 53 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 54 public class BroadcastReceiverTest extends BaseBroadcastTest { 55 private static final int RESULT_INITIAL_CODE = 1; 56 private static final String RESULT_INITIAL_DATA = "initial data"; 57 58 private static final int RESULT_INTERNAL_FINAL_CODE = 7; 59 private static final String RESULT_INTERNAL_FINAL_DATA = "internal final data"; 60 61 private static final String ACTION_BROADCAST_INTERNAL = 62 "com.android.cts.broadcasts.BROADCAST_INTERNAL"; 63 private static final String ACTION_BROADCAST_MOCKTEST = 64 "com.android.cts.broadcasts.BROADCAST_MOCKTEST"; 65 private static final String ACTION_BROADCAST_TESTABORT = 66 "com.android.cts.broadcasts.BROADCAST_TESTABORT"; 67 private static final String ACTION_BROADCAST_DISABLED = 68 "com.android.cts.broadcasts.BROADCAST_DISABLED"; 69 private static final String TEST_PACKAGE_NAME = "com.android.cts.broadcasts"; 70 71 private static final String SIGNATURE_PERMISSION = 72 "com.android.cts.broadcasts.SIGNATURE_PERMISSION"; 73 74 private static final long SEND_BROADCAST_TIMEOUT = 15000; 75 76 private static final ComponentName DISABLEABLE_RECEIVER = new ComponentName(TEST_PACKAGE_NAME, 77 "android.app.cts.broadcasts.MockReceiverDisableable"); 78 79 @Test testConstructor()80 public void testConstructor() { 81 new MockReceiverInternal(); 82 } 83 84 @Test testAccessDebugUnregister()85 public void testAccessDebugUnregister() { 86 MockReceiverInternal mockReceiver = new MockReceiverInternal(); 87 assertFalse(mockReceiver.getDebugUnregister()); 88 89 mockReceiver.setDebugUnregister(true); 90 assertTrue(mockReceiver.getDebugUnregister()); 91 92 mockReceiver.setDebugUnregister(false); 93 assertFalse(mockReceiver.getDebugUnregister()); 94 } 95 96 @Test testSetOrderedHint()97 public void testSetOrderedHint() { 98 MockReceiverInternal mockReceiver = new MockReceiverInternal(); 99 100 /* 101 * Let's just test to make sure the method doesn't fail for this one. 102 * It's marked as "for internal use". 103 */ 104 mockReceiver.setOrderedHint(true); 105 mockReceiver.setOrderedHint(false); 106 } 107 108 private class MockReceiverInternal extends BroadcastReceiver { 109 protected boolean mCalledOnReceive = false; 110 private IBinder mIBinder; 111 private final Intent mServiceIntentToPeek; 112 MockReceiverInternal()113 MockReceiverInternal() { 114 this(null); 115 } 116 MockReceiverInternal(Intent serviceIntentToPeek)117 MockReceiverInternal(Intent serviceIntentToPeek) { 118 mServiceIntentToPeek = serviceIntentToPeek; 119 } 120 121 @Override onReceive(Context context, Intent intent)122 public synchronized void onReceive(Context context, Intent intent) { 123 mCalledOnReceive = true; 124 if (mServiceIntentToPeek != null) { 125 mIBinder = peekService(context, mServiceIntentToPeek); 126 } 127 notifyAll(); 128 } 129 reset()130 public void reset() { 131 mCalledOnReceive = false; 132 } 133 waitForReceiver(long timeout)134 public synchronized void waitForReceiver(long timeout) 135 throws InterruptedException { 136 if (!mCalledOnReceive) { 137 wait(timeout); 138 } 139 assertTrue(mCalledOnReceive); 140 } 141 waitForReceiverNoException(long timeout)142 public synchronized boolean waitForReceiverNoException(long timeout) 143 throws InterruptedException { 144 if (!mCalledOnReceive) { 145 wait(timeout); 146 } 147 return mCalledOnReceive; 148 } 149 getIBinder()150 public IBinder getIBinder() { 151 return mIBinder; 152 } 153 } 154 155 private class MockReceiverInternalOrder extends MockReceiverInternal { 156 @Override onReceive(Context context, Intent intent)157 public synchronized void onReceive(Context context, Intent intent) { 158 setResultCode(RESULT_INTERNAL_FINAL_CODE); 159 setResultData(RESULT_INTERNAL_FINAL_DATA); 160 161 super.onReceive(context, intent); 162 } 163 } 164 165 private class MockReceiverInternalVerifyUncalled extends MockReceiverInternal { 166 final int mExpectedInitialCode; 167 MockReceiverInternalVerifyUncalled(int initialCode)168 MockReceiverInternalVerifyUncalled(int initialCode) { 169 mExpectedInitialCode = initialCode; 170 } 171 172 @Override onReceive(Context context, Intent intent)173 public synchronized void onReceive(Context context, Intent intent) { 174 // only update to the expected final values if we're still in the 175 // initial conditions. The intermediate receiver would have 176 // updated the result code if it [inappropriately] ran. 177 if (getResultCode() == mExpectedInitialCode) { 178 setResultCode(RESULT_INTERNAL_FINAL_CODE); 179 } 180 181 super.onReceive(context, intent); 182 } 183 } 184 185 public static class MockAsyncReceiver extends BroadcastReceiver { 186 public CompletableFuture<PendingResult> pendingResult = new CompletableFuture<>(); 187 188 @Override onReceive(Context context, Intent intent)189 public void onReceive(Context context, Intent intent) { 190 pendingResult.complete(goAsync()); 191 } 192 } 193 194 @Test testOnReceive()195 public void testOnReceive() throws Exception { 196 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 197 IntentFilter filter = new IntentFilter(); 198 filter.addAction(ACTION_BROADCAST_INTERNAL); 199 mContext.registerReceiver(internalReceiver, filter, RECEIVER_EXPORTED); 200 try { 201 assertEquals(0, internalReceiver.getResultCode()); 202 assertEquals(null, internalReceiver.getResultData()); 203 assertEquals(null, internalReceiver.getResultExtras(false)); 204 205 mContext.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL) 206 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)); 207 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 208 } finally { 209 mContext.unregisterReceiver(internalReceiver); 210 } 211 } 212 213 @Test 214 @AppModeFull testManifestReceiverPackage()215 public void testManifestReceiverPackage() throws Exception { 216 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 217 218 Bundle map = new Bundle(); 219 map.putString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY, 220 MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE); 221 map.putString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY, 222 MockReceiver.RESULT_EXTRAS_REMOVE_VALUE); 223 mContext.sendOrderedBroadcast( 224 new Intent(ACTION_BROADCAST_MOCKTEST) 225 .setPackage(TEST_PACKAGE_NAME).addFlags(Intent.FLAG_RECEIVER_FOREGROUND), 226 null, internalReceiver, 227 null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map); 228 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 229 230 // These are set by MockReceiver. 231 assertEquals(MockReceiver.RESULT_CODE, internalReceiver.getResultCode()); 232 assertEquals(MockReceiver.RESULT_DATA, internalReceiver.getResultData()); 233 234 Bundle resultExtras = internalReceiver.getResultExtras(false); 235 assertEquals(MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE, 236 resultExtras.getString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY)); 237 assertEquals(MockReceiver.RESULT_EXTRAS_ADD_VALUE, 238 resultExtras.getString(MockReceiver.RESULT_EXTRAS_ADD_KEY)); 239 assertNull(resultExtras.getString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY)); 240 } 241 242 @Test 243 @AppModeFull testManifestReceiverComponent()244 public void testManifestReceiverComponent() throws Exception { 245 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 246 247 Bundle map = new Bundle(); 248 map.putString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY, 249 MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE); 250 map.putString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY, 251 MockReceiver.RESULT_EXTRAS_REMOVE_VALUE); 252 mContext.sendOrderedBroadcast( 253 new Intent(ACTION_BROADCAST_MOCKTEST) 254 .setClass(mContext, MockReceiver.class) 255 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND), 256 null, internalReceiver, 257 null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map); 258 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 259 260 // These are set by MockReceiver. 261 assertEquals(MockReceiver.RESULT_CODE, internalReceiver.getResultCode()); 262 assertEquals(MockReceiver.RESULT_DATA, internalReceiver.getResultData()); 263 264 Bundle resultExtras = internalReceiver.getResultExtras(false); 265 assertEquals(MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE, 266 resultExtras.getString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY)); 267 assertEquals(MockReceiver.RESULT_EXTRAS_ADD_VALUE, 268 resultExtras.getString(MockReceiver.RESULT_EXTRAS_ADD_KEY)); 269 assertNull(resultExtras.getString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY)); 270 } 271 272 @Test 273 @AppModeFull testManifestReceiverPermission()274 public void testManifestReceiverPermission() throws Exception { 275 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 276 277 Bundle map = new Bundle(); 278 map.putString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY, 279 MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE); 280 map.putString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY, 281 MockReceiver.RESULT_EXTRAS_REMOVE_VALUE); 282 mContext.sendOrderedBroadcast( 283 new Intent(ACTION_BROADCAST_MOCKTEST) 284 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND), 285 SIGNATURE_PERMISSION, internalReceiver, 286 null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map); 287 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 288 289 // These are set by MockReceiver. 290 assertEquals(MockReceiver.RESULT_CODE, internalReceiver.getResultCode()); 291 assertEquals(MockReceiver.RESULT_DATA, internalReceiver.getResultData()); 292 293 Bundle resultExtras = internalReceiver.getResultExtras(false); 294 assertEquals(MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE, 295 resultExtras.getString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY)); 296 assertEquals(MockReceiver.RESULT_EXTRAS_ADD_VALUE, 297 resultExtras.getString(MockReceiver.RESULT_EXTRAS_ADD_KEY)); 298 assertNull(resultExtras.getString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY)); 299 } 300 301 @Test testNoManifestReceiver()302 public void testNoManifestReceiver() throws Exception { 303 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 304 305 Bundle map = new Bundle(); 306 map.putString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY, 307 MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE); 308 map.putString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY, 309 MockReceiver.RESULT_EXTRAS_REMOVE_VALUE); 310 mContext.sendOrderedBroadcast( 311 new Intent(ACTION_BROADCAST_MOCKTEST).addFlags(Intent.FLAG_RECEIVER_FOREGROUND), 312 null, internalReceiver, 313 null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map); 314 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 315 316 // The MockReceiver should not have run, so we should still have the initial result. 317 assertEquals(RESULT_INITIAL_CODE, internalReceiver.getResultCode()); 318 assertEquals(RESULT_INITIAL_DATA, internalReceiver.getResultData()); 319 320 Bundle resultExtras = internalReceiver.getResultExtras(false); 321 assertEquals(MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE, 322 resultExtras.getString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY)); 323 assertNull(resultExtras.getString(MockReceiver.RESULT_EXTRAS_ADD_KEY)); 324 assertEquals(MockReceiver.RESULT_EXTRAS_REMOVE_VALUE, 325 resultExtras.getString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY)); 326 } 327 328 @Test 329 @AppModeFull testAbortBroadcast()330 public void testAbortBroadcast() throws Exception { 331 MockReceiverInternalOrder internalOrderReceiver = new MockReceiverInternalOrder(); 332 333 assertEquals(0, internalOrderReceiver.getResultCode()); 334 assertNull(internalOrderReceiver.getResultData()); 335 assertNull(internalOrderReceiver.getResultExtras(false)); 336 337 Bundle map = new Bundle(); 338 map.putString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY, 339 MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE); 340 map.putString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY, 341 MockReceiver.RESULT_EXTRAS_REMOVE_VALUE); 342 // The order of the receiver is: 343 // MockReceiverFirst --> MockReceiverAbort --> MockReceiver --> internalOrderReceiver. 344 // And MockReceiver is the receiver which will be aborted. 345 mContext.sendOrderedBroadcast( 346 new Intent(ACTION_BROADCAST_TESTABORT) 347 .setPackage(TEST_PACKAGE_NAME).addFlags(Intent.FLAG_RECEIVER_FOREGROUND), 348 null, internalOrderReceiver, 349 null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, map); 350 internalOrderReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 351 352 assertEquals(RESULT_INTERNAL_FINAL_CODE, internalOrderReceiver.getResultCode()); 353 assertEquals(RESULT_INTERNAL_FINAL_DATA, internalOrderReceiver.getResultData()); 354 Bundle resultExtras = internalOrderReceiver.getResultExtras(false); 355 assertEquals(MockReceiver.RESULT_EXTRAS_INVARIABLE_VALUE, 356 resultExtras.getString(MockReceiver.RESULT_EXTRAS_INVARIABLE_KEY)); 357 assertEquals(MockReceiver.RESULT_EXTRAS_REMOVE_VALUE, 358 resultExtras.getString(MockReceiver.RESULT_EXTRAS_REMOVE_KEY)); 359 assertEquals(MockReceiverFirst.RESULT_EXTRAS_FIRST_VALUE, 360 resultExtras.getString(MockReceiverFirst.RESULT_EXTRAS_FIRST_KEY)); 361 assertEquals(MockReceiverAbort.RESULT_EXTRAS_ABORT_VALUE, 362 resultExtras.getString(MockReceiverAbort.RESULT_EXTRAS_ABORT_KEY)); 363 } 364 365 @Test testDisabledBroadcastReceiver()366 public void testDisabledBroadcastReceiver() throws Exception { 367 PackageManager pm = mContext.getPackageManager(); 368 369 MockReceiverInternalVerifyUncalled lastReceiver = 370 new MockReceiverInternalVerifyUncalled(RESULT_INITIAL_CODE); 371 assertEquals(0, lastReceiver.getResultCode()); 372 373 pm.setComponentEnabledSetting(DISABLEABLE_RECEIVER, 374 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 375 PackageManager.DONT_KILL_APP); 376 377 mContext.sendOrderedBroadcast( 378 new Intent(ACTION_BROADCAST_DISABLED).addFlags(Intent.FLAG_RECEIVER_FOREGROUND), 379 null, lastReceiver, 380 null, RESULT_INITIAL_CODE, RESULT_INITIAL_DATA, new Bundle()); 381 lastReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 382 383 assertEquals(RESULT_INTERNAL_FINAL_CODE, lastReceiver.getResultCode()); 384 } 385 386 @Test testPeekService()387 public void testPeekService() throws Exception { 388 final Intent serviceIntent = new Intent().setComponent( 389 new ComponentName(HELPER_PKG1, HELPER_SERVICE)); 390 MockReceiverInternal internalReceiver = new MockReceiverInternal(serviceIntent); 391 IntentFilter filter = new IntentFilter(); 392 filter.addAction(ACTION_BROADCAST_INTERNAL); 393 mContext.registerReceiver(internalReceiver, filter, RECEIVER_EXPORTED); 394 try { 395 mContext.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL) 396 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)); 397 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 398 assertNull(internalReceiver.getIBinder()); 399 400 final TestServiceConnection connection = bindToHelperService(HELPER_PKG1); 401 try { 402 assertNotNull(connection.getService()); 403 internalReceiver.reset(); 404 mContext.sendBroadcast(new Intent(ACTION_BROADCAST_INTERNAL) 405 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)); 406 internalReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 407 assertNotNull(internalReceiver.getIBinder()); 408 } finally { 409 connection.unbind(); 410 } 411 } finally { 412 mContext.unregisterReceiver(internalReceiver); 413 } 414 } 415 416 @Test testAsync()417 public void testAsync() throws Exception { 418 final MockAsyncReceiver asyncReceiver = new MockAsyncReceiver(); 419 final IntentFilter filter = new IntentFilter(); 420 filter.addAction(ACTION_BROADCAST_INTERNAL); 421 mContext.registerReceiver(asyncReceiver, filter, RECEIVER_EXPORTED); 422 423 final Intent intent = new Intent(ACTION_BROADCAST_INTERNAL) 424 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 425 final MockReceiverInternal resultReceiver = new MockReceiverInternal(); 426 mContext.sendOrderedBroadcast(intent, null, resultReceiver, null, 24, null, null); 427 428 final PendingResult res = asyncReceiver.pendingResult.get(SEND_BROADCAST_TIMEOUT, 429 TimeUnit.MILLISECONDS); 430 res.setResultCode(42); 431 res.finish(); 432 433 resultReceiver.waitForReceiver(SEND_BROADCAST_TIMEOUT); 434 assertEquals(42, resultReceiver.getResultCode()); 435 } 436 437 @Test testNewPhotoBroadcast_notReceived()438 public void testNewPhotoBroadcast_notReceived() throws Exception { 439 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 440 IntentFilter filter = new IntentFilter(); 441 filter.addAction(Camera.ACTION_NEW_PICTURE); 442 mContext.registerReceiver(internalReceiver, filter, RECEIVER_EXPORTED); 443 assertFalse(internalReceiver.waitForReceiverNoException(SEND_BROADCAST_TIMEOUT)); 444 } 445 446 @Test testNewVideoBroadcast_notReceived()447 public void testNewVideoBroadcast_notReceived() throws Exception { 448 MockReceiverInternal internalReceiver = new MockReceiverInternal(); 449 IntentFilter filter = new IntentFilter(); 450 filter.addAction(Camera.ACTION_NEW_VIDEO); 451 mContext.registerReceiver(internalReceiver, filter, RECEIVER_EXPORTED); 452 assertFalse(internalReceiver.waitForReceiverNoException(SEND_BROADCAST_TIMEOUT)); 453 } 454 executeShellCommand(String cmd)455 private static byte[] executeShellCommand(String cmd) throws Exception { 456 ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation() 457 .getUiAutomation().executeShellCommand(cmd); 458 try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd); 459 ByteArrayOutputStream out = new ByteArrayOutputStream()) { 460 FileUtils.copy(in, out); 461 return out.toByteArray(); 462 } 463 } 464 } 465