1 /*
2  * Copyright (C) 2006 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.activity;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.os.Binder;
26 import android.os.Bundle;
27 import android.os.IBinder;
28 import android.os.Parcel;
29 import android.os.UserHandle;
30 import android.support.test.filters.LargeTest;
31 import android.test.FlakyTest;
32 import android.util.Log;
33 
34 import java.util.Arrays;
35 
36 @LargeTest
37 public class BroadcastTest extends ActivityTestsBase {
38     public static final int BROADCAST_TIMEOUT = 5 * 1000;
39 
40     public static final String BROADCAST_REGISTERED =
41             "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED";
42     public static final String BROADCAST_LOCAL =
43             "com.android.frameworks.coretests.activity.BROADCAST_LOCAL";
44     public static final String BROADCAST_LOCAL_GRANTED =
45             "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_GRANTED";
46     public static final String BROADCAST_LOCAL_DENIED =
47             "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_DENIED";
48     public static final String BROADCAST_REMOTE =
49             "com.android.frameworks.coretests.activity.BROADCAST_REMOTE";
50     public static final String BROADCAST_REMOTE_GRANTED =
51             "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_GRANTED";
52     public static final String BROADCAST_REMOTE_DENIED =
53             "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_DENIED";
54     public static final String BROADCAST_ALL =
55             "com.android.frameworks.coretests.activity.BROADCAST_ALL";
56     public static final String BROADCAST_MULTI =
57             "com.android.frameworks.coretests.activity.BROADCAST_MULTI";
58     public static final String BROADCAST_ABORT =
59             "com.android.frameworks.coretests.activity.BROADCAST_ABORT";
60 
61     public static final String BROADCAST_STICKY1 =
62             "com.android.frameworks.coretests.activity.BROADCAST_STICKY1";
63     public static final String BROADCAST_STICKY2 =
64             "com.android.frameworks.coretests.activity.BROADCAST_STICKY2";
65 
66     public static final String BROADCAST_FAIL_REGISTER =
67             "com.android.frameworks.coretests.activity.BROADCAST_FAIL_REGISTER";
68     public static final String BROADCAST_FAIL_BIND =
69             "com.android.frameworks.coretests.activity.BROADCAST_FAIL_BIND";
70 
71     public static final String RECEIVER_REG = "receiver-reg";
72     public static final String RECEIVER_LOCAL = "receiver-local";
73     public static final String RECEIVER_REMOTE = "receiver-remote";
74     public static final String RECEIVER_ABORT = "receiver-abort";
75     public static final String RECEIVER_RESULTS = "receiver-results";
76 
77     public static final String DATA_1 = "one";
78     public static final String DATA_2 = "two";
79 
80     public static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
81     public static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
82 
83     private String[] mExpectedReceivers = null;
84     private int mNextReceiver;
85 
86     private String[] mExpectedData = null;
87     private boolean[] mReceivedData = null;
88 
89     boolean mReceiverRegistered = false;
90 
setExpectedReceivers(String[] receivers)91     public void setExpectedReceivers(String[] receivers) {
92         mExpectedReceivers = receivers;
93         mNextReceiver = 0;
94     }
95 
setExpectedData(String[] data)96     public void setExpectedData(String[] data) {
97         mExpectedData = data;
98         mReceivedData = new boolean[data.length];
99     }
100 
onTimeout()101     public void onTimeout() {
102         String msg = "Timeout";
103         if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) {
104             msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver];
105         }
106         finishBad(msg);
107     }
108 
makeBroadcastIntent(String action)109     public Intent makeBroadcastIntent(String action) {
110         Intent intent = new Intent(action, null);
111         intent.putExtra("caller", mCallTarget);
112         return intent;
113     }
114 
finishWithResult(int resultCode, Intent data)115     public void finishWithResult(int resultCode, Intent data) {
116         unregisterMyReceiver();
117         super.finishWithResult(resultCode, data);
118     }
119 
gotReceive(String name, Intent intent)120     public final void gotReceive(String name, Intent intent) {
121         synchronized (this) {
122 
123             //System.out.println("Got receive: " + name);
124             //System.out.println(mNextReceiver + " in " + mExpectedReceivers);
125             //new RuntimeException("stack").printStackTrace();
126 
127             addIntermediate(name);
128 
129             if (mExpectedData != null) {
130                 int n = mExpectedData.length;
131                 int i;
132                 boolean prev = false;
133                 for (i = 0; i < n; i++) {
134                     if (mExpectedData[i].equals(intent.getStringExtra("test"))) {
135                         if (mReceivedData[i]) {
136                             prev = true;
137                             continue;
138                         }
139                         mReceivedData[i] = true;
140                         break;
141                     }
142                 }
143                 if (i >= n) {
144                     if (prev) {
145                         finishBad("Receive got data too many times: "
146                                 + intent.getStringExtra("test"));
147                     } else {
148                         finishBad("Receive got unexpected data: "
149                                 + intent.getStringExtra("test"));
150                     }
151                     new RuntimeException("stack").printStackTrace();
152                     return;
153                 }
154             }
155 
156             if (mNextReceiver >= mExpectedReceivers.length) {
157                 finishBad("Got too many onReceiveIntent() calls!");
158 //                System.out.println("Too many intents received: now at "
159 //                        + mNextReceiver + ", expect list: "
160 //                        + Arrays.toString(mExpectedReceivers));
161                 fail("Got too many onReceiveIntent() calls!");
162             } else if (!mExpectedReceivers[mNextReceiver].equals(name)) {
163                 finishBad("Receive out of order: got " + name
164                         + " but expected "
165                         + mExpectedReceivers[mNextReceiver]);
166                 fail("Receive out of order: got " + name
167                         + " but expected "
168                         + mExpectedReceivers[mNextReceiver]);
169             } else {
170                 mNextReceiver++;
171                 if (mNextReceiver == mExpectedReceivers.length) {
172                     finishTest();
173                 }
174             }
175         }
176     }
177 
registerMyReceiver(IntentFilter filter, String permission)178     public void registerMyReceiver(IntentFilter filter, String permission) {
179         mReceiverRegistered = true;
180         //System.out.println("Registering: " + mReceiver);
181         getContext().registerReceiver(mReceiver, filter, permission, null);
182     }
183 
unregisterMyReceiver()184     public void unregisterMyReceiver() {
185         if (mReceiverRegistered) {
186             unregisterMyReceiverNoCheck();
187         }
188     }
189 
unregisterMyReceiverNoCheck()190     public void unregisterMyReceiverNoCheck() {
191         mReceiverRegistered = false;
192         //System.out.println("Unregistering: " + mReceiver);
193         getContext().unregisterReceiver(mReceiver);
194     }
195 
onRegisteredReceiver(Intent intent)196     public void onRegisteredReceiver(Intent intent) {
197         gotReceive(RECEIVER_REG, intent);
198     }
199 
200     private Binder mCallTarget = new Binder() {
201         public boolean onTransact(int code, Parcel data, Parcel reply,
202                 int flags) {
203             data.setDataPosition(0);
204             data.enforceInterface(LaunchpadActivity.LAUNCH);
205             if (code == GOT_RECEIVE_TRANSACTION) {
206                 String name = data.readString();
207                 gotReceive(name, null);
208                 return true;
209             } else if (code == ERROR_TRANSACTION) {
210                 finishBad(data.readString());
211                 return true;
212             }
213             return false;
214         }
215     };
216 
finishTest()217     private void finishTest() {
218         if (mReceiverRegistered) {
219             addIntermediate("before-unregister");
220             unregisterMyReceiver();
221         }
222         finishTiming(true);
223         finishGood();
224     }
225 
226     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
227         public void onReceive(Context context, Intent intent) {
228             //System.out.println("Receive in: " + this + ": " + intent);
229             onRegisteredReceiver(intent);
230         }
231     };
232 
233     // Mark flaky until http://b/issue?id=1191607 is resolved.
234     @FlakyTest(tolerance=2)
testRegistered()235     public void testRegistered() throws Exception {
236         runLaunchpad(LaunchpadActivity.BROADCAST_REGISTERED);
237     }
238 
testLocal()239     public void testLocal() throws Exception {
240         runLaunchpad(LaunchpadActivity.BROADCAST_LOCAL);
241     }
242 
testRemote()243     public void testRemote() throws Exception {
244         runLaunchpad(LaunchpadActivity.BROADCAST_REMOTE);
245     }
246 
testAbort()247     public void testAbort() throws Exception {
248         runLaunchpad(LaunchpadActivity.BROADCAST_ABORT);
249     }
250 
251     @FlakyTest(tolerance=2)
testAll()252     public void testAll() throws Exception {
253         runLaunchpad(LaunchpadActivity.BROADCAST_ALL);
254     }
255 
256     @FlakyTest(tolerance=2)
testMulti()257     public void testMulti() throws Exception {
258         runLaunchpad(LaunchpadActivity.BROADCAST_MULTI);
259     }
260 
261     private class TestBroadcastReceiver extends BroadcastReceiver {
262         public boolean mHaveResult = false;
263 
264         @Override
onReceive(Context context, Intent intent)265         public void onReceive(Context context, Intent intent) {
266             synchronized (BroadcastTest.this) {
267                 mHaveResult = true;
268                 BroadcastTest.this.notifyAll();
269             }
270         }
271     }
272 
testResult()273     public void testResult() throws Exception {
274         TestBroadcastReceiver broadcastReceiver = new TestBroadcastReceiver();
275 
276         synchronized (this) {
277             Bundle map = new Bundle();
278             map.putString("foo", "you");
279             map.putString("remove", "me");
280             getContext().sendOrderedBroadcast(
281                     new Intent("com.android.frameworks.coretests.activity.BROADCAST_RESULT"),
282                     null, broadcastReceiver, null, 1, "foo", map);
283             while (!broadcastReceiver.mHaveResult) {
284                 try {
285                     wait();
286                 } catch (InterruptedException e) {
287                 }
288             }
289 
290             //System.out.println("Code: " + mResultCode + ", data: " + mResultData);
291             //System.out.println("Extras: " + mResultExtras);
292 
293             assertEquals("Incorrect code: " + broadcastReceiver.getResultCode(),
294                     3, broadcastReceiver.getResultCode());
295 
296             assertEquals("bar", broadcastReceiver.getResultData());
297 
298             Bundle resultExtras = broadcastReceiver.getResultExtras(false);
299             assertEquals("them", resultExtras.getString("bar"));
300             assertEquals("you", resultExtras.getString("foo"));
301             assertNull(resultExtras.getString("remove"));
302         }
303     }
304 
testSetSticky()305     public void testSetSticky() throws Exception {
306         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
307         intent.putExtra("test", LaunchpadActivity.DATA_1);
308         ActivityManager.getService().unbroadcastIntent(null, intent,
309                 UserHandle.myUserId());
310 
311         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
312         addIntermediate("finished-broadcast");
313 
314         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
315         Intent sticky = getContext().registerReceiver(null, filter);
316         assertNotNull("Sticky not found", sticky);
317         assertEquals(LaunchpadActivity.DATA_1, sticky.getStringExtra("test"));
318     }
319 
testClearSticky()320     public void testClearSticky() throws Exception {
321         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
322         intent.putExtra("test", LaunchpadActivity.DATA_1);
323         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
324 
325         ActivityManager.getService().unbroadcastIntent(
326                 null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null),
327                 UserHandle.myUserId());
328         addIntermediate("finished-unbroadcast");
329 
330         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
331         Intent sticky = getContext().registerReceiver(null, filter);
332         assertNull("Sticky not found", sticky);
333     }
334 
testReplaceSticky()335     public void testReplaceSticky() throws Exception {
336         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
337         intent.putExtra("test", LaunchpadActivity.DATA_1);
338         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
339         intent.putExtra("test", LaunchpadActivity.DATA_2);
340 
341         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
342         addIntermediate("finished-broadcast");
343 
344         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
345         Intent sticky = getContext().registerReceiver(null, filter);
346         assertNotNull("Sticky not found", sticky);
347         assertEquals(LaunchpadActivity.DATA_2, sticky.getStringExtra("test"));
348     }
349 
350     // Marking flaky until http://b/issue?id=1191337 is resolved
351     @FlakyTest(tolerance=2)
testReceiveSticky()352     public void testReceiveSticky() throws Exception {
353         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
354         intent.putExtra("test", LaunchpadActivity.DATA_1);
355         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
356 
357         runLaunchpad(LaunchpadActivity.BROADCAST_STICKY1);
358     }
359 
360     // Marking flaky until http://b/issue?id=1191337 is resolved
361     @FlakyTest(tolerance=2)
testReceive2Sticky()362     public void testReceive2Sticky() throws Exception {
363         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
364         intent.putExtra("test", LaunchpadActivity.DATA_1);
365         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
366         intent = new Intent(LaunchpadActivity.BROADCAST_STICKY2, null);
367         intent.putExtra("test", LaunchpadActivity.DATA_2);
368         ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId());
369 
370         runLaunchpad(LaunchpadActivity.BROADCAST_STICKY2);
371     }
372 
testRegisteredReceivePermissionGranted()373     public void testRegisteredReceivePermissionGranted() throws Exception {
374         setExpectedReceivers(new String[]{RECEIVER_REG});
375         registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED);
376         addIntermediate("after-register");
377         getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED));
378         waitForResultOrThrow(BROADCAST_TIMEOUT);
379     }
380 
testRegisteredReceivePermissionDenied()381     public void testRegisteredReceivePermissionDenied() throws Exception {
382         setExpectedReceivers(new String[]{RECEIVER_RESULTS});
383         registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED);
384         addIntermediate("after-register");
385 
386         BroadcastReceiver finish = new BroadcastReceiver() {
387             public void onReceive(Context context, Intent intent) {
388                 gotReceive(RECEIVER_RESULTS, intent);
389             }
390         };
391 
392         getContext().sendOrderedBroadcast(
393                 makeBroadcastIntent(BROADCAST_REGISTERED),
394                 null, finish, null, Activity.RESULT_CANCELED, null, null);
395         waitForResultOrThrow(BROADCAST_TIMEOUT);
396     }
397 
testRegisteredBroadcastPermissionGranted()398     public void testRegisteredBroadcastPermissionGranted() throws Exception {
399         setExpectedReceivers(new String[]{RECEIVER_REG});
400         registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null);
401         addIntermediate("after-register");
402         getContext().sendBroadcast(
403                 makeBroadcastIntent(BROADCAST_REGISTERED),
404                 PERMISSION_GRANTED);
405         waitForResultOrThrow(BROADCAST_TIMEOUT);
406     }
407 
testRegisteredBroadcastPermissionDenied()408     public void testRegisteredBroadcastPermissionDenied() throws Exception {
409         setExpectedReceivers(new String[]{RECEIVER_RESULTS});
410         registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null);
411         addIntermediate("after-register");
412 
413         BroadcastReceiver finish = new BroadcastReceiver() {
414             public void onReceive(Context context, Intent intent) {
415                 gotReceive(RECEIVER_RESULTS, intent);
416             }
417         };
418 
419         getContext().sendOrderedBroadcast(
420                 makeBroadcastIntent(BROADCAST_REGISTERED),
421                 PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED,
422                 null, null);
423         waitForResultOrThrow(BROADCAST_TIMEOUT);
424     }
425 
testLocalReceivePermissionGranted()426     public void testLocalReceivePermissionGranted() throws Exception {
427         setExpectedReceivers(new String[]{RECEIVER_LOCAL});
428         getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL_GRANTED));
429         waitForResultOrThrow(BROADCAST_TIMEOUT);
430     }
431 
testLocalReceivePermissionDenied()432     public void testLocalReceivePermissionDenied() throws Exception {
433         setExpectedReceivers(new String[]{RECEIVER_RESULTS});
434 
435         BroadcastReceiver finish = new BroadcastReceiver() {
436             public void onReceive(Context context, Intent intent) {
437                 gotReceive(RECEIVER_RESULTS, intent);
438             }
439         };
440 
441         getContext().sendOrderedBroadcast(
442                 makeBroadcastIntent(BROADCAST_LOCAL_DENIED),
443                 null, finish, null, Activity.RESULT_CANCELED,
444                 null, null);
445         waitForResultOrThrow(BROADCAST_TIMEOUT);
446     }
447 
testLocalBroadcastPermissionGranted()448     public void testLocalBroadcastPermissionGranted() throws Exception {
449         setExpectedReceivers(new String[]{RECEIVER_LOCAL});
450         getContext().sendBroadcast(
451                 makeBroadcastIntent(BROADCAST_LOCAL),
452                 PERMISSION_GRANTED);
453         waitForResultOrThrow(BROADCAST_TIMEOUT);
454     }
455 
testLocalBroadcastPermissionDenied()456     public void testLocalBroadcastPermissionDenied() throws Exception {
457         setExpectedReceivers(new String[]{RECEIVER_RESULTS});
458 
459         BroadcastReceiver finish = new BroadcastReceiver() {
460             public void onReceive(Context context, Intent intent) {
461                 gotReceive(RECEIVER_RESULTS, intent);
462             }
463         };
464 
465         getContext().sendOrderedBroadcast(
466                 makeBroadcastIntent(BROADCAST_LOCAL),
467                 PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED,
468                 null, null);
469         waitForResultOrThrow(BROADCAST_TIMEOUT);
470     }
471 
testRemoteReceivePermissionGranted()472     public void testRemoteReceivePermissionGranted() throws Exception {
473         setExpectedReceivers(new String[]{RECEIVER_REMOTE});
474         getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE_GRANTED));
475         waitForResultOrThrow(BROADCAST_TIMEOUT);
476     }
477 
testRemoteReceivePermissionDenied()478     public void testRemoteReceivePermissionDenied() throws Exception {
479         setExpectedReceivers(new String[]{RECEIVER_RESULTS});
480 
481         BroadcastReceiver finish = new BroadcastReceiver() {
482             public void onReceive(Context context, Intent intent) {
483                 gotReceive(RECEIVER_RESULTS, intent);
484             }
485         };
486 
487         getContext().sendOrderedBroadcast(
488                 makeBroadcastIntent(BROADCAST_REMOTE_DENIED),
489                 null, finish, null, Activity.RESULT_CANCELED,
490                 null, null);
491         waitForResultOrThrow(BROADCAST_TIMEOUT);
492     }
493 
testRemoteBroadcastPermissionGranted()494     public void testRemoteBroadcastPermissionGranted() throws Exception {
495         setExpectedReceivers(new String[]{RECEIVER_REMOTE});
496         getContext().sendBroadcast(
497                 makeBroadcastIntent(BROADCAST_REMOTE),
498                 PERMISSION_GRANTED);
499         waitForResultOrThrow(BROADCAST_TIMEOUT);
500     }
501 
testRemoteBroadcastPermissionDenied()502     public void testRemoteBroadcastPermissionDenied() throws Exception {
503         setExpectedReceivers(new String[]{RECEIVER_RESULTS});
504 
505         BroadcastReceiver finish = new BroadcastReceiver() {
506             public void onReceive(Context context, Intent intent) {
507                 gotReceive(RECEIVER_RESULTS, intent);
508             }
509         };
510 
511         getContext().sendOrderedBroadcast(
512                 makeBroadcastIntent(BROADCAST_REMOTE),
513                 PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED,
514                 null, null);
515         waitForResultOrThrow(BROADCAST_TIMEOUT);
516     }
517 
testReceiverCanNotRegister()518     public void testReceiverCanNotRegister() throws Exception {
519         setExpectedReceivers(new String[]{RECEIVER_LOCAL});
520         getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_REGISTER));
521         waitForResultOrThrow(BROADCAST_TIMEOUT);
522     }
523 
testReceiverCanNotBind()524     public void testReceiverCanNotBind() throws Exception {
525         setExpectedReceivers(new String[]{RECEIVER_LOCAL});
526         getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_BIND));
527         waitForResultOrThrow(BROADCAST_TIMEOUT);
528     }
529 
testLocalUnregisterTwice()530     public void testLocalUnregisterTwice() throws Exception {
531         registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null);
532         unregisterMyReceiverNoCheck();
533         try {
534             unregisterMyReceiverNoCheck();
535             fail("No exception thrown on second unregister");
536         } catch (IllegalArgumentException e) {
537             Log.i("foo", "Unregister exception", e);
538         }
539     }
540 }
541