19599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey/* 29599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project 39599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * 49599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 59599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * you may not use this file except in compliance with the License. 69599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * You may obtain a copy of the License at 79599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * 89599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 99599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * 109599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 119599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 129599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * See the License for the specific language governing permissions and 149599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * limitations under the License. 159599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey */ 169599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 179599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeypackage com.android.server; 189599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 199599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport android.content.BroadcastReceiver; 209599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport android.content.Context; 219599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport android.content.ContextWrapper; 229599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport android.content.Intent; 239599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport android.content.IntentFilter; 249599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport android.os.Handler; 259599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 269599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport com.google.common.collect.Lists; 279599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport com.google.common.util.concurrent.AbstractFuture; 289599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 299599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport java.util.Iterator; 309599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport java.util.List; 31b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.concurrent.ExecutionException; 329599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport java.util.concurrent.Future; 33b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.concurrent.TimeUnit; 34b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.concurrent.TimeoutException; 359599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 369599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey/** 379599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * {@link ContextWrapper} that can attach listeners for upcoming 389599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * {@link Context#sendBroadcast(Intent)}. 399599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey */ 409599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeypublic class BroadcastInterceptingContext extends ContextWrapper { 419599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private static final String TAG = "WatchingContext"; 429599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 439599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private final List<BroadcastInterceptor> mInterceptors = Lists.newArrayList(); 449599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 459599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public class BroadcastInterceptor extends AbstractFuture<Intent> { 469599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private final BroadcastReceiver mReceiver; 479599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private final IntentFilter mFilter; 489599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 499599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter) { 509599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mReceiver = receiver; 519599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mFilter = filter; 529599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 539599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 549599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public boolean dispatchBroadcast(Intent intent) { 559599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) { 569599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (mReceiver != null) { 579599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final Context context = BroadcastInterceptingContext.this; 589599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mReceiver.onReceive(context, intent); 599599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return false; 609599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } else { 619599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey set(intent); 629599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return true; 639599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 649599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } else { 659599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return false; 669599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 679599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 68b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 69b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey @Override 70b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public Intent get() throws InterruptedException, ExecutionException { 71b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey try { 72b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return get(5, TimeUnit.SECONDS); 73b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } catch (TimeoutException e) { 74b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey throw new RuntimeException(e); 75b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 76b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 779599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 789599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 799599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public BroadcastInterceptingContext(Context base) { 809599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey super(base); 819599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 829599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 839599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Future<Intent> nextBroadcastIntent(String action) { 849599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return nextBroadcastIntent(new IntentFilter(action)); 859599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 869599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 879599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Future<Intent> nextBroadcastIntent(IntentFilter filter) { 889599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter); 899599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 909599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mInterceptors.add(interceptor); 919599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 929599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return interceptor; 939599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 949599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 959599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 969599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 979599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 989599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mInterceptors.add(new BroadcastInterceptor(receiver, filter)); 999599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1009599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return null; 1019599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1029599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1039599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1049599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 1059599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey String broadcastPermission, Handler scheduler) { 1069599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return registerReceiver(receiver, filter); 1079599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1089599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1099599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1109599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void unregisterReceiver(BroadcastReceiver receiver) { 1119599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 1129599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final Iterator<BroadcastInterceptor> i = mInterceptors.iterator(); 1139599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey while (i.hasNext()) { 1149599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final BroadcastInterceptor interceptor = i.next(); 1159599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (receiver.equals(interceptor.mReceiver)) { 1169599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey i.remove(); 1179599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1189599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1199599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1209599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1219599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1229599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1239599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void sendBroadcast(Intent intent) { 1249599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 1259599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final Iterator<BroadcastInterceptor> i = mInterceptors.iterator(); 1269599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey while (i.hasNext()) { 1279599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final BroadcastInterceptor interceptor = i.next(); 1289599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (interceptor.dispatchBroadcast(intent)) { 1299599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey i.remove(); 1309599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1319599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1329599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1339599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1349599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1359599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1369599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void sendStickyBroadcast(Intent intent) { 1379599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey sendBroadcast(intent); 1389599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1399599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1409599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 141b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public void sendBroadcast(Intent intent, String receiverPermission) { 142b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey sendBroadcast(intent); 143b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 144b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 145b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey @Override 1469599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void removeStickyBroadcast(Intent intent) { 1479599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey // ignored 1489599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1499599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey} 150