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