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