RemoteCallbackList.java revision b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0
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: 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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}. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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 } 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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 } 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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. 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The 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. 95231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * @param cookie Optional additional data to be associated with this 96231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * callback. 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns true if the callback was successfully added to the list. 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns false if it was not added, either because {@link #kill} had 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * previously been called or the callback's process has gone away. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #unregister 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #kill 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #onCallbackDied 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public boolean register(E callback, Object cookie) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mCallbacks) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mKilled) { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IBinder binder = callback.asBinder(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn Callback cb = new Callback(callback, cookie); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project binder.linkToDeath(cb, 0); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallbacks.put(binder, cb); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove from the list a callback that was previously added with 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #register}. This uses the 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link IInterface#asBinder callback.asBinder()} object to correctly 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * find the previous registration. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Registrations are not counted; a single unregister call will remove 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a callback after any number calls to {@link #register} for it. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param callback The callback to be removed from the list. Passing 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null here will cause a NullPointerException, so you will generally want 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to check for null before calling. 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns true if the callback was found and unregistered. Returns 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * false if the given callback was not found on the list. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #register 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean unregister(E callback) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mCallbacks) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Callback cb = mCallbacks.remove(callback.asBinder()); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cb != null) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cb.mCallback.asBinder().unlinkToDeath(cb, 0); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Disable this callback list. All registered callbacks are unregistered, 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and the list is disabled so that future calls to {@link #register} will 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fail. This should be used when a Service is stopping, to prevent clients 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from registering callbacks after it is stopped. 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #register 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void kill() { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mCallbacks) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Callback cb : mCallbacks.values()) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cb.mCallback.asBinder().unlinkToDeath(cb, 0); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCallbacks.clear(); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKilled = true; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Old version of {@link #onCallbackDied(E, Object)} that 171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * does not provide a cookie. 172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn */ 173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void onCallbackDied(E callback) { 174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn /** 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called when the process hosting a callback in the list has gone away. 178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * The default implementation calls {@link #onCallbackDied(E)} 179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * for backwards compatibility. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param callback The callback whose process has died. Note that, since 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * its process has died, you can not make any calls on to this interface. 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You can, however, retrieve its IBinder and compare it with another 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * IBinder to see if it is the same object. 185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * @param cookie The cookie object original provided to 186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * {@link #register(E, Object)}. 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #register 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public void onCallbackDied(E callback, Object cookie) { 191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn onCallbackDied(callback); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prepare to start making calls to the currently registered callbacks. 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This creates a copy of the callback list, which you can retrieve items 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from using {@link #getBroadcastItem}. Note that only one broadcast can 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be active at a time, so you must be sure to always call this from the 199b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn * same thread (usually by scheduling with {@link Handler}) or 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * do your own synchronization. You must call {@link #finishBroadcast} 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when done. 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>A typical loop delivering a broadcast looks like this: 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 206b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn * int i = callbacks.beginBroadcast(); 207b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn * while (i > 0) { 208b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn * i--; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * try { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * callbacks.getBroadcastItem(i).somethingHappened(); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } catch (RemoteException e) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // The RemoteCallbackList will take care of removing 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * // the dead object for us. 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * callbacks.finishBroadcast();</pre> 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns the number of callbacks in the broadcast, to be used 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with {@link #getBroadcastItem} to determine the range of indices you 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can supply. 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #getBroadcastItem 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #finishBroadcast 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int beginBroadcast() { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mCallbacks) { 227b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn if (mBroadcastCount > 0) { 228b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn throw new IllegalStateException( 229b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn "beginBroadcast() called while already in a broadcast"); 230b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn } 231b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn 232b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn final int N = mBroadcastCount = mCallbacks.size(); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (N <= 0) { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn Object[] active = mActiveBroadcast; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (active == null || active.length < N) { 238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn mActiveBroadcast = active = new Object[N]; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i=0; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Callback cb : mCallbacks.values()) { 242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn active[i++] = cb; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 244105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project return i; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve an item in the active broadcast that was previously started 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with {@link #beginBroadcast}. This can <em>only</em> be called after 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the broadcast is started, and its data is no longer valid after 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * calling {@link #finishBroadcast}. 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Note that it is possible for the process of one of the returned 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * callbacks to go away before you call it, so you will need to catch 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link RemoteException} when calling on to the returned object. 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The callback list itself, however, will take care of unregistering 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these objects once it detects that it is no longer valid, so you can 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * handle such an exception by simply ignoring it. 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index Which of the registered callbacks you would like to 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * retrieve. Ranges from 0 to 1-{@link #beginBroadcast}. 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns the callback interface that you can call. This will 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * always be non-null. 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #beginBroadcast 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public E getBroadcastItem(int index) { 270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return ((Callback)mActiveBroadcast[index]).mCallback; 271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn } 272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn 273231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn /** 274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Retrieve the cookie associated with the item 275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * returned by {@link #getBroadcastItem(int)}. 276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * 277231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * @see #getBroadcastItem 278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn */ 279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn public Object getBroadcastCookie(int index) { 280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn return ((Callback)mActiveBroadcast[index]).mCookie; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clean up the state of a broadcast previously initiated by calling 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #beginBroadcast}. This must always be called when you are done 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with a broadcast. 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #beginBroadcast 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void finishBroadcast() { 291b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn if (mBroadcastCount < 0) { 292b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn throw new IllegalStateException( 293b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn "finishBroadcast() called outside of a broadcast"); 294b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn } 295b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn 296231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn Object[] active = mActiveBroadcast; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (active != null) { 298b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn final int N = mBroadcastCount; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project active[i] = null; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 303b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn 304b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn mBroadcastCount = -1; 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 307