14b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa/*
24b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * Copyright (C) 2014 The Android Open Source Project
34b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa *
44b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * Licensed under the Apache License, Version 2.0 (the "License");
54b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * you may not use this file except in compliance with the License.
64b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * You may obtain a copy of the License at
74b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa *
84b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa *      http://www.apache.org/licenses/LICENSE-2.0
94b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa *
104b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * Unless required by applicable law or agreed to in writing, software
114b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * distributed under the License is distributed on an "AS IS" BASIS,
124b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * See the License for the specific language governing permissions and
144b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * limitations under the License
154b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa */
164b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
174b3e3931270f8e406fc806bc7fa1c2788256687ddestradaapackage android.location;
184b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
194b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport com.android.internal.util.Preconditions;
204b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
214b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport android.annotation.NonNull;
226568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaaimport android.content.Context;
23a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tangimport android.os.Handler;
244b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport android.os.RemoteException;
254b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport android.util.Log;
264b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
274b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport java.util.ArrayList;
284b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport java.util.Collection;
29a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tangimport java.util.HashMap;
30a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tangimport java.util.Map;
314b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
324b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa/**
334b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * A base handler class to manage transport and local listeners.
344b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa *
354b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * @hide
364b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa */
374b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaabstract class LocalListenerHelper<TListener> {
38a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang    private final HashMap<TListener, Handler> mListeners = new HashMap<>();
396568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
404b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    private final String mTag;
416568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    private final Context mContext;
424b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
436568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected LocalListenerHelper(Context context, String name) {
444b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(name);
456568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        mContext = context;
464b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        mTag = name;
474b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
484b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
49a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang    public boolean add(@NonNull TListener listener, Handler handler) {
504b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(listener);
514b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        synchronized (mListeners) {
524b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            // we need to register with the service first, because we need to find out if the
534b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            // service will actually support the request before we attempt anything
544b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            if (mListeners.isEmpty()) {
554b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                boolean registeredWithService;
564b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                try {
574b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    registeredWithService = registerWithServer();
584b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                } catch (RemoteException e) {
594b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    Log.e(mTag, "Error handling first listener.", e);
604b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    return false;
614b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                }
624b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                if (!registeredWithService) {
634b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    Log.e(mTag, "Unable to register listener transport.");
644b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    return false;
654b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                }
664b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
67a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            if (mListeners.containsKey(listener)) {
684b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                return true;
694b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
70a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            mListeners.put(listener, handler);
71a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            return true;
724b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
734b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
744b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
754b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    public void remove(@NonNull TListener listener) {
764b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(listener);
774b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        synchronized (mListeners) {
78a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            boolean removed = mListeners.containsKey(listener);
79a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            mListeners.remove(listener);
804b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            boolean isLastRemoved = removed && mListeners.isEmpty();
814b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            if (isLastRemoved) {
824b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                try {
834b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    unregisterFromServer();
844b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                } catch (RemoteException e) {
856568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa                    Log.v(mTag, "Error handling last listener removal", e);
864b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                }
874b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
884b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
894b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
904b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
914b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected abstract boolean registerWithServer() throws RemoteException;
924b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected abstract void unregisterFromServer() throws RemoteException;
934b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
944b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected interface ListenerOperation<TListener> {
954b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        void execute(TListener listener) throws RemoteException;
964b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
974b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
986568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    protected Context getContext() {
996568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa        return mContext;
1006568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa    }
1016568d709e78d6ccaf256b7d0e4a19cdfb26deafbdestradaa
102a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang    private void executeOperation(ListenerOperation<TListener> operation, TListener listener) {
103a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang        try {
104a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            operation.execute(listener);
105a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang        } catch (RemoteException e) {
106a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            Log.e(mTag, "Error in monitored listener.", e);
107a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            // don't return, give a fair chance to all listeners to receive the event
108a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang        }
109a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang    }
110a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang
111a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang    protected void foreach(final ListenerOperation<TListener> operation) {
112a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang        Collection<Map.Entry<TListener, Handler>> listeners;
1134b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        synchronized (mListeners) {
114a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            listeners = new ArrayList<>(mListeners.entrySet());
1154b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
116a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang        for (final Map.Entry<TListener, Handler> listener : listeners) {
117a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            if (listener.getValue() == null) {
118a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                executeOperation(operation, listener.getKey());
119a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang            } else {
120a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                listener.getValue().post(new Runnable() {
121a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                    @Override
122a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                    public void run() {
123a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                        executeOperation(operation, listener.getKey());
124a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                    }
125a8b7bb5a50d8ad197c6f32eb308919c11b52ce74Lifu Tang                });
1264b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
1274b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
1284b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
1294b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa}
130