1 /* 2 * Copyright (C) 2017 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 package android.app.cts.backgroundrestrictions; 17 18 import static junit.framework.Assert.assertFalse; 19 20 import static org.junit.Assert.assertTrue; 21 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.platform.test.annotations.AppModeFull; 27 import android.util.Log; 28 29 import androidx.test.InstrumentationRegistry; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import com.android.compatibility.common.util.AmUtils; 33 import com.android.compatibility.common.util.CddTest; 34 import com.android.compatibility.common.util.SystemUtil; 35 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import java.util.ArrayList; 40 import java.util.concurrent.CountDownLatch; 41 import java.util.concurrent.TimeUnit; 42 import java.util.concurrent.atomic.AtomicReference; 43 import java.util.function.BiConsumer; 44 import java.util.function.Consumer; 45 46 @RunWith(AndroidJUnit4.class) 47 public class BroadcastsTest { 48 private static final String TAG = "BroadcastsTest"; 49 50 private final int BROADCASTS_TIMEOUT_SECOND = 3 * 60; 51 getContext()52 private static Context getContext() { 53 return InstrumentationRegistry.getContext(); 54 } 55 56 /** 57 * Make sure "com.android.launcher.action.INSTALL_SHORTCUT" won't be delivered to a runtime 58 * receiver. 59 */ 60 @Test 61 @CddTest(requirement="3.5/C-0-6") testNonSupportedBroadcastsNotDelivered_runtimeReceiver()62 public void testNonSupportedBroadcastsNotDelivered_runtimeReceiver() throws Exception { 63 64 // Need a reference here to initialize it in a lambda. 65 final AtomicReference<BroadcastReceiver> receiverRef = new AtomicReference<>(); 66 67 testNonSupportedBroadcastsNotDelivered( 68 (filter, callback) -> { 69 final BroadcastReceiver receiver = new BroadcastReceiver() { 70 @Override 71 public void onReceive(Context context, Intent intent) { 72 callback.accept(intent); 73 } 74 }; 75 receiverRef.set(receiver); 76 77 getContext().registerReceiver(receiver, filter); 78 }, 79 (intent) -> {}, 80 () -> getContext().unregisterReceiver(receiverRef.get())); 81 } 82 83 /** 84 * Make sure "com.android.launcher.action.INSTALL_SHORTCUT" won't be delivered to a manifest 85 * receiver, even if an intent is targeted to the component. 86 */ 87 @AppModeFull(reason = "Instant apps don't get to run in the background.") 88 @Test 89 @CddTest(requirement="3.5/C-0-6") testNonSupportedBroadcastsNotDelivered_manifestReceiver()90 public void testNonSupportedBroadcastsNotDelivered_manifestReceiver() throws Exception { 91 // Need a reference here to initialize it in a lambda. 92 final AtomicReference<BroadcastReceiver> receiverRef = new AtomicReference<>(); 93 94 testNonSupportedBroadcastsNotDelivered( 95 (filter, callback) -> { 96 MyReceiver.setCallback((intent) -> callback.accept(intent)); 97 }, 98 (intent) -> intent.setComponent(MyReceiver.getComponent()), 99 () -> MyReceiver.clearCallback()); 100 } 101 testNonSupportedBroadcastsNotDelivered( BiConsumer<IntentFilter, Consumer<Intent>> receiverInitializer, Consumer<Intent> intentInitializer, Runnable receiverDeinitializer)102 private void testNonSupportedBroadcastsNotDelivered( 103 BiConsumer<IntentFilter, Consumer<Intent>> receiverInitializer, 104 Consumer<Intent> intentInitializer, 105 Runnable receiverDeinitializer) throws Exception { 106 107 AmUtils.waitForBroadcastIdle(); 108 109 // This broadcast should not be delivered. 110 final String[] UNSUPPORTED_BROADCASTS = new String[]{ 111 "com.android.launcher.action.INSTALL_SHORTCUT", 112 }; 113 // These broadcasts should be delivered. 114 final String[] SUPPORTED_BROADCASTS = new String[]{ 115 Intent.ACTION_VIEW, 116 Intent.ACTION_SEND, 117 }; 118 final String[][] ALL_BROADCASTS = new String[][]{ 119 UNSUPPORTED_BROADCASTS, 120 SUPPORTED_BROADCASTS, 121 }; 122 123 // GuardedBy receivedBroadcasts 124 final ArrayList<String> receivedBroadcasts = new ArrayList<>(); 125 126 final CountDownLatch latch = new CountDownLatch(SUPPORTED_BROADCASTS.length); 127 128 // Register a receiver for all the actions. 129 final IntentFilter filter = new IntentFilter(); 130 for (String[] list : ALL_BROADCASTS) { 131 for (String action : list) { 132 filter.addAction(action); 133 } 134 } 135 136 // This is what's called when a receiver receives an intent. 137 final Consumer<Intent> callbackHandler = (intent) -> { 138 Log.i(TAG, "Intent " + intent + " received."); 139 synchronized (receivedBroadcasts) { 140 receivedBroadcasts.add(intent.getAction()); 141 } 142 143 latch.countDown(); 144 }; 145 146 receiverInitializer.accept(filter, callbackHandler); 147 try { 148 // Send all broadcasts one by one. 149 for (String[] list : ALL_BROADCASTS) { 150 for (String action : list) { 151 final Intent intent = new Intent(action) 152 .setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 153 154 intentInitializer.accept(intent); 155 156 getContext().sendBroadcast(intent); 157 } 158 } 159 assertTrue(latch.await(BROADCASTS_TIMEOUT_SECOND, TimeUnit.SECONDS)); 160 161 final String history = 162 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 163 "dumpsys activity broadcasts history"); 164 Log.v(TAG, "Broadcast history:\n"); 165 for (String line : history.split("\n")) { 166 Log.v(TAG, line); 167 } 168 169 170 // Verify the received lists. 171 // The supported ones should be delivered, and show up in the history. 172 // The unsupported should not. 173 synchronized (receivedBroadcasts) { 174 for (String action : SUPPORTED_BROADCASTS) { 175 assertTrue(receivedBroadcasts.contains(action)); 176 assertTrue(history.contains(action)); 177 } 178 179 for (String action : UNSUPPORTED_BROADCASTS) { 180 assertFalse(receivedBroadcasts.contains(action)); 181 assertFalse(history.contains(action)); 182 } 183 } 184 185 } finally { 186 receiverDeinitializer.run(); 187 } 188 } 189 } 190