• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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