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 > 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