1ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa/* 2ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Copyright (C) 2014 The Android Open Source Project 3ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * 4ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Licensed under the Apache License, Version 2.0 (the "License"); 5ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * you may not use this file except in compliance with the License. 6ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * You may obtain a copy of the License at 7ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * 8ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * http://www.apache.org/licenses/LICENSE-2.0 9ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * 10ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * Unless required by applicable law or agreed to in writing, software 11ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * distributed under the License is distributed on an "AS IS" BASIS, 12ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * See the License for the specific language governing permissions and 14ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * limitations under the License 15ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa */ 16ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 17ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaapackage com.android.server.location; 18ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 19ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport com.android.internal.util.Preconditions; 20ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 21ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.annotation.NonNull; 226568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaaimport android.os.Handler; 23ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.IBinder; 24ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.IInterface; 25ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.RemoteException; 26ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.util.Log; 27ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 28ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport java.util.HashMap; 2913a60b0d41c740448ea39ca19842c7b193c61efddestradaaimport java.util.Map; 30ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 31ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa/** 32ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa * A helper class, that handles operations in remote listeners, and tracks for remote process death. 33ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa */ 34ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaabstract class RemoteListenerHelper<TListener extends IInterface> { 3513a60b0d41c740448ea39ca19842c7b193c61efddestradaa 366568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected static final int RESULT_SUCCESS = 0; 376568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected static final int RESULT_NOT_AVAILABLE = 1; 386568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected static final int RESULT_NOT_SUPPORTED = 2; 396568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected static final int RESULT_GPS_LOCATION_DISABLED = 3; 406568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected static final int RESULT_INTERNAL_ERROR = 4; 4113a60b0d41c740448ea39ca19842c7b193c61efddestradaa protected static final int RESULT_UNKNOWN = 5; 426568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 436568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private final Handler mHandler; 444b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa private final String mTag; 45ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 4613a60b0d41c740448ea39ca19842c7b193c61efddestradaa private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>(); 476568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 486568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private boolean mIsRegistered; 496568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private boolean mHasIsSupported; 506568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private boolean mIsSupported; 516568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 5213a60b0d41c740448ea39ca19842c7b193c61efddestradaa private int mLastReportedResult = RESULT_UNKNOWN; 5313a60b0d41c740448ea39ca19842c7b193c61efddestradaa 546568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected RemoteListenerHelper(Handler handler, String name) { 554b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa Preconditions.checkNotNull(name); 566568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mHandler = handler; 574b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa mTag = name; 584b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa } 594b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa 60ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa public boolean addListener(@NonNull TListener listener) { 61ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener."); 62ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa IBinder binder = listener.asBinder(); 63ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa LinkedListener deathListener = new LinkedListener(listener); 64ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa synchronized (mListenerMap) { 65ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa if (mListenerMap.containsKey(binder)) { 66ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa // listener already added 67ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa return true; 68ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 69ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa try { 70ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa binder.linkToDeath(deathListener, 0 /* flags */); 71ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } catch (RemoteException e) { 72ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa // if the remote process registering the listener is already death, just swallow the 736568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa // exception and return 746568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa Log.v(mTag, "Remote listener already died.", e); 75ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa return false; 76ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 77ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa mListenerMap.put(binder, deathListener); 786568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 796568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa // update statuses we already know about, starting from the ones that will never change 806568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa int result; 816568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa if (!isAvailableInPlatform()) { 826568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa result = RESULT_NOT_AVAILABLE; 836568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } else if (mHasIsSupported && !mIsSupported) { 846568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa result = RESULT_NOT_SUPPORTED; 856568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } else if (!isGpsEnabled()) { 866568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa result = RESULT_GPS_LOCATION_DISABLED; 876568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } else if (!tryRegister()) { 886568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa // only attempt to register if GPS is enabled, otherwise we will register once GPS 896568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa // becomes available 906568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa result = RESULT_INTERNAL_ERROR; 916568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } else if (mHasIsSupported && mIsSupported) { 926568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa result = RESULT_SUCCESS; 936568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } else { 946568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa // at this point if the supported flag is not set, the notification will be sent 956568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa // asynchronously in the future 966568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa return true; 97ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 986568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa post(listener, getHandlerOperation(result)); 99ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 100ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa return true; 101ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 102ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 1036568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa public void removeListener(@NonNull TListener listener) { 104ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa Preconditions.checkNotNull(listener, "Attempted to remove a 'null' listener."); 105ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa IBinder binder = listener.asBinder(); 106ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa LinkedListener linkedListener; 107ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa synchronized (mListenerMap) { 108ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa linkedListener = mListenerMap.remove(binder); 1096568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa if (mListenerMap.isEmpty()) { 1106568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa tryUnregister(); 111ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 112ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 113ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa if (linkedListener != null) { 114ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa binder.unlinkToDeath(linkedListener, 0 /* flags */); 115ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 116ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 117ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 1186568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected abstract boolean isAvailableInPlatform(); 1196568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected abstract boolean isGpsEnabled(); 1204b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa protected abstract boolean registerWithService(); 1214b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa protected abstract void unregisterFromService(); 1226568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected abstract ListenerOperation<TListener> getHandlerOperation(int result); 123ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 124ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa protected interface ListenerOperation<TListener extends IInterface> { 125ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa void execute(TListener listener) throws RemoteException; 126ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 127ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 1286568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa protected void foreach(ListenerOperation<TListener> operation) { 129ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa synchronized (mListenerMap) { 1306568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa foreachUnsafe(operation); 131ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 1326568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 133ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 13413a60b0d41c740448ea39ca19842c7b193c61efddestradaa protected void setSupported(boolean value) { 1356568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa synchronized (mListenerMap) { 1366568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mHasIsSupported = true; 1376568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mIsSupported = value; 13813a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 13913a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 14013a60b0d41c740448ea39ca19842c7b193c61efddestradaa 14113a60b0d41c740448ea39ca19842c7b193c61efddestradaa protected boolean tryUpdateRegistrationWithService() { 14213a60b0d41c740448ea39ca19842c7b193c61efddestradaa synchronized (mListenerMap) { 14313a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (!isGpsEnabled()) { 14413a60b0d41c740448ea39ca19842c7b193c61efddestradaa tryUnregister(); 14513a60b0d41c740448ea39ca19842c7b193c61efddestradaa return true; 14613a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 14713a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (mListenerMap.isEmpty()) { 14813a60b0d41c740448ea39ca19842c7b193c61efddestradaa return true; 14913a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 15013a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (tryRegister()) { 15113a60b0d41c740448ea39ca19842c7b193c61efddestradaa // registration was successful, there is no need to update the state 15213a60b0d41c740448ea39ca19842c7b193c61efddestradaa return true; 15313a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 15413a60b0d41c740448ea39ca19842c7b193c61efddestradaa ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR); 15513a60b0d41c740448ea39ca19842c7b193c61efddestradaa foreachUnsafe(operation); 15613a60b0d41c740448ea39ca19842c7b193c61efddestradaa return false; 15713a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 15813a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 15913a60b0d41c740448ea39ca19842c7b193c61efddestradaa 16013a60b0d41c740448ea39ca19842c7b193c61efddestradaa protected void updateResult() { 16113a60b0d41c740448ea39ca19842c7b193c61efddestradaa synchronized (mListenerMap) { 16213a60b0d41c740448ea39ca19842c7b193c61efddestradaa int newResult = calculateCurrentResultUnsafe(); 16313a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (mLastReportedResult == newResult) { 16413a60b0d41c740448ea39ca19842c7b193c61efddestradaa return; 16513a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 16613a60b0d41c740448ea39ca19842c7b193c61efddestradaa foreachUnsafe(getHandlerOperation(newResult)); 16713a60b0d41c740448ea39ca19842c7b193c61efddestradaa mLastReportedResult = newResult; 1686568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1696568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1706568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 1716568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private void foreachUnsafe(ListenerOperation<TListener> operation) { 1726568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa for (LinkedListener linkedListener : mListenerMap.values()) { 1736568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa post(linkedListener.getUnderlyingListener(), operation); 1746568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1756568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1766568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 1776568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private void post(TListener listener, ListenerOperation<TListener> operation) { 1786568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa if (operation != null) { 1796568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mHandler.post(new HandlerRunnable(listener, operation)); 1806568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1816568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1826568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 1836568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private boolean tryRegister() { 1846568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa if (!mIsRegistered) { 1856568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mIsRegistered = registerWithService(); 1866568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1876568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa return mIsRegistered; 1886568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 1896568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 1906568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private void tryUnregister() { 1916568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa if (!mIsRegistered) { 1926568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa return; 193ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 1946568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa unregisterFromService(); 1956568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mIsRegistered = false; 196ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 197ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 19813a60b0d41c740448ea39ca19842c7b193c61efddestradaa private int calculateCurrentResultUnsafe() { 19913a60b0d41c740448ea39ca19842c7b193c61efddestradaa // update statuses we already know about, starting from the ones that will never change 20013a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (!isAvailableInPlatform()) { 20113a60b0d41c740448ea39ca19842c7b193c61efddestradaa return RESULT_NOT_AVAILABLE; 20213a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 20313a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (!mHasIsSupported || mListenerMap.isEmpty()) { 20413a60b0d41c740448ea39ca19842c7b193c61efddestradaa // we'll update once we have a supported status available 20513a60b0d41c740448ea39ca19842c7b193c61efddestradaa return RESULT_UNKNOWN; 20613a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 20713a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (!mIsSupported) { 20813a60b0d41c740448ea39ca19842c7b193c61efddestradaa return RESULT_NOT_SUPPORTED; 20913a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 21013a60b0d41c740448ea39ca19842c7b193c61efddestradaa if (!isGpsEnabled()) { 21113a60b0d41c740448ea39ca19842c7b193c61efddestradaa return RESULT_GPS_LOCATION_DISABLED; 21213a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 21313a60b0d41c740448ea39ca19842c7b193c61efddestradaa return RESULT_SUCCESS; 21413a60b0d41c740448ea39ca19842c7b193c61efddestradaa } 21513a60b0d41c740448ea39ca19842c7b193c61efddestradaa 216ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa private class LinkedListener implements IBinder.DeathRecipient { 217ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa private final TListener mListener; 218ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 219ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa public LinkedListener(@NonNull TListener listener) { 220ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa mListener = listener; 221ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 222ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 223ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa @NonNull 224ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa public TListener getUnderlyingListener() { 225ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa return mListener; 226ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 227ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa 228ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa @Override 229ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa public void binderDied() { 2304b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa Log.d(mTag, "Remote Listener died: " + mListener); 231ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa removeListener(mListener); 232ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 233ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa } 2346568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 2356568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private class HandlerRunnable implements Runnable { 2366568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private final TListener mListener; 2376568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa private final ListenerOperation<TListener> mOperation; 2386568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 2396568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa public HandlerRunnable(TListener listener, ListenerOperation<TListener> operation) { 2406568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mListener = listener; 2416568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mOperation = operation; 2426568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 2436568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa 2446568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa @Override 2456568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa public void run() { 2466568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa try { 2476568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa mOperation.execute(mListener); 2486568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } catch (RemoteException e) { 2496568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa Log.v(mTag, "Error in monitored listener.", e); 2506568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 2516568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 2526568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa } 253ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa} 254