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.server;
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.Handler;
25 import android.os.UserHandle;
26 
27 import com.google.common.collect.Lists;
28 import com.google.common.util.concurrent.AbstractFuture;
29 
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Future;
34 import java.util.concurrent.TimeUnit;
35 import java.util.concurrent.TimeoutException;
36 
37 /**
38  * {@link ContextWrapper} that can attach listeners for upcoming
39  * {@link Context#sendBroadcast(Intent)}.
40  */
41 public class BroadcastInterceptingContext extends ContextWrapper {
42     private static final String TAG = "WatchingContext";
43 
44     private final List<BroadcastInterceptor> mInterceptors = Lists.newArrayList();
45 
46     public class BroadcastInterceptor extends AbstractFuture<Intent> {
47         private final BroadcastReceiver mReceiver;
48         private final IntentFilter mFilter;
49 
BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter)50         public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter) {
51             mReceiver = receiver;
52             mFilter = filter;
53         }
54 
dispatchBroadcast(Intent intent)55         public boolean dispatchBroadcast(Intent intent) {
56             if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) {
57                 if (mReceiver != null) {
58                     final Context context = BroadcastInterceptingContext.this;
59                     mReceiver.onReceive(context, intent);
60                     return false;
61                 } else {
62                     set(intent);
63                     return true;
64                 }
65             } else {
66                 return false;
67             }
68         }
69 
70         @Override
get()71         public Intent get() throws InterruptedException, ExecutionException {
72             try {
73                 return get(5, TimeUnit.SECONDS);
74             } catch (TimeoutException e) {
75                 throw new RuntimeException(e);
76             }
77         }
78     }
79 
BroadcastInterceptingContext(Context base)80     public BroadcastInterceptingContext(Context base) {
81         super(base);
82     }
83 
nextBroadcastIntent(String action)84     public Future<Intent> nextBroadcastIntent(String action) {
85         return nextBroadcastIntent(new IntentFilter(action));
86     }
87 
nextBroadcastIntent(IntentFilter filter)88     public Future<Intent> nextBroadcastIntent(IntentFilter filter) {
89         final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter);
90         synchronized (mInterceptors) {
91             mInterceptors.add(interceptor);
92         }
93         return interceptor;
94     }
95 
96     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)97     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
98         synchronized (mInterceptors) {
99             mInterceptors.add(new BroadcastInterceptor(receiver, filter));
100         }
101         return null;
102     }
103 
104     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)105     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
106             String broadcastPermission, Handler scheduler) {
107         return registerReceiver(receiver, filter);
108     }
109 
110     @Override
unregisterReceiver(BroadcastReceiver receiver)111     public void unregisterReceiver(BroadcastReceiver receiver) {
112         synchronized (mInterceptors) {
113             final Iterator<BroadcastInterceptor> i = mInterceptors.iterator();
114             while (i.hasNext()) {
115                 final BroadcastInterceptor interceptor = i.next();
116                 if (receiver.equals(interceptor.mReceiver)) {
117                     i.remove();
118                 }
119             }
120         }
121     }
122 
123     @Override
sendBroadcast(Intent intent)124     public void sendBroadcast(Intent intent) {
125         synchronized (mInterceptors) {
126             final Iterator<BroadcastInterceptor> i = mInterceptors.iterator();
127             while (i.hasNext()) {
128                 final BroadcastInterceptor interceptor = i.next();
129                 if (interceptor.dispatchBroadcast(intent)) {
130                     i.remove();
131                 }
132             }
133         }
134     }
135 
136     @Override
sendBroadcast(Intent intent, String receiverPermission)137     public void sendBroadcast(Intent intent, String receiverPermission) {
138         sendBroadcast(intent);
139     }
140 
141     @Override
sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions)142     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
143         sendBroadcast(intent);
144     }
145 
146     @Override
sendBroadcastAsUser(Intent intent, UserHandle user)147     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
148         sendBroadcast(intent);
149     }
150 
151     @Override
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission)152     public void sendBroadcastAsUser(Intent intent, UserHandle user,
153             String receiverPermission) {
154         sendBroadcast(intent);
155     }
156 
157     @Override
sendStickyBroadcast(Intent intent)158     public void sendStickyBroadcast(Intent intent) {
159         sendBroadcast(intent);
160     }
161 
162     @Override
sendStickyBroadcastAsUser(Intent intent, UserHandle user)163     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
164         sendBroadcast(intent);
165     }
166 
167     @Override
removeStickyBroadcast(Intent intent)168     public void removeStickyBroadcast(Intent intent) {
169         // ignored
170     }
171 }
172