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