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; 253671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkeyimport android.os.UserHandle; 269599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 279599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport com.google.common.collect.Lists; 289599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport com.google.common.util.concurrent.AbstractFuture; 299599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 309599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport java.util.Iterator; 319599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport java.util.List; 32b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.concurrent.ExecutionException; 339599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeyimport java.util.concurrent.Future; 34b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.concurrent.TimeUnit; 35b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.concurrent.TimeoutException; 369599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 379599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey/** 389599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * {@link ContextWrapper} that can attach listeners for upcoming 399599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey * {@link Context#sendBroadcast(Intent)}. 409599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey */ 419599cc5f21152860af9d18015b1398b50743da76Jeff Sharkeypublic class BroadcastInterceptingContext extends ContextWrapper { 429599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private static final String TAG = "WatchingContext"; 439599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 449599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private final List<BroadcastInterceptor> mInterceptors = Lists.newArrayList(); 459599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 469599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public class BroadcastInterceptor extends AbstractFuture<Intent> { 479599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private final BroadcastReceiver mReceiver; 489599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey private final IntentFilter mFilter; 499599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 509599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter) { 519599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mReceiver = receiver; 529599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mFilter = filter; 539599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 549599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 559599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public boolean dispatchBroadcast(Intent intent) { 569599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) { 579599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (mReceiver != null) { 589599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final Context context = BroadcastInterceptingContext.this; 599599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mReceiver.onReceive(context, intent); 609599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return false; 619599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } else { 629599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey set(intent); 639599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return true; 649599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 659599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } else { 669599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return false; 679599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 689599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 69b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 70b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey @Override 71b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public Intent get() throws InterruptedException, ExecutionException { 72b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey try { 73b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey return get(5, TimeUnit.SECONDS); 74b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } catch (TimeoutException e) { 75b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey throw new RuntimeException(e); 76b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 77b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 789599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 799599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 809599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public BroadcastInterceptingContext(Context base) { 819599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey super(base); 829599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 839599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 849599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Future<Intent> nextBroadcastIntent(String action) { 859599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return nextBroadcastIntent(new IntentFilter(action)); 869599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 879599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 889599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Future<Intent> nextBroadcastIntent(IntentFilter filter) { 899599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter); 909599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 919599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mInterceptors.add(interceptor); 929599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 939599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return interceptor; 949599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 959599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 969599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 979599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 989599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 999599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey mInterceptors.add(new BroadcastInterceptor(receiver, filter)); 1009599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1019599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return null; 1029599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1039599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1049599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1059599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 1069599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey String broadcastPermission, Handler scheduler) { 1079599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey return registerReceiver(receiver, filter); 1089599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1099599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1109599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1119599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void unregisterReceiver(BroadcastReceiver receiver) { 1129599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 1139599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final Iterator<BroadcastInterceptor> i = mInterceptors.iterator(); 1149599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey while (i.hasNext()) { 1159599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final BroadcastInterceptor interceptor = i.next(); 1169599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (receiver.equals(interceptor.mReceiver)) { 1179599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey i.remove(); 1189599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1199599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1209599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1219599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1229599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1239599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1249599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void sendBroadcast(Intent intent) { 1259599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey synchronized (mInterceptors) { 1269599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final Iterator<BroadcastInterceptor> i = mInterceptors.iterator(); 1279599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey while (i.hasNext()) { 1289599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey final BroadcastInterceptor interceptor = i.next(); 1299599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey if (interceptor.dispatchBroadcast(intent)) { 1309599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey i.remove(); 1319599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1329599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1339599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1349599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1359599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1369599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1373671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey public void sendBroadcast(Intent intent, String receiverPermission) { 1383671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey sendBroadcast(intent); 1393671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey } 1403671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey 1413671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey @Override 1423671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey public void sendBroadcastAsUser(Intent intent, UserHandle user) { 1433671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey sendBroadcast(intent); 1443671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey } 1453671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey 1463671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey @Override 1473671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey public void sendBroadcastAsUser(Intent intent, UserHandle user, 1483671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey String receiverPermission) { 1493671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey sendBroadcast(intent); 1503671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey } 1513671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey 1523671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey @Override 1539599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void sendStickyBroadcast(Intent intent) { 1549599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey sendBroadcast(intent); 1559599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1569599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey 1579599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey @Override 1583671b1e910e4d297bebcd3ceaa2682bfb4b1f4a1Jeff Sharkey public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { 159b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey sendBroadcast(intent); 160b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 161b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 162b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey @Override 1639599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey public void removeStickyBroadcast(Intent intent) { 1649599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey // ignored 1659599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey } 1669599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey} 167