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