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;
224b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport android.os.RemoteException;
234b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport android.util.Log;
244b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
254b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport java.util.ArrayList;
264b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport java.util.Collection;
274b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaimport java.util.HashSet;
284b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
294b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa/**
304b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * A base handler class to manage transport and local listeners.
314b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa *
324b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa * @hide
334b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa */
344b3e3931270f8e406fc806bc7fa1c2788256687ddestradaaabstract class LocalListenerHelper<TListener> {
354b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    private final HashSet<TListener> mListeners = new HashSet<TListener>();
364b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    private final String mTag;
374b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
384b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected LocalListenerHelper(String name) {
394b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(name);
404b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        mTag = name;
414b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
424b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
434b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    public boolean add(@NonNull TListener listener) {
444b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(listener);
454b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
464b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        synchronized (mListeners) {
474b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            // we need to register with the service first, because we need to find out if the
484b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            // service will actually support the request before we attempt anything
494b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            if (mListeners.isEmpty()) {
504b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                boolean registeredWithService;
514b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                try {
524b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    registeredWithService = registerWithServer();
534b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                } catch (RemoteException e) {
544b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    Log.e(mTag, "Error handling first listener.", e);
554b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    return false;
564b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                }
574b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                if (!registeredWithService) {
584b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    Log.e(mTag, "Unable to register listener transport.");
594b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    return false;
604b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                }
614b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
624b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
634b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            if (mListeners.contains(listener)) {
644b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                return true;
654b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
664b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            mListeners.add(listener);
674b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
684b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        return true;
694b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
704b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
714b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    public void remove(@NonNull TListener listener) {
724b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Preconditions.checkNotNull(listener);
734b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
744b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        synchronized (mListeners) {
754b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            boolean removed = mListeners.remove(listener);
764b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            boolean isLastRemoved = removed && mListeners.isEmpty();
774b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            if (isLastRemoved) {
784b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                try {
794b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                    unregisterFromServer();
804b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                } catch (RemoteException e) {
814b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
824b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                }
834b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
844b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
854b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
864b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
874b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected abstract boolean registerWithServer() throws RemoteException;
884b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected abstract void unregisterFromServer() throws RemoteException;
894b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
904b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected interface ListenerOperation<TListener> {
914b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        void execute(TListener listener) throws RemoteException;
924b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
934b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
944b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    protected void foreach(ListenerOperation operation) {
954b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        Collection<TListener> listeners;
964b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        synchronized (mListeners) {
974b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            listeners = new ArrayList<TListener>(mListeners);
984b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
994b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa
1004b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        for (TListener listener : listeners) {
1014b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            try {
1024b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                operation.execute(listener);
1034b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            } catch (RemoteException e) {
1044b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                Log.e(mTag, "Error in monitored listener.", e);
1054b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa                // don't return, give a fair chance to all listeners to receive the event
1064b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa            }
1074b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa        }
1084b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa    }
1094b3e3931270f8e406fc806bc7fa1c2788256687ddestradaa}
110