13083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn/*
23083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
33083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn *
43083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
53083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * you may not use this file except in compliance with the License.
63083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * You may obtain a copy of the License at
73083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn *
83083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
93083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn *
103083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
113083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
123083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * See the License for the specific language governing permissions and
143083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * limitations under the License.
153083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn */
163083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
173083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornpackage android.support.v4.content;
183083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
193083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport java.util.ArrayList;
203083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport java.util.HashMap;
213083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport java.util.Set;
223083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
233083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.content.BroadcastReceiver;
243083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.content.Context;
253083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.content.Intent;
263083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.content.IntentFilter;
273083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.net.Uri;
283083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.os.Handler;
293083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.os.Message;
303083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornimport android.util.Log;
313083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
323083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn/**
333083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * Helper to register for and send broadcasts of Intents to local objects
343083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * within your process.  This is has a number of advantages over sending
353083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * global broadcasts with {@link android.content.Context#sendBroadcast}:
363083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * <ul>
373083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * <li> You know that the data you are broadcasting won't leave your app, so
383083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * don't need to worry about leaking private data.
393083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * <li> It is not possible for other applications to send these broadcasts to
403083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * your app, so you don't need to worry about having security holes they can
413083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * exploit.
423083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * <li> It is more efficient than sending a global broadcast through the
433083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * system.
443083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn * </ul>
453083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn */
463083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackbornpublic class LocalBroadcastManager {
473083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private static class ReceiverRecord {
483083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        final IntentFilter filter;
493083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        final BroadcastReceiver receiver;
503083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        boolean broadcasting;
513083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
523083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
533083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            filter = _filter;
543083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            receiver = _receiver;
553083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
563083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
573083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        @Override
583083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        public String toString() {
593083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            StringBuilder builder = new StringBuilder(128);
603083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            builder.append("Receiver{");
613083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            builder.append(receiver);
623083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            builder.append(" filter=");
633083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            builder.append(filter);
643083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            builder.append("}");
653083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            return builder.toString();
663083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
673083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
683083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
693083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private static class BroadcastRecord {
703083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        final Intent intent;
713083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        final ArrayList<ReceiverRecord> receivers;
723083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
733083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {
743083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            intent = _intent;
753083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            receivers = _receivers;
763083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
773083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
783083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
793083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private static final String TAG = "LocalBroadcastManager";
803083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private static final boolean DEBUG = false;
813083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
823083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private final Context mAppContext;
833083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
843083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
853083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            = new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
863083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private final HashMap<String, ArrayList<ReceiverRecord>> mActions
873083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            = new HashMap<String, ArrayList<ReceiverRecord>>();
883083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
893083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private final ArrayList<BroadcastRecord> mPendingBroadcasts
903083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            = new ArrayList<BroadcastRecord>();
913083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
923083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    static final int MSG_EXEC_PENDING_BROADCASTS = 1;
933083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
943083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private final Handler mHandler;
953083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
963083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private static final Object mLock = new Object();
973083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private static LocalBroadcastManager mInstance;
983083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
993083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    public static LocalBroadcastManager getInstance(Context context) {
1003083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        synchronized (mLock) {
1013083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            if (mInstance == null) {
1023083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                mInstance = new LocalBroadcastManager(context.getApplicationContext());
1033083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
1043083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            return mInstance;
1053083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
1063083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
1073083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
1083083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private LocalBroadcastManager(Context context) {
1093083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        mAppContext = context;
1103083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        mHandler = new Handler(context.getMainLooper()) {
1113083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
1123083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            @Override
1133083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            public void handleMessage(Message msg) {
1143083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                switch (msg.what) {
1153083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    case MSG_EXEC_PENDING_BROADCASTS:
1163083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        executePendingBroadcasts();
1173083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        break;
1183083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    default:
1193083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        super.handleMessage(msg);
1203083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
1213083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
1223083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        };
1233083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
1243083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
1253083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    /**
1263083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * Register a receive for any local broadcasts that match the given IntentFilter.
1273083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *
1283083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @param receiver The BroadcastReceiver to handle the broadcast.
1293083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @param filter Selects the Intent broadcasts to be received.
1303083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *
1313083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @see #unregisterReceiver
1323083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     */
1333083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
1343083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        synchronized (mReceivers) {
1353083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            ReceiverRecord entry = new ReceiverRecord(filter, receiver);
1363083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            ArrayList<IntentFilter> filters = mReceivers.get(receiver);
1373083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            if (filters == null) {
1383083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                filters = new ArrayList<IntentFilter>(1);
1393083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                mReceivers.put(receiver, filters);
1403083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
1413083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            filters.add(filter);
1423083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            for (int i=0; i<filter.countActions(); i++) {
1433083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                String action = filter.getAction(i);
1443083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                ArrayList<ReceiverRecord> entries = mActions.get(action);
1453083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                if (entries == null) {
1463083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    entries = new ArrayList<ReceiverRecord>(1);
1473083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    mActions.put(action, entries);
1483083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
1493083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                entries.add(entry);
1503083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
1513083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
1523083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
1533083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
1543083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    /**
1553083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * Unregister a previously registered BroadcastReceiver.  <em>All</em>
1563083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * filters that have been registered for this BroadcastReceiver will be
1573083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * removed.
1583083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *
1593083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @param receiver The BroadcastReceiver to unregister.
1603083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *
1613083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @see #registerReceiver
1623083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     */
1633083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    public void unregisterReceiver(BroadcastReceiver receiver) {
1643083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        synchronized (mReceivers) {
1653083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
1663083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            if (filters == null) {
1673083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                return;
1683083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
1693083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            for (int i=0; i<filters.size(); i++) {
1703083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                IntentFilter filter = filters.get(i);
1713083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                for (int j=0; j<filter.countActions(); j++) {
1723083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    String action = filter.getAction(j);
1733083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    ArrayList<ReceiverRecord> receivers = mActions.get(action);
1743083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    if (receivers != null) {
1753083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        for (int k=0; k<receivers.size(); k++) {
1763083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            if (receivers.get(k).receiver == receiver) {
1773083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                receivers.remove(k);
1783083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                k--;
1793083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            }
1803083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        }
1813083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        if (receivers.size() <= 0) {
1823083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            mActions.remove(action);
1833083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        }
1843083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    }
1853083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
1863083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
1873083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
1883083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
1893083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
1903083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    /**
1913083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * Broadcast the given intent to all interested BroadcastReceivers.  This
1923083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * call is asynchronous; it returns immediately, and you will continue
1933083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * executing while the receivers are run.
1943083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *
1953083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @param intent The Intent to broadcast; all receivers matching this
1963083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *     Intent will receive the broadcast.
1973083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     *
1983083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * @see #registerReceiver
1993083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     */
2003083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    public boolean sendBroadcast(Intent intent) {
2013083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        synchronized (mReceivers) {
2023083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            final String action = intent.getAction();
2033083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            final String type = intent.resolveTypeIfNeeded(
2043083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    mAppContext.getContentResolver());
2053083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            final Uri data = intent.getData();
2063083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            final String scheme = intent.getScheme();
2073083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            final Set<String> categories = intent.getCategories();
2083083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2093083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            final boolean debug = DEBUG ||
2103083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
2113083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            if (debug) Log.v(
2123083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    TAG, "Resolving type " + type + " scheme " + scheme
2133083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    + " of intent " + intent);
2143083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2153083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
2163083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            if (entries != null) {
2173083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                if (debug) Log.v(TAG, "Action list: " + entries);
2183083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2193083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                ArrayList<ReceiverRecord> receivers = null;
2203083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                for (int i=0; i<entries.size(); i++) {
2213083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    ReceiverRecord receiver = entries.get(i);
2223083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    if (debug) Log.v(TAG, "Matching against filter " + receiver.filter);
2233083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2243083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    if (receiver.broadcasting) {
2253083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        if (debug) {
2263083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            Log.v(TAG, "  Filter's target already added");
2273083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        }
2283083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        continue;
2293083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    }
2303083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2313083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    int match = receiver.filter.match(action, type, scheme, data,
2323083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            categories, "LocalBroadcastManager");
2333083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    if (match >= 0) {
2343083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        if (debug) Log.v(TAG, "  Filter matched!  match=0x" +
2353083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                Integer.toHexString(match));
2363083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        if (receivers == null) {
2373083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            receivers = new ArrayList<ReceiverRecord>();
2383083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        }
2393083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        receivers.add(receiver);
2403083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        receiver.broadcasting = true;
2413083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    } else {
2423083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        if (debug) {
2433083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            String reason;
2443083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            switch (match) {
2453083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
2463083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
2473083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
2483083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
2493083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                                default: reason = "unknown reason"; break;
2503083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            }
2513083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                            Log.v(TAG, "  Filter did not match: " + reason);
2523083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        }
2533083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    }
2543083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
2553083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2563083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                if (receivers != null) {
2573083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    for (int i=0; i<receivers.size(); i++) {
2583083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        receivers.get(i).broadcasting = false;
2593083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    }
2603083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
2613083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
2623083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                        mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
2633083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    }
2643083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    return true;
2653083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
2663083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
2673083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
2683083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        return false;
2693083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
2703083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2713083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    /**
2723083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * Like {@link #sendBroadcast(Intent)}, but if there are any receivers for
2733083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * the Intent this function will block and immediately dispatch them before
2743083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     * returning.
2753083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn     */
2763083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    public void sendBroadcastSync(Intent intent) {
2773083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        if (sendBroadcast(intent)) {
2783083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            executePendingBroadcasts();
2793083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
2803083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
2813083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn
2823083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    private void executePendingBroadcasts() {
2833083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        while (true) {
2843083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            BroadcastRecord[] brs = null;
2853083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            synchronized (mReceivers) {
2863083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                final int N = mPendingBroadcasts.size();
2873083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                if (N <= 0) {
2883083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    return;
2893083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
2903083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                brs = new BroadcastRecord[N];
2913083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                mPendingBroadcasts.toArray(brs);
2923083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                mPendingBroadcasts.clear();
2933083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
2943083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            for (int i=0; i<brs.length; i++) {
2953083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                BroadcastRecord br = brs[i];
2963083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                for (int j=0; j<br.receivers.size(); j++) {
2973083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                    br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
2983083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn                }
2993083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn            }
3003083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn        }
3013083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn    }
3023083afddf1baabb57e801d2aa7d9c59e8b1e1c19Dianne Hackborn}
303