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
19390517be2d60dd6e6264150c190c372d89bb331aDianne Hackbornimport android.util.ArrayMap;
2018a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasaniimport android.util.Slog;
21390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn
22ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukuiimport java.io.PrintWriter;
23ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Suslaimport java.util.function.Consumer;
24ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Takes care of the grunt work of maintaining a list of remote interfaces,
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * typically for the use of performing callbacks from a
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.app.Service} to its clients.  In particular, this:
297b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project *
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Keeps track of a set of registered {@link IInterface} callbacks,
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * taking care to identify them through their underlying unique {@link IBinder}
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (by calling {@link IInterface#asBinder IInterface.asBinder()}.
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Attaches a {@link IBinder.DeathRecipient IBinder.DeathRecipient} to
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * each registered interface, so that it can be cleaned out of the list if its
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * process goes away.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> Performs locking of the underlying list of interfaces to deal with
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * multithreaded incoming calls, and a thread-safe way to iterate over a
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * snapshot of the list without holding its lock.
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
417b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project *
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>To use this class, simply create a single instance along with your
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * service, and call its {@link #register} and {@link #unregister} methods
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as client register and unregister with your service.  To call back on to
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the registered clients, use {@link #beginBroadcast},
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getBroadcastItem}, and {@link #finishBroadcast}.
477b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project *
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If a registered callback's process goes away, this class will take
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * care of automatically removing it from the list.  If you want to do
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * additional work in this situation, you can create a subclass that
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implements the {@link #onCallbackDied} method.
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class RemoteCallbackList<E extends IInterface> {
5418a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani    private static final String TAG = "RemoteCallbackList";
5518a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani
56390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn    /*package*/ ArrayMap<IBinder, Callback> mCallbacks
57390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            = new ArrayMap<IBinder, Callback>();
58231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private Object[] mActiveBroadcast;
59b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn    private int mBroadcastCount = -1;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mKilled = false;
6118a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani    private StringBuilder mRecentCallers;
627b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Callback implements IBinder.DeathRecipient {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final E mCallback;
65231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Object mCookie;
6618a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani
67231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Callback(E callback, Object cookie) {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCallback = callback;
69231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCookie = cookie;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
717b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mCallbacks) {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCallbacks.remove(mCallback.asBinder());
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
76231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            onCallbackDied(mCallback, mCookie);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
797b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Simple version of {@link RemoteCallbackList#register(E, Object)}
82231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that does not take a cookie object.
83231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
84231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean register(E callback) {
85231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return register(callback, null);
86231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
875614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn
88231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add a new callback to the list.  This callback will remain in the list
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * until a corresponding call to {@link #unregister} or its hosting process
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * goes away.  If the callback was already registered (determined by
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * checking to see if the {@link IInterface#asBinder callback.asBinder()}
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * object is already in the list), then it will be left as-is.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registrations are not counted; a single call to {@link #unregister}
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will remove a callback after any number calls to register it.
967b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param callback The callback interface to be added to the list.  Must
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not be null -- passing null here will cause a NullPointerException.
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Most services will want to check for null before calling this with
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * an object given from a client, so that clients can't crash the
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * service with bad data.
1027b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param cookie Optional additional data to be associated with this
104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * callback.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true if the callback was successfully added to the list.
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns false if it was not added, either because {@link #kill} had
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * previously been called or the callback's process has gone away.
1097b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #unregister
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #kill
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #onCallbackDied
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean register(E callback, Object cookie) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mKilled) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11918a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani            // Flag unusual case that could be caused by a leak. b/36778087
12018a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani            logExcessiveCallbacks();
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IBinder binder = callback.asBinder();
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Callback cb = new Callback(callback, cookie);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                binder.linkToDeath(cb, 0);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCallbacks.put(binder, cb);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1327b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove from the list a callback that was previously added with
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #register}.  This uses the
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link IInterface#asBinder callback.asBinder()} object to correctly
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * find the previous registration.
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Registrations are not counted; a single unregister call will remove
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a callback after any number calls to {@link #register} for it.
1407b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param callback The callback to be removed from the list.  Passing
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null here will cause a NullPointerException, so you will generally want
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to check for null before calling.
1447b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns true if the callback was found and unregistered.  Returns
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * false if the given callback was not found on the list.
1477b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #register
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean unregister(E callback) {
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Callback cb = mCallbacks.remove(callback.asBinder());
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cb != null) {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cb.mCallback.asBinder().unlinkToDeath(cb, 0);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1607b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disable this callback list.  All registered callbacks are unregistered,
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and the list is disabled so that future calls to {@link #register} will
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fail.  This should be used when a Service is stopping, to prevent clients
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from registering callbacks after it is stopped.
1667b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #register
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void kill() {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
171390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            for (int cbi=mCallbacks.size()-1; cbi>=0; cbi--) {
172390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                Callback cb = mCallbacks.valueAt(cbi);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cb.mCallback.asBinder().unlinkToDeath(cb, 0);
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCallbacks.clear();
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKilled = true;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1797b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Old version of {@link #onCallbackDied(E, Object)} that
182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * does not provide a cookie.
183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void onCallbackDied(E callback) {
185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the process hosting a callback in the list has gone away.
189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * The default implementation calls {@link #onCallbackDied(E)}
190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * for backwards compatibility.
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param callback The callback whose process has died.  Note that, since
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * its process has died, you can not make any calls on to this interface.
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * You can, however, retrieve its IBinder and compare it with another
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * IBinder to see if it is the same object.
196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param cookie The cookie object original provided to
197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * {@link #register(E, Object)}.
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #register
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void onCallbackDied(E callback, Object cookie) {
202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        onCallbackDied(callback);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2047b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prepare to start making calls to the currently registered callbacks.
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This creates a copy of the callback list, which you can retrieve items
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from using {@link #getBroadcastItem}.  Note that only one broadcast can
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be active at a time, so you must be sure to always call this from the
210b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn     * same thread (usually by scheduling with {@link Handler}) or
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * do your own synchronization.  You must call {@link #finishBroadcast}
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when done.
2137b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>A typical loop delivering a broadcast looks like this:
2157b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <pre>
217b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn     * int i = callbacks.beginBroadcast();
218dace230043314d6fab1c5ced4b031eaccd814c25Dianne Hackborn     * while (i &gt; 0) {
219b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn     *     i--;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     try {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         callbacks.getBroadcastItem(i).somethingHappened();
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     } catch (RemoteException e) {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         // The RemoteCallbackList will take care of removing
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         // the dead object for us.
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * callbacks.finishBroadcast();</pre>
2287b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns the number of callbacks in the broadcast, to be used
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with {@link #getBroadcastItem} to determine the range of indices you
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can supply.
2327b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getBroadcastItem
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #finishBroadcast
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int beginBroadcast() {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCallbacks) {
238b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            if (mBroadcastCount > 0) {
239b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                throw new IllegalStateException(
240b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn                        "beginBroadcast() called while already in a broadcast");
241b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            }
242b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn
243b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            final int N = mBroadcastCount = mCallbacks.size();
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (N <= 0) {
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Object[] active = mActiveBroadcast;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (active == null || active.length < N) {
249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveBroadcast = active = new Object[N];
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
251390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            for (int i=0; i<N; i++) {
252390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                active[i] = mCallbacks.valueAt(i);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
254390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            return N;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2577b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve an item in the active broadcast that was previously started
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with {@link #beginBroadcast}.  This can <em>only</em> be called after
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the broadcast is started, and its data is no longer valid after
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * calling {@link #finishBroadcast}.
2637b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note that it is possible for the process of one of the returned
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * callbacks to go away before you call it, so you will need to catch
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link RemoteException} when calling on to the returned object.
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The callback list itself, however, will take care of unregistering
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * these objects once it detects that it is no longer valid, so you can
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * handle such an exception by simply ignoring it.
2707b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param index Which of the registered callbacks you would like to
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * retrieve.  Ranges from 0 to 1-{@link #beginBroadcast}.
2737b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns the callback interface that you can call.  This will
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * always be non-null.
2767b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #beginBroadcast
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public E getBroadcastItem(int index) {
280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return ((Callback)mActiveBroadcast[index]).mCallback;
281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
282231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
283231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve the cookie associated with the item
285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * returned by {@link #getBroadcastItem(int)}.
286231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     *
287231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @see #getBroadcastItem
288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public Object getBroadcastCookie(int index) {
290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return ((Callback)mActiveBroadcast[index]).mCookie;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2927b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clean up the state of a broadcast previously initiated by calling
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #beginBroadcast}.  This must always be called when you are done
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with a broadcast.
2977b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     *
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #beginBroadcast
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishBroadcast() {
3017bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki        synchronized (mCallbacks) {
3027bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki            if (mBroadcastCount < 0) {
3037bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki                throw new IllegalStateException(
3047bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki                        "finishBroadcast() called outside of a broadcast");
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3067bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki
3077bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki            Object[] active = mActiveBroadcast;
3087bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki            if (active != null) {
3097bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki                final int N = mBroadcastCount;
3107bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki                for (int i=0; i<N; i++) {
3117bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki                    active[i] = null;
3127bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki                }
3137bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki            }
3147bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki
3157bdb9ce97811782864d3b54616f233c041590c7eMakoto Onuki            mBroadcastCount = -1;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3181cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3191cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    /**
320ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla     * Performs {@code action} on each callback, calling
321ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla     * {@link #beginBroadcast()}/{@link #finishBroadcast()} before/after looping
322ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla     *
323ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla     * @hide
324ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla     */
325ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla    public void broadcast(Consumer<E> action) {
326ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla        int itemCount = beginBroadcast();
327ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla        try {
328ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla            for (int i = 0; i < itemCount; i++) {
329ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla                action.accept(getBroadcastItem(i));
330ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla            }
331ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla        } finally {
3324b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            finishBroadcast();
3334b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        }
3344b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    }
3354b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla
3364b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    /**
3374b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * Performs {@code action} for each cookie associated with a callback, calling
3384b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * {@link #beginBroadcast()}/{@link #finishBroadcast()} before/after looping
3394b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     *
3404b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     * @hide
3414b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla     */
3424b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla    public <C> void broadcastForEachCookie(Consumer<C> action) {
3434b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        int itemCount = beginBroadcast();
3444b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        try {
3454b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            for (int i = 0; i < itemCount; i++) {
3464b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla                action.accept((C) getBroadcastCookie(i));
3474b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla            }
3484b7c919e725bc87bea82ab2c2370f094a049b8cfEugene Susla        } finally {
349ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla            finishBroadcast();
350ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla        }
351ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla    }
352ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla
353ef4351cc72abeeba0f659950c199a4f9b7cd1842Eugene Susla    /**
3541cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * Returns the number of registered callbacks. Note that the number of registered
3551cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * callbacks may differ from the value returned by {@link #beginBroadcast()} since
3561cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * the former returns the number of callbacks registered at the time of the call
3571cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * and the second the number of callback to which the broadcast will be delivered.
3581cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * <p>
3591cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * This function is useful to decide whether to schedule a broadcast if this
3601cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * requires doing some work which otherwise would not be performed.
3611cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * </p>
3621cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     *
3631cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * @return The size.
3641cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     */
3651cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    public int getRegisteredCallbackCount() {
3661cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        synchronized (mCallbacks) {
3671cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            if (mKilled) {
3681cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov                return 0;
3691cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            }
3701cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            return mCallbacks.size();
3711cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3721cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3735614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn
3745614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn    /**
37559359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * Return a currently registered callback.  Note that this is
37659359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * <em>not</em> the same as {@link #getBroadcastItem} and should not be used
37759359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * interchangeably with it.  This method returns the registered callback at the given
37859359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * index, not the current broadcast state.  This means that it is not itself thread-safe:
37959359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * any call to {@link #register} or {@link #unregister} will change these indices, so you
38059359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * must do your own thread safety between these to protect from such changes.
38159359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     *
38259359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * @param index Index of which callback registration to return, from 0 to
38359359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * {@link #getRegisteredCallbackCount()} - 1.
38459359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     *
38559359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * @return Returns whatever callback is associated with this index, or null if
38659359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * {@link #kill()} has been called.
38759359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     */
38859359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn    public E getRegisteredCallbackItem(int index) {
38959359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn        synchronized (mCallbacks) {
39059359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn            if (mKilled) {
39159359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn                return null;
39259359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn            }
39359359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn            return mCallbacks.valueAt(index).mCallback;
39459359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn        }
39559359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn    }
39659359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn
39759359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn    /**
39859359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * Return any cookie associated with a currently registered callback.  Note that this is
3995614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     * <em>not</em> the same as {@link #getBroadcastCookie} and should not be used
40059359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * interchangeably with it.  This method returns the current cookie registered at the given
4015614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     * index, not the current broadcast state.  This means that it is not itself thread-safe:
4025614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     * any call to {@link #register} or {@link #unregister} will change these indices, so you
4035614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     * must do your own thread safety between these to protect from such changes.
4045614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     *
40559359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * @param index Index of which registration cookie to return, from 0 to
40659359d06c4b504579db1bc72ded5ef29c4334c79Dianne Hackborn     * {@link #getRegisteredCallbackCount()} - 1.
4075614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     *
4085614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     * @return Returns whatever cookie object is associated with this index, or null if
4095614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     * {@link #kill()} has been called.
4105614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn     */
4115614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn    public Object getRegisteredCallbackCookie(int index) {
4125614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn        synchronized (mCallbacks) {
4135614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn            if (mKilled) {
4145614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn                return null;
4155614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn            }
4165614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn            return mCallbacks.valueAt(index).mCookie;
4175614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn        }
4185614bf5a1ae4522dfc1a041f003cebc9b25c8b93Dianne Hackborn    }
41918a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani
420ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui    /** @hide */
421ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui    public void dump(PrintWriter pw, String prefix) {
422ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui        pw.print(prefix); pw.print("callbacks: "); pw.println(mCallbacks.size());
423ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui        pw.print(prefix); pw.print("killed: "); pw.println(mKilled);
424ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui        pw.print(prefix); pw.print("broadcasts count: "); pw.println(mBroadcastCount);
425ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui    }
426ccec6a6ae8b9f9785934e7d97849cbafcfcf3dcbKoji Fukui
42718a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani    private void logExcessiveCallbacks() {
42818a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani        final long size = mCallbacks.size();
42918a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani        final long TOO_MANY = 3000;
43018a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani        final long MAX_CHARS = 1000;
43118a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani        if (size >= TOO_MANY) {
43218a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani            if (size == TOO_MANY && mRecentCallers == null) {
43318a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                mRecentCallers = new StringBuilder();
43418a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani            }
43518a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani            if (mRecentCallers != null && mRecentCallers.length() < MAX_CHARS) {
43618a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                mRecentCallers.append(Debug.getCallers(5));
43718a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                mRecentCallers.append('\n');
43818a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                if (mRecentCallers.length() >= MAX_CHARS) {
43918a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                    Slog.wtf(TAG, "More than "
44018a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                            + TOO_MANY + " remote callbacks registered. Recent callers:\n"
44118a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                            + mRecentCallers.toString());
44218a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                    mRecentCallers = null;
44318a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani                }
44418a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani            }
44518a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani        }
44618a23f2fd8c18d812401563e1d9a847e4c2a2d93Amith Yamasani    }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
448