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