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