19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** @hide */
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Broadcaster
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Broadcaster()
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  Sign up for notifications about something.
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  When this broadcaster pushes a message with senderWhat in the what field,
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  target will be sent a copy of that message with targetWhat in the what field.
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void request(int senderWhat, Handler target, int targetWhat)
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Registration r = null;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mReg == null) {
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r = new Registration();
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.senderWhat = senderWhat;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.targets = new Handler[1];
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.targetWhats = new int[1];
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.targets[0] = target;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.targetWhats[0] = targetWhat;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mReg = r;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.next = r;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.prev = r;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // find its place in the map
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Registration start = mReg;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r = start;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (r.senderWhat >= senderWhat) {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r = r.next;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (r != start);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int n;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (r.senderWhat != senderWhat) {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we didn't find a senderWhat match, but r is right
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // after where it goes
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Registration reg = new Registration();
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    reg.senderWhat = senderWhat;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    reg.targets = new Handler[1];
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    reg.targetWhats = new int[1];
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    reg.next = r;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    reg.prev = r.prev;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r.prev.next = reg;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r.prev = reg;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (r == mReg && r.senderWhat > reg.senderWhat) {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mReg = reg;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r = reg;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    n = 0;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    n = r.targets.length;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Handler[] oldTargets = r.targets;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int[] oldWhats = r.targetWhats;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // check for duplicates, and don't do it if we are dup.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<n; i++) {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (oldTargets[i] == target && oldWhats[i] == targetWhat) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            return;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r.targets = new Handler[n+1];
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.arraycopy(oldTargets, 0, r.targets, 0, n);
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r.targetWhats = new int[n+1];
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.arraycopy(oldWhats, 0, r.targetWhats, 0, n);
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.targets[n] = target;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r.targetWhats[n] = targetWhat;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Unregister for notifications for this senderWhat/target/targetWhat tuple.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void cancelRequest(int senderWhat, Handler target, int targetWhat)
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Registration start = mReg;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Registration r = start;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (r == null) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            do {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (r.senderWhat >= senderWhat) {
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r = r.next;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } while (r != start);
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (r.senderWhat == senderWhat) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Handler[] targets = r.targets;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int[] whats = r.targetWhats;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int oldLen = targets.length;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0; i<oldLen; i++) {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (targets[i] == target && whats[i] == targetWhat) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        r.targets = new Handler[oldLen-1];
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        r.targetWhats = new int[oldLen-1];
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (i > 0) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.arraycopy(targets, 0, r.targets, 0, i);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.arraycopy(whats, 0, r.targetWhats, 0, i);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int remainingLen = oldLen-i-1;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (remainingLen != 0) {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.arraycopy(targets, i+1, r.targets, i,
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    remainingLen);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.arraycopy(whats, i+1, r.targetWhats, i,
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    remainingLen);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For debugging purposes, print the registrations to System.out
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dumpRegistrations()
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Registration start = mReg;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.out.println("Broadcaster " + this + " {");
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (start != null) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Registration r = start;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.out.println("    senderWhat=" + r.senderWhat);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int n = r.targets.length;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<n; i++) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        System.out.println("        [" + r.targetWhats[i]
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        + "] " + r.targets[i]);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r = r.next;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (r != start);
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            System.out.println("}");
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Send out msg.  Anyone who has registered via the request() method will be
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * sent the message.
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void broadcast(Message msg)
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        	if (mReg == null) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        		return;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        	}
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int senderWhat = msg.what;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Registration start = mReg;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Registration r = start;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            do {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (r.senderWhat >= senderWhat) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                r = r.next;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } while (r != start);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (r.senderWhat == senderWhat) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Handler[] targets = r.targets;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int[] whats = r.targetWhats;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int n = targets.length;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0; i<n; i++) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Handler target = targets[i];
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Message m = Message.obtain();
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    m.copyFrom(msg);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    m.what = whats[i];
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    target.sendMessage(m);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class Registration
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Registration next;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Registration prev;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int senderWhat;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Handler[] targets;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] targetWhats;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Registration mReg;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
213