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