| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.app.activity; |
| |
| import android.app.Activity; |
| import android.app.ActivityManager; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.os.Binder; |
| import android.os.Bundle; |
| import android.os.IBinder; |
| import android.os.Parcel; |
| import android.os.UserHandle; |
| import android.util.Log; |
| |
| import androidx.test.filters.FlakyTest; |
| import androidx.test.filters.LargeTest; |
| |
| @LargeTest |
| public class BroadcastTest extends ActivityTestsBase { |
| public static final int BROADCAST_TIMEOUT = 5 * 1000; |
| |
| public static final String BROADCAST_REGISTERED = |
| "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED"; |
| public static final String BROADCAST_LOCAL = |
| "com.android.frameworks.coretests.activity.BROADCAST_LOCAL"; |
| public static final String BROADCAST_LOCAL_GRANTED = |
| "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_GRANTED"; |
| public static final String BROADCAST_LOCAL_DENIED = |
| "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_DENIED"; |
| public static final String BROADCAST_REMOTE = |
| "com.android.frameworks.coretests.activity.BROADCAST_REMOTE"; |
| public static final String BROADCAST_REMOTE_GRANTED = |
| "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_GRANTED"; |
| public static final String BROADCAST_REMOTE_DENIED = |
| "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_DENIED"; |
| public static final String BROADCAST_ALL = |
| "com.android.frameworks.coretests.activity.BROADCAST_ALL"; |
| public static final String BROADCAST_MULTI = |
| "com.android.frameworks.coretests.activity.BROADCAST_MULTI"; |
| public static final String BROADCAST_ABORT = |
| "com.android.frameworks.coretests.activity.BROADCAST_ABORT"; |
| |
| public static final String BROADCAST_STICKY1 = |
| "com.android.frameworks.coretests.activity.BROADCAST_STICKY1"; |
| public static final String BROADCAST_STICKY2 = |
| "com.android.frameworks.coretests.activity.BROADCAST_STICKY2"; |
| |
| public static final String BROADCAST_FAIL_REGISTER = |
| "com.android.frameworks.coretests.activity.BROADCAST_FAIL_REGISTER"; |
| public static final String BROADCAST_FAIL_BIND = |
| "com.android.frameworks.coretests.activity.BROADCAST_FAIL_BIND"; |
| |
| public static final String RECEIVER_REG = "receiver-reg"; |
| public static final String RECEIVER_LOCAL = "receiver-local"; |
| public static final String RECEIVER_REMOTE = "receiver-remote"; |
| public static final String RECEIVER_ABORT = "receiver-abort"; |
| public static final String RECEIVER_RESULTS = "receiver-results"; |
| |
| public static final String DATA_1 = "one"; |
| public static final String DATA_2 = "two"; |
| |
| public static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; |
| public static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1; |
| |
| private String[] mExpectedReceivers = null; |
| private int mNextReceiver; |
| |
| private String[] mExpectedData = null; |
| private boolean[] mReceivedData = null; |
| |
| boolean mReceiverRegistered = false; |
| |
| public void setExpectedReceivers(String[] receivers) { |
| mExpectedReceivers = receivers; |
| mNextReceiver = 0; |
| } |
| |
| public void setExpectedData(String[] data) { |
| mExpectedData = data; |
| mReceivedData = new boolean[data.length]; |
| } |
| |
| public void onTimeout() { |
| String msg = "Timeout"; |
| if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) { |
| msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver]; |
| } |
| finishBad(msg); |
| } |
| |
| public Intent makeBroadcastIntent(String action) { |
| Intent intent = new Intent(action, null); |
| intent.putExtra("caller", mCallTarget); |
| return intent; |
| } |
| |
| public void finishWithResult(int resultCode, Intent data) { |
| unregisterMyReceiver(); |
| super.finishWithResult(resultCode, data); |
| } |
| |
| public final void gotReceive(String name, Intent intent) { |
| synchronized (this) { |
| |
| //System.out.println("Got receive: " + name); |
| //System.out.println(mNextReceiver + " in " + mExpectedReceivers); |
| //new RuntimeException("stack").printStackTrace(); |
| |
| addIntermediate(name); |
| |
| if (mExpectedData != null) { |
| int n = mExpectedData.length; |
| int i; |
| boolean prev = false; |
| for (i = 0; i < n; i++) { |
| if (mExpectedData[i].equals(intent.getStringExtra("test"))) { |
| if (mReceivedData[i]) { |
| prev = true; |
| continue; |
| } |
| mReceivedData[i] = true; |
| break; |
| } |
| } |
| if (i >= n) { |
| if (prev) { |
| finishBad("Receive got data too many times: " |
| + intent.getStringExtra("test")); |
| } else { |
| finishBad("Receive got unexpected data: " |
| + intent.getStringExtra("test")); |
| } |
| new RuntimeException("stack").printStackTrace(); |
| return; |
| } |
| } |
| |
| if (mNextReceiver >= mExpectedReceivers.length) { |
| finishBad("Got too many onReceiveIntent() calls!"); |
| // System.out.println("Too many intents received: now at " |
| // + mNextReceiver + ", expect list: " |
| // + Arrays.toString(mExpectedReceivers)); |
| fail("Got too many onReceiveIntent() calls!"); |
| } else if (!mExpectedReceivers[mNextReceiver].equals(name)) { |
| finishBad("Receive out of order: got " + name |
| + " but expected " |
| + mExpectedReceivers[mNextReceiver]); |
| fail("Receive out of order: got " + name |
| + " but expected " |
| + mExpectedReceivers[mNextReceiver]); |
| } else { |
| mNextReceiver++; |
| if (mNextReceiver == mExpectedReceivers.length) { |
| finishTest(); |
| } |
| } |
| } |
| } |
| |
| public void registerMyReceiver(IntentFilter filter, String permission) { |
| mReceiverRegistered = true; |
| //System.out.println("Registering: " + mReceiver); |
| getContext().registerReceiver(mReceiver, filter, permission, null); |
| } |
| |
| public void unregisterMyReceiver() { |
| if (mReceiverRegistered) { |
| unregisterMyReceiverNoCheck(); |
| } |
| } |
| |
| public void unregisterMyReceiverNoCheck() { |
| mReceiverRegistered = false; |
| //System.out.println("Unregistering: " + mReceiver); |
| getContext().unregisterReceiver(mReceiver); |
| } |
| |
| public void onRegisteredReceiver(Intent intent) { |
| gotReceive(RECEIVER_REG, intent); |
| } |
| |
| private Binder mCallTarget = new Binder() { |
| public boolean onTransact(int code, Parcel data, Parcel reply, |
| int flags) { |
| data.setDataPosition(0); |
| data.enforceInterface(LaunchpadActivity.LAUNCH); |
| if (code == GOT_RECEIVE_TRANSACTION) { |
| String name = data.readString(); |
| gotReceive(name, null); |
| return true; |
| } else if (code == ERROR_TRANSACTION) { |
| finishBad(data.readString()); |
| return true; |
| } |
| return false; |
| } |
| }; |
| |
| private void finishTest() { |
| if (mReceiverRegistered) { |
| addIntermediate("before-unregister"); |
| unregisterMyReceiver(); |
| } |
| finishTiming(true); |
| finishGood(); |
| } |
| |
| private BroadcastReceiver mReceiver = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| //System.out.println("Receive in: " + this + ": " + intent); |
| onRegisteredReceiver(intent); |
| } |
| }; |
| |
| // Mark flaky until http://b/issue?id=1191607 is resolved. |
| @FlakyTest |
| public void testRegistered() throws Exception { |
| runLaunchpad(LaunchpadActivity.BROADCAST_REGISTERED); |
| } |
| |
| public void testLocal() throws Exception { |
| runLaunchpad(LaunchpadActivity.BROADCAST_LOCAL); |
| } |
| |
| public void testRemote() throws Exception { |
| runLaunchpad(LaunchpadActivity.BROADCAST_REMOTE); |
| } |
| |
| public void testAbort() throws Exception { |
| runLaunchpad(LaunchpadActivity.BROADCAST_ABORT); |
| } |
| |
| @FlakyTest |
| public void testAll() throws Exception { |
| runLaunchpad(LaunchpadActivity.BROADCAST_ALL); |
| } |
| |
| @FlakyTest |
| public void testMulti() throws Exception { |
| runLaunchpad(LaunchpadActivity.BROADCAST_MULTI); |
| } |
| |
| private class TestBroadcastReceiver extends BroadcastReceiver { |
| public boolean mHaveResult = false; |
| |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| synchronized (BroadcastTest.this) { |
| mHaveResult = true; |
| BroadcastTest.this.notifyAll(); |
| } |
| } |
| } |
| |
| public void testResult() throws Exception { |
| TestBroadcastReceiver broadcastReceiver = new TestBroadcastReceiver(); |
| |
| synchronized (this) { |
| Bundle map = new Bundle(); |
| map.putString("foo", "you"); |
| map.putString("remove", "me"); |
| getContext().sendOrderedBroadcast( |
| new Intent("com.android.frameworks.coretests.activity.BROADCAST_RESULT"), |
| null, broadcastReceiver, null, 1, "foo", map); |
| while (!broadcastReceiver.mHaveResult) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| //System.out.println("Code: " + mResultCode + ", data: " + mResultData); |
| //System.out.println("Extras: " + mResultExtras); |
| |
| assertEquals("Incorrect code: " + broadcastReceiver.getResultCode(), |
| 3, broadcastReceiver.getResultCode()); |
| |
| assertEquals("bar", broadcastReceiver.getResultData()); |
| |
| Bundle resultExtras = broadcastReceiver.getResultExtras(false); |
| assertEquals("them", resultExtras.getString("bar")); |
| assertEquals("you", resultExtras.getString("foo")); |
| assertNull(resultExtras.getString("remove")); |
| } |
| } |
| |
| public void testSetSticky() throws Exception { |
| Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); |
| intent.putExtra("test", LaunchpadActivity.DATA_1); |
| ActivityManager.getService().unbroadcastIntent(null, intent, |
| UserHandle.myUserId()); |
| |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| addIntermediate("finished-broadcast"); |
| |
| IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); |
| Intent sticky = getContext().registerReceiver(null, filter); |
| assertNotNull("Sticky not found", sticky); |
| assertEquals(LaunchpadActivity.DATA_1, sticky.getStringExtra("test")); |
| } |
| |
| public void testClearSticky() throws Exception { |
| Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); |
| intent.putExtra("test", LaunchpadActivity.DATA_1); |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| |
| ActivityManager.getService().unbroadcastIntent( |
| null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null), |
| UserHandle.myUserId()); |
| addIntermediate("finished-unbroadcast"); |
| |
| IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); |
| Intent sticky = getContext().registerReceiver(null, filter); |
| assertNull("Sticky not found", sticky); |
| } |
| |
| public void testReplaceSticky() throws Exception { |
| Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); |
| intent.putExtra("test", LaunchpadActivity.DATA_1); |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| intent.putExtra("test", LaunchpadActivity.DATA_2); |
| |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| addIntermediate("finished-broadcast"); |
| |
| IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1); |
| Intent sticky = getContext().registerReceiver(null, filter); |
| assertNotNull("Sticky not found", sticky); |
| assertEquals(LaunchpadActivity.DATA_2, sticky.getStringExtra("test")); |
| } |
| |
| // Marking flaky until http://b/issue?id=1191337 is resolved |
| @FlakyTest |
| public void testReceiveSticky() throws Exception { |
| Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); |
| intent.putExtra("test", LaunchpadActivity.DATA_1); |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| |
| runLaunchpad(LaunchpadActivity.BROADCAST_STICKY1); |
| } |
| |
| // Marking flaky until http://b/issue?id=1191337 is resolved |
| @FlakyTest |
| public void testReceive2Sticky() throws Exception { |
| Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null); |
| intent.putExtra("test", LaunchpadActivity.DATA_1); |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| intent = new Intent(LaunchpadActivity.BROADCAST_STICKY2, null); |
| intent.putExtra("test", LaunchpadActivity.DATA_2); |
| ActivityManager.broadcastStickyIntent(intent, UserHandle.myUserId()); |
| |
| runLaunchpad(LaunchpadActivity.BROADCAST_STICKY2); |
| } |
| |
| public void testRegisteredReceivePermissionGranted() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_REG}); |
| registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED); |
| addIntermediate("after-register"); |
| getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED)); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRegisteredReceivePermissionDenied() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_RESULTS}); |
| registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED); |
| addIntermediate("after-register"); |
| |
| BroadcastReceiver finish = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| gotReceive(RECEIVER_RESULTS, intent); |
| } |
| }; |
| |
| getContext().sendOrderedBroadcast( |
| makeBroadcastIntent(BROADCAST_REGISTERED), |
| null, finish, null, Activity.RESULT_CANCELED, null, null); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRegisteredBroadcastPermissionGranted() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_REG}); |
| registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); |
| addIntermediate("after-register"); |
| getContext().sendBroadcast( |
| makeBroadcastIntent(BROADCAST_REGISTERED), |
| PERMISSION_GRANTED); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRegisteredBroadcastPermissionDenied() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_RESULTS}); |
| registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); |
| addIntermediate("after-register"); |
| |
| BroadcastReceiver finish = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| gotReceive(RECEIVER_RESULTS, intent); |
| } |
| }; |
| |
| getContext().sendOrderedBroadcast( |
| makeBroadcastIntent(BROADCAST_REGISTERED), |
| PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, |
| null, null); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testLocalReceivePermissionGranted() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_LOCAL}); |
| getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL_GRANTED)); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testLocalReceivePermissionDenied() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_RESULTS}); |
| |
| BroadcastReceiver finish = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| gotReceive(RECEIVER_RESULTS, intent); |
| } |
| }; |
| |
| getContext().sendOrderedBroadcast( |
| makeBroadcastIntent(BROADCAST_LOCAL_DENIED), |
| null, finish, null, Activity.RESULT_CANCELED, |
| null, null); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testLocalBroadcastPermissionGranted() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_LOCAL}); |
| getContext().sendBroadcast( |
| makeBroadcastIntent(BROADCAST_LOCAL), |
| PERMISSION_GRANTED); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testLocalBroadcastPermissionDenied() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_RESULTS}); |
| |
| BroadcastReceiver finish = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| gotReceive(RECEIVER_RESULTS, intent); |
| } |
| }; |
| |
| getContext().sendOrderedBroadcast( |
| makeBroadcastIntent(BROADCAST_LOCAL), |
| PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, |
| null, null); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRemoteReceivePermissionGranted() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_REMOTE}); |
| getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE_GRANTED)); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRemoteReceivePermissionDenied() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_RESULTS}); |
| |
| BroadcastReceiver finish = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| gotReceive(RECEIVER_RESULTS, intent); |
| } |
| }; |
| |
| getContext().sendOrderedBroadcast( |
| makeBroadcastIntent(BROADCAST_REMOTE_DENIED), |
| null, finish, null, Activity.RESULT_CANCELED, |
| null, null); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRemoteBroadcastPermissionGranted() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_REMOTE}); |
| getContext().sendBroadcast( |
| makeBroadcastIntent(BROADCAST_REMOTE), |
| PERMISSION_GRANTED); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testRemoteBroadcastPermissionDenied() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_RESULTS}); |
| |
| BroadcastReceiver finish = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| gotReceive(RECEIVER_RESULTS, intent); |
| } |
| }; |
| |
| getContext().sendOrderedBroadcast( |
| makeBroadcastIntent(BROADCAST_REMOTE), |
| PERMISSION_DENIED, finish, null, Activity.RESULT_CANCELED, |
| null, null); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testReceiverCanNotRegister() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_LOCAL}); |
| getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_REGISTER)); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testReceiverCanNotBind() throws Exception { |
| setExpectedReceivers(new String[]{RECEIVER_LOCAL}); |
| getContext().sendBroadcast(makeBroadcastIntent(BROADCAST_FAIL_BIND)); |
| waitForResultOrThrow(BROADCAST_TIMEOUT); |
| } |
| |
| public void testLocalUnregisterTwice() throws Exception { |
| registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), null); |
| unregisterMyReceiverNoCheck(); |
| try { |
| unregisterMyReceiverNoCheck(); |
| fail("No exception thrown on second unregister"); |
| } catch (IllegalArgumentException e) { |
| Log.i("foo", "Unregister exception", e); |
| } |
| } |
| } |