• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 com.android.internal.util.test;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.ContextWrapper;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.UserHandle;
27 
28 import java.util.ArrayList;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.concurrent.ExecutionException;
32 import java.util.concurrent.FutureTask;
33 import java.util.concurrent.TimeUnit;
34 import java.util.concurrent.TimeoutException;
35 
36 /**
37  * {@link ContextWrapper} that can attach listeners for upcoming
38  * {@link Context#sendBroadcast(Intent)}.
39  */
40 public class BroadcastInterceptingContext extends ContextWrapper {
41     private static final String TAG = "WatchingContext";
42 
43     private final List<BroadcastInterceptor> mInterceptors = new ArrayList<>();
44 
45     private boolean mUseRegisteredHandlers;
46 
47     public abstract class FutureIntent extends FutureTask<Intent> {
FutureIntent()48         public FutureIntent() {
49             super(
50                 () -> { throw new IllegalStateException("Cannot happen"); }
51             );
52         }
53 
assertNotReceived()54         public void assertNotReceived()
55                 throws InterruptedException, ExecutionException {
56             assertNotReceived(5, TimeUnit.SECONDS);
57         }
58 
assertNotReceived(long timeout, TimeUnit unit)59         public abstract void assertNotReceived(long timeout, TimeUnit unit)
60                 throws InterruptedException, ExecutionException;
61     }
62 
63     public class BroadcastInterceptor extends FutureIntent {
64         private final BroadcastReceiver mReceiver;
65         private final IntentFilter mFilter;
66         private final Handler mHandler;
67 
BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter, Handler handler)68         public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter,
69                 Handler handler) {
70             mReceiver = receiver;
71             mFilter = filter;
72             mHandler = mUseRegisteredHandlers ? handler : null;
73         }
74 
dispatchBroadcast(Intent intent)75         public boolean dispatchBroadcast(Intent intent) {
76             if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) {
77                 if (mReceiver != null) {
78                     final Context context = BroadcastInterceptingContext.this;
79                     if (mHandler == null) {
80                         mReceiver.onReceive(context, intent);
81                     } else {
82                         mHandler.post(() -> mReceiver.onReceive(context, intent));
83                     }
84                     return false;
85                 } else {
86                     set(intent);
87                     return true;
88                 }
89             } else {
90                 return false;
91             }
92         }
93 
94         @Override
get()95         public Intent get() throws InterruptedException, ExecutionException {
96             try {
97                 return get(5, TimeUnit.SECONDS);
98             } catch (TimeoutException e) {
99                 throw new RuntimeException(e);
100             }
101         }
102 
103         @Override
assertNotReceived()104         public void assertNotReceived()
105             throws InterruptedException, ExecutionException {
106             assertNotReceived(5, TimeUnit.SECONDS);
107         }
108 
assertNotReceived(long timeout, TimeUnit unit)109         public void assertNotReceived(long timeout, TimeUnit unit)
110                 throws InterruptedException, ExecutionException {
111             try {
112                 final Intent intent = get(timeout, unit);
113                 throw new AssertionError("Received intent: " + intent);
114             } catch (TimeoutException e) {
115             }
116         }
117     }
118 
BroadcastInterceptingContext(Context base)119     public BroadcastInterceptingContext(Context base) {
120         super(base);
121     }
122 
nextBroadcastIntent(String action)123     public FutureIntent nextBroadcastIntent(String action) {
124         return nextBroadcastIntent(new IntentFilter(action));
125     }
126 
nextBroadcastIntent(IntentFilter filter)127     public FutureIntent nextBroadcastIntent(IntentFilter filter) {
128         final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter, null);
129         synchronized (mInterceptors) {
130             mInterceptors.add(interceptor);
131         }
132         return interceptor;
133     }
134 
135     /**
136      * Whether to send broadcasts to registered handlers. By default, receivers are called
137      * synchronously by sendBroadcast. If this method is called with {@code true}, the receiver is
138      * instead called by a runnable posted to the Handler specified when the receiver was
139      * registered. This method applies only to future registrations, already-registered receivers
140      * are unaffected.
141      */
setUseRegisteredHandlers(boolean use)142     public void setUseRegisteredHandlers(boolean use) {
143         synchronized (mInterceptors) {
144             mUseRegisteredHandlers = use;
145         }
146     }
147 
148     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)149     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
150         return registerReceiver(receiver, filter, null, null, 0);
151     }
152 
153     /**
154      * Registers the specified {@code receiver} to listen for broadcasts that match the {@code
155      * filter} in the current process.
156      *
157      * <p>Since this method only listens for broadcasts in the current process, the provided {@code
158      * flags} are ignored; this method is primarily intended to allow receivers that register with
159      * flags to register in the current process during tests.
160      */
161     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags)162     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
163         return registerReceiver(receiver, filter, null, null, flags);
164     }
165 
166     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)167     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
168             String broadcastPermission, Handler scheduler) {
169         return registerReceiver(receiver, filter, broadcastPermission, scheduler, 0);
170     }
171 
172     /**
173      * Registers the specified {@code receiver} to listen for broadcasts that match the {@code
174      * filter} to run in the context of the specified {@code scheduler} in the current process.
175      *
176      * <p>Since this method only listens for broadcasts in the current process, the provided {@code
177      * flags} are ignored; this method is primarily intended to allow receivers that register with
178      * flags to register in the current process during tests.
179      */
180     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags)181     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
182             String broadcastPermission, Handler scheduler, int flags) {
183         synchronized (mInterceptors) {
184             mInterceptors.add(new BroadcastInterceptor(receiver, filter, scheduler));
185         }
186         return null;
187     }
188 
189     @Override
unregisterReceiver(BroadcastReceiver receiver)190     public void unregisterReceiver(BroadcastReceiver receiver) {
191         synchronized (mInterceptors) {
192             final Iterator<BroadcastInterceptor> i = mInterceptors.iterator();
193             while (i.hasNext()) {
194                 final BroadcastInterceptor interceptor = i.next();
195                 if (receiver.equals(interceptor.mReceiver)) {
196                     i.remove();
197                 }
198             }
199         }
200     }
201 
202     @Override
sendBroadcast(Intent intent)203     public void sendBroadcast(Intent intent) {
204         synchronized (mInterceptors) {
205             final Iterator<BroadcastInterceptor> i = mInterceptors.iterator();
206             while (i.hasNext()) {
207                 final BroadcastInterceptor interceptor = i.next();
208                 if (interceptor.dispatchBroadcast(intent)) {
209                     i.remove();
210                 }
211             }
212         }
213     }
214 
215     @Override
sendBroadcast(Intent intent, String receiverPermission)216     public void sendBroadcast(Intent intent, String receiverPermission) {
217         sendBroadcast(intent);
218     }
219 
220     @Override
sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)221     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
222         sendBroadcast(intent);
223     }
224 
225     @Override
sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions, Bundle options)226     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions,
227             Bundle options) {
228         sendBroadcast(intent);
229     }
230 
231     @Override
sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions)232     public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
233             String[] receiverPermissions) {
234         sendBroadcast(intent);
235     }
236 
237     @Override
sendBroadcastAsUser(Intent intent, UserHandle user)238     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
239         sendBroadcast(intent);
240     }
241 
242     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)243     public void sendBroadcastAsUser(Intent intent, UserHandle user,
244             String receiverPermission) {
245         sendBroadcast(intent);
246     }
247 
248     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options)249     public void sendBroadcastAsUser(Intent intent, UserHandle user,
250             String receiverPermission, Bundle options) {
251         sendBroadcast(intent);
252     }
253 
254     @Override
sendStickyBroadcast(Intent intent)255     public void sendStickyBroadcast(Intent intent) {
256         sendBroadcast(intent);
257     }
258 
259     @Override
sendStickyBroadcast(Intent intent, Bundle options)260     public void sendStickyBroadcast(Intent intent, Bundle options) {
261         sendBroadcast(intent);
262     }
263 
264     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user)265     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
266         sendBroadcast(intent);
267     }
268 
269     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options)270     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
271         sendBroadcast(intent);
272     }
273 
274     @Override
removeStickyBroadcast(Intent intent)275     public void removeStickyBroadcast(Intent intent) {
276         // ignored
277     }
278 }
279