19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 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 Projectimport java.util.HashMap;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Takes care of the grunt work of maintaining a list of remote interfaces,
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * typically for the use of performing callbacks from a
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Service} to its clients.  In particular, this:
257b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project *
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Keeps track of a set of registered {@link IInterface} callbacks,
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * taking care to identify them through their underlying unique {@link IBinder}
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (by calling {@link IInterface#asBinder IInterface.asBinder()}.
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Attaches a {@link IBinder.DeathRecipient IBinder.DeathRecipient} to
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * each registered interface, so that it can be cleaned out of the list if its
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * process goes away.
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Performs locking of the underlying list of interfaces to deal with
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multithreaded incoming calls, and a thread-safe way to iterate over a
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * snapshot of the list without holding its lock.
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
377b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project *
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>To use this class, simply create a single instance along with your
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * service, and call its {@link #register} and {@link #unregister} methods
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as client register and unregister with your service.  To call back on to
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the registered clients, use {@link #beginBroadcast},
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getBroadcastItem}, and {@link #finishBroadcast}.
437b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If a registered callback's process goes away, this class will take
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * care of automatically removing it from the list.  If you want to do
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * additional work in this situation, you can create a subclass that
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implements the {@link #onCallbackDied} method.
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class RemoteCallbackList<E extends IInterface> {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ HashMap<IBinder, Callback> mCallbacks
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, Callback>();
52231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private Object[] mActiveBroadcast;
53b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn    private int mBroadcastCount = -1;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mKilled = false;
557b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Callback implements IBinder.DeathRecipient {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final E mCallback;
58231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Object mCookie;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Callback(E callback, Object cookie) {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCallback = callback;
62231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCookie = cookie;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
647b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mCallbacks) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCallbacks.remove(mCallback.asBinder());
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
69231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            onCallbackDied(mCallback, mCookie);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
727b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
74231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Simple version of {@link RemoteCallbackList#register(E, Object)}
75231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that does not take a cookie object.
76231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
77231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean register(E callback) {
78231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return register(callback, null);
79231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
80231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add a new callback to the list.  This callback will remain in the list
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * until a corresponding call to {@link #unregister} or its hosting process
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * goes away.  If the callback was already registered (determined by
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * checking to see if the {@link IInterface#asBinder callback.asBinder()}
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * object is already in the list), then it will be left as-is.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registrations are not counted; a single call to {@link #unregister}
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will remove a callback after any number calls to register it.
897b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param callback The callback interface to be added to the list.  Must
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not be null -- passing null here will cause a NullPointerException.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Most services will want to check for null before calling this with
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * an object given from a client, so that clients can't crash the
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * service with bad data.
957b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
96231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param cookie Optional additional data to be associated with this
97231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * callback.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true if the callback was successfully added to the list.
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns false if it was not added, either because {@link #kill} had
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * previously been called or the callback's process has gone away.
1027b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #unregister
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #kill
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #onCallbackDied
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean register(E callback, Object cookie) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mKilled) {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IBinder binder = callback.asBinder();
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Callback cb = new Callback(callback, cookie);
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                binder.linkToDeath(cb, 0);
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCallbacks.put(binder, cb);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1237b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove from the list a callback that was previously added with
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #register}.  This uses the
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link IInterface#asBinder callback.asBinder()} object to correctly
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * find the previous registration.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registrations are not counted; a single unregister call will remove
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a callback after any number calls to {@link #register} for it.
1317b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param callback The callback to be removed from the list.  Passing
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null here will cause a NullPointerException, so you will generally want
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to check for null before calling.
1357b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true if the callback was found and unregistered.  Returns
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * false if the given callback was not found on the list.
1387b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #register
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean unregister(E callback) {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Callback cb = mCallbacks.remove(callback.asBinder());
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cb != null) {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cb.mCallback.asBinder().unlinkToDeath(cb, 0);
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1517b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disable this callback list.  All registered callbacks are unregistered,
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and the list is disabled so that future calls to {@link #register} will
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fail.  This should be used when a Service is stopping, to prevent clients
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from registering callbacks after it is stopped.
1577b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #register
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void kill() {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Callback cb : mCallbacks.values()) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cb.mCallback.asBinder().unlinkToDeath(cb, 0);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCallbacks.clear();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKilled = true;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1697b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Old version of {@link #onCallbackDied(E, Object)} that
172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * does not provide a cookie.
173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void onCallbackDied(E callback) {
175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the process hosting a callback in the list has gone away.
179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * The default implementation calls {@link #onCallbackDied(E)}
180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * for backwards compatibility.
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param callback The callback whose process has died.  Note that, since
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * its process has died, you can not make any calls on to this interface.
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * You can, however, retrieve its IBinder and compare it with another
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * IBinder to see if it is the same object.
186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param cookie The cookie object original provided to
187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * {@link #register(E, Object)}.
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #register
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void onCallbackDied(E callback, Object cookie) {
192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        onCallbackDied(callback);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1947b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prepare to start making calls to the currently registered callbacks.
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This creates a copy of the callback list, which you can retrieve items
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from using {@link #getBroadcastItem}.  Note that only one broadcast can
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be active at a time, so you must be sure to always call this from the
200b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn     * same thread (usually by scheduling with {@link Handler}) or
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * do your own synchronization.  You must call {@link #finishBroadcast}
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when done.
2037b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>A typical loop delivering a broadcast looks like this:
2057b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
207b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn     * int i = callbacks.beginBroadcast();
208dace230043314d6fab1c5ced4b031eaccd814c25Dianne Hackborn     * while (i &gt; 0) {
209b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn     *     i--;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     try {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         callbacks.getBroadcastItem(i).somethingHappened();
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     } catch (RemoteException e) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         // The RemoteCallbackList will take care of removing
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         // the dead object for us.
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * callbacks.finishBroadcast();</pre>
2187b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns the number of callbacks in the broadcast, to be used
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with {@link #getBroadcastItem} to determine the range of indices you
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can supply.
2227b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getBroadcastItem
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #finishBroadcast
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int beginBroadcast() {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
228b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            if (mBroadcastCount > 0) {
229b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                throw new IllegalStateException(
230b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                        "beginBroadcast() called while already in a broadcast");
231b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            }
232b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn
233b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            final int N = mBroadcastCount = mCallbacks.size();
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (N <= 0) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Object[] active = mActiveBroadcast;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (active == null || active.length < N) {
239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveBroadcast = active = new Object[N];
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int i=0;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Callback cb : mCallbacks.values()) {
243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                active[i++] = cb;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
245105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return i;
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2487b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve an item in the active broadcast that was previously started
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with {@link #beginBroadcast}.  This can <em>only</em> be called after
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the broadcast is started, and its data is no longer valid after
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * calling {@link #finishBroadcast}.
2547b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that it is possible for the process of one of the returned
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * callbacks to go away before you call it, so you will need to catch
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link RemoteException} when calling on to the returned object.
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The callback list itself, however, will take care of unregistering
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * these objects once it detects that it is no longer valid, so you can
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * handle such an exception by simply ignoring it.
2617b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param index Which of the registered callbacks you would like to
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * retrieve.  Ranges from 0 to 1-{@link #beginBroadcast}.
2647b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns the callback interface that you can call.  This will
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * always be non-null.
2677b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #beginBroadcast
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public E getBroadcastItem(int index) {
271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return ((Callback)mActiveBroadcast[index]).mCallback;
272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
273231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve the cookie associated with the item
276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * returned by {@link #getBroadcastItem(int)}.
277231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     *
278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @see #getBroadcastItem
279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public Object getBroadcastCookie(int index) {
281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return ((Callback)mActiveBroadcast[index]).mCookie;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2837b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clean up the state of a broadcast previously initiated by calling
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #beginBroadcast}.  This must always be called when you are done
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with a broadcast.
2887b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #beginBroadcast
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishBroadcast() {
292b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        if (mBroadcastCount < 0) {
293b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            throw new IllegalStateException(
294b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                    "finishBroadcast() called outside of a broadcast");
295b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        }
296b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn
297231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Object[] active = mActiveBroadcast;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (active != null) {
299b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            final int N = mBroadcastCount;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                active[i] = null;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
304b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn
305b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn        mBroadcastCount = -1;
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3071cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3081cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    /**
3091cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * Returns the number of registered callbacks. Note that the number of registered
3101cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * callbacks may differ from the value returned by {@link #beginBroadcast()} since
3111cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * the former returns the number of callbacks registered at the time of the call
3121cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * and the second the number of callback to which the broadcast will be delivered.
3131cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * <p>
3141cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * This function is useful to decide whether to schedule a broadcast if this
3151cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * requires doing some work which otherwise would not be performed.
3161cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * </p>
3171cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     *
3181cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * @return The size.
3191cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     */
3201cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    public int getRegisteredCallbackCount() {
3211cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        synchronized (mCallbacks) {
3221cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            if (mKilled) {
3231cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov                return 0;
3241cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            }
3251cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            return mCallbacks.size();
3261cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3271cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
329