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 android.annotation.NonNull;
206568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaaimport android.os.Handler;
21ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.IBinder;
22ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.IInterface;
23ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.os.RemoteException;
24ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaaimport android.util.Log;
25ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
2648f1a647655f3479bc655d2c3c4873c6aa9b712cgomoimport com.android.internal.util.Preconditions;
2748f1a647655f3479bc655d2c3c4873c6aa9b712cgomo
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;
4248f1a647655f3479bc655d2c3c4873c6aa9b712cgomo    protected static final int RESULT_NOT_ALLOWED = 6;
436568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
446568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private final Handler mHandler;
454b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    private final String mTag;
46ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
4713a60b0d41c740448ea39ca19842c7b193c61efddestradaa    private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
486568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
499c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley    private volatile boolean mIsRegistered;  // must access only on handler thread, or read-only
509c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley
516568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private boolean mHasIsSupported;
526568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private boolean mIsSupported;
536568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
5413a60b0d41c740448ea39ca19842c7b193c61efddestradaa    private int mLastReportedResult = RESULT_UNKNOWN;
5513a60b0d41c740448ea39ca19842c7b193c61efddestradaa
566568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected RemoteListenerHelper(Handler handler, String name) {
574b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(name);
586568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        mHandler = handler;
594b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        mTag = name;
604b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
614b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
629c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley    // read-only access for a dump() thread assured via volatile
639c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley    public boolean isRegistered() {
649c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley        return mIsRegistered;
659c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley    }
669c25085863a2762b06e9e967cffe2d8e78b17526Wyatt Riley
67ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    public boolean addListener(@NonNull TListener listener) {
68ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
69ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        IBinder binder = listener.asBinder();
70ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        LinkedListener deathListener = new LinkedListener(listener);
71ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mListenerMap) {
72ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            if (mListenerMap.containsKey(binder)) {
73ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                // listener already added
74ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                return true;
75ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
76ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            try {
77ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                binder.linkToDeath(deathListener, 0 /* flags */);
78ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            } catch (RemoteException e) {
79ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                // if the remote process registering the listener is already death, just swallow the
806568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                // exception and return
816568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                Log.v(mTag, "Remote listener already died.", e);
82ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa                return false;
83ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
84ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            mListenerMap.put(binder, deathListener);
856568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
866568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            // update statuses we already know about, starting from the ones that will never change
876568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            int result;
886568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            if (!isAvailableInPlatform()) {
896568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                result = RESULT_NOT_AVAILABLE;
906568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            } else if (mHasIsSupported && !mIsSupported) {
916568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                result = RESULT_NOT_SUPPORTED;
926568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            } else if (!isGpsEnabled()) {
936568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                // only attempt to register if GPS is enabled, otherwise we will register once GPS
946568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                // becomes available
95aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                result = RESULT_GPS_LOCATION_DISABLED;
966568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            } else if (mHasIsSupported && mIsSupported) {
97aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                tryRegister();
98aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                // initially presume success, possible internal error could follow asynchornously
996568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                result = RESULT_SUCCESS;
1006568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            } else {
1016568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                // at this point if the supported flag is not set, the notification will be sent
1026568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                // asynchronously in the future
1036568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                return true;
104ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
1056568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            post(listener, getHandlerOperation(result));
106ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
107ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        return true;
108ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
109ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1106568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    public void removeListener(@NonNull TListener listener) {
111ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        Preconditions.checkNotNull(listener, "Attempted to remove a 'null' listener.");
112ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        IBinder binder = listener.asBinder();
113ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        LinkedListener linkedListener;
114ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mListenerMap) {
115ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            linkedListener = mListenerMap.remove(binder);
1166568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            if (mListenerMap.isEmpty()) {
1176568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                tryUnregister();
118ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            }
119ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
120ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        if (linkedListener != null) {
121ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            binder.unlinkToDeath(linkedListener, 0 /* flags */);
122ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
123ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
124ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1256568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected abstract boolean isAvailableInPlatform();
1266568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected abstract boolean isGpsEnabled();
12748f1a647655f3479bc655d2c3c4873c6aa9b712cgomo    // must access only on handler thread
12848f1a647655f3479bc655d2c3c4873c6aa9b712cgomo    protected abstract int registerWithService();
129aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley    protected abstract void unregisterFromService(); // must access only on handler thread
1306568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected abstract ListenerOperation<TListener> getHandlerOperation(int result);
131ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
132ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    protected interface ListenerOperation<TListener extends IInterface> {
133ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        void execute(TListener listener) throws RemoteException;
134ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
135ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
1366568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected void foreach(ListenerOperation<TListener> operation) {
137ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        synchronized (mListenerMap) {
1386568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            foreachUnsafe(operation);
139ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
1406568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
141ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
14213a60b0d41c740448ea39ca19842c7b193c61efddestradaa    protected void setSupported(boolean value) {
1436568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        synchronized (mListenerMap) {
1446568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            mHasIsSupported = true;
1456568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            mIsSupported = value;
14613a60b0d41c740448ea39ca19842c7b193c61efddestradaa        }
14713a60b0d41c740448ea39ca19842c7b193c61efddestradaa    }
14813a60b0d41c740448ea39ca19842c7b193c61efddestradaa
149aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley    protected void tryUpdateRegistrationWithService() {
15013a60b0d41c740448ea39ca19842c7b193c61efddestradaa        synchronized (mListenerMap) {
15113a60b0d41c740448ea39ca19842c7b193c61efddestradaa            if (!isGpsEnabled()) {
15213a60b0d41c740448ea39ca19842c7b193c61efddestradaa                tryUnregister();
153aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                return;
15413a60b0d41c740448ea39ca19842c7b193c61efddestradaa            }
15513a60b0d41c740448ea39ca19842c7b193c61efddestradaa            if (mListenerMap.isEmpty()) {
156aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                return;
15713a60b0d41c740448ea39ca19842c7b193c61efddestradaa            }
158aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            tryRegister();
15913a60b0d41c740448ea39ca19842c7b193c61efddestradaa        }
16013a60b0d41c740448ea39ca19842c7b193c61efddestradaa    }
16113a60b0d41c740448ea39ca19842c7b193c61efddestradaa
16213a60b0d41c740448ea39ca19842c7b193c61efddestradaa    protected void updateResult() {
16313a60b0d41c740448ea39ca19842c7b193c61efddestradaa        synchronized (mListenerMap) {
16413a60b0d41c740448ea39ca19842c7b193c61efddestradaa            int newResult = calculateCurrentResultUnsafe();
16513a60b0d41c740448ea39ca19842c7b193c61efddestradaa            if (mLastReportedResult == newResult) {
16613a60b0d41c740448ea39ca19842c7b193c61efddestradaa                return;
16713a60b0d41c740448ea39ca19842c7b193c61efddestradaa            }
16813a60b0d41c740448ea39ca19842c7b193c61efddestradaa            foreachUnsafe(getHandlerOperation(newResult));
16913a60b0d41c740448ea39ca19842c7b193c61efddestradaa            mLastReportedResult = newResult;
1706568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        }
1716568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
1726568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
1736568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private void foreachUnsafe(ListenerOperation<TListener> operation) {
1746568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        for (LinkedListener linkedListener : mListenerMap.values()) {
1756568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            post(linkedListener.getUnderlyingListener(), operation);
1766568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        }
1776568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
1786568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
1796568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private void post(TListener listener, ListenerOperation<TListener> operation) {
1806568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        if (operation != null) {
1816568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            mHandler.post(new HandlerRunnable(listener, operation));
1826568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        }
1836568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
1846568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
185aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley    private void tryRegister() {
186aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley        mHandler.post(new Runnable() {
18748f1a647655f3479bc655d2c3c4873c6aa9b712cgomo            int registrationState = RESULT_INTERNAL_ERROR;
188aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            @Override
189aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            public void run() {
190aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                if (!mIsRegistered) {
19148f1a647655f3479bc655d2c3c4873c6aa9b712cgomo                    registrationState = registerWithService();
19248f1a647655f3479bc655d2c3c4873c6aa9b712cgomo                    mIsRegistered = registrationState == RESULT_SUCCESS;
193aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                }
194aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                if (!mIsRegistered) {
195aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                    // post back a failure
196aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                    mHandler.post(new Runnable() {
197aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                        @Override
198aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                        public void run() {
199aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                            synchronized (mListenerMap) {
20048f1a647655f3479bc655d2c3c4873c6aa9b712cgomo                                ListenerOperation<TListener> operation = getHandlerOperation(registrationState);
201aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                                foreachUnsafe(operation);
202aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                            }
203aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                        }
204aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                    });
205aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                }
206aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            }
207aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley        });
2086568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
2096568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
2106568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private void tryUnregister() {
211aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley        mHandler.post(new Runnable() {
212aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            @Override
213aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            public void run() {
214aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                if (!mIsRegistered) {
215aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                    return;
216aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                }
217aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                unregisterFromService();
218aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley                mIsRegistered = false;
219aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley            }
220aa420d5e1432d8669ecc10a52246e734b4eea156Wyatt Riley        });
221ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
222ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
22313a60b0d41c740448ea39ca19842c7b193c61efddestradaa    private int calculateCurrentResultUnsafe() {
22413a60b0d41c740448ea39ca19842c7b193c61efddestradaa        // update statuses we already know about, starting from the ones that will never change
22513a60b0d41c740448ea39ca19842c7b193c61efddestradaa        if (!isAvailableInPlatform()) {
22613a60b0d41c740448ea39ca19842c7b193c61efddestradaa            return RESULT_NOT_AVAILABLE;
22713a60b0d41c740448ea39ca19842c7b193c61efddestradaa        }
22813a60b0d41c740448ea39ca19842c7b193c61efddestradaa        if (!mHasIsSupported || mListenerMap.isEmpty()) {
22913a60b0d41c740448ea39ca19842c7b193c61efddestradaa            // we'll update once we have a supported status available
23013a60b0d41c740448ea39ca19842c7b193c61efddestradaa            return RESULT_UNKNOWN;
23113a60b0d41c740448ea39ca19842c7b193c61efddestradaa        }
23213a60b0d41c740448ea39ca19842c7b193c61efddestradaa        if (!mIsSupported) {
23313a60b0d41c740448ea39ca19842c7b193c61efddestradaa            return RESULT_NOT_SUPPORTED;
23413a60b0d41c740448ea39ca19842c7b193c61efddestradaa        }
23513a60b0d41c740448ea39ca19842c7b193c61efddestradaa        if (!isGpsEnabled()) {
23613a60b0d41c740448ea39ca19842c7b193c61efddestradaa            return RESULT_GPS_LOCATION_DISABLED;
23713a60b0d41c740448ea39ca19842c7b193c61efddestradaa        }
23813a60b0d41c740448ea39ca19842c7b193c61efddestradaa        return RESULT_SUCCESS;
23913a60b0d41c740448ea39ca19842c7b193c61efddestradaa    }
24013a60b0d41c740448ea39ca19842c7b193c61efddestradaa
241ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    private class LinkedListener implements IBinder.DeathRecipient {
242ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        private final TListener mListener;
243ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
244ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        public LinkedListener(@NonNull TListener listener) {
245ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            mListener = listener;
246ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
247ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
248ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        @NonNull
249ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        public TListener getUnderlyingListener() {
250ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            return mListener;
251ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
252ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa
253ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        @Override
254ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        public void binderDied() {
2554b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            Log.d(mTag, "Remote Listener died: " + mListener);
256ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa            removeListener(mListener);
257ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa        }
258ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa    }
2596568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
2606568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private class HandlerRunnable implements Runnable {
2616568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        private final TListener mListener;
2626568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        private final ListenerOperation<TListener> mOperation;
2636568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
2646568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        public HandlerRunnable(TListener listener, ListenerOperation<TListener> operation) {
2656568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            mListener = listener;
2666568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            mOperation = operation;
2676568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        }
2686568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
2696568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        @Override
2706568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        public void run() {
2716568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            try {
2726568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                mOperation.execute(mListener);
2736568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            } catch (RemoteException e) {
2746568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                Log.v(mTag, "Error in monitored listener.", e);
2756568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa            }
2766568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        }
2776568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
278ea8a8a6076f04360de2d25b3e5853cde8026cd5fdestradaa}
279