11af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
21af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Copyright (C) 2013 The Android Open Source Project
31af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *
41af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Licensed under the Apache License, Version 2.0 (the "License");
51af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * you may not use this file except in compliance with the License.
61af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * You may obtain a copy of the License at
71af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *
81af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *     http://www.apache.org/licenses/LICENSE-2.0
91af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *
101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Unless required by applicable law or agreed to in writing, software
111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * distributed under the License is distributed on an "AS IS" BASIS,
1264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * See the License for the specific language governing permissions and
141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * limitations under the License.
151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
171af4b0280af406cfc7eb46810f6b76e57b983e11destradaapackage com.android.location.provider;
181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
191af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport android.hardware.location.IFusedLocationHardware;
201af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport android.hardware.location.IFusedLocationHardwareSink;
211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
221af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport android.location.Location;
231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaaimport android.os.Handler;
2564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaaimport android.os.Looper;
2664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaaimport android.os.Message;
271af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport android.os.RemoteException;
281af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport android.util.Log;
291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaaimport java.util.HashMap;
3164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaaimport java.util.Map;
321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/**
341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Class that exposes IFusedLocationHardware functionality to unbundled services.
351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
361af4b0280af406cfc7eb46810f6b76e57b983e11destradaapublic final class FusedLocationHardware {
371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    private final String TAG = "FusedLocationHardware";
381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    private IFusedLocationHardware mLocationHardware;
4064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
4164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    // the list uses a copy-on-write pattern to update its contents
4264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    HashMap<FusedLocationHardwareSink, DispatcherHandler> mSinkList =
4364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            new HashMap<FusedLocationHardwareSink, DispatcherHandler>();
441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    private IFusedLocationHardwareSink mInternalSink = new IFusedLocationHardwareSink.Stub() {
461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        @Override
471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        public void onLocationAvailable(Location[] locations) {
481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            dispatchLocations(locations);
491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        @Override
521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        public void onDiagnosticDataAvailable(String data) {
531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            dispatchDiagnosticData(data);
541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    };
561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    /**
5864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa     * @hide
5964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa     */
601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public FusedLocationHardware(IFusedLocationHardware locationHardware) {
611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        mLocationHardware = locationHardware;
621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    /*
651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa     * Methods to provide a Facade for IFusedLocationHardware
661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa     */
6764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    public void registerSink(FusedLocationHardwareSink sink, Looper looper) {
6864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        if(sink == null || looper == null) {
6964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            throw new IllegalArgumentException("Parameter sink and looper cannot be null.");
701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        boolean registerSink;
731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        synchronized (mSinkList) {
741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            // register only on first insertion
751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            registerSink = mSinkList.size() == 0;
761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            // guarantee uniqueness
7764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            if(mSinkList.containsKey(sink)) {
7864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                return;
791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            }
8064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
8164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
8264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
8364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            newSinkList.put(sink, new DispatcherHandler(looper));
8464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mSinkList = newSinkList;
851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        if(registerSink) {
881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            try {
891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa                mLocationHardware.registerSink(mInternalSink);
901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            } catch(RemoteException e) {
911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa                Log.e(TAG, "RemoteException at registerSink");
921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            }
931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void unregisterSink(FusedLocationHardwareSink sink) {
971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        if(sink == null) {
9864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            throw new IllegalArgumentException("Parameter sink cannot be null.");
991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
10164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        boolean unregisterSink;
1021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        synchronized(mSinkList) {
10364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            if(!mSinkList.containsKey(sink)) {
10464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                //done
10564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                return;
10664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            }
10764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
10864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
10964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
11064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            newSinkList.remove(sink);
11164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            //unregister after the last sink
11264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            unregisterSink = newSinkList.size() == 0;
11364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
11464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mSinkList = newSinkList;
1151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        if(unregisterSink) {
1181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            try {
1191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa                mLocationHardware.unregisterSink(mInternalSink);
1201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            } catch(RemoteException e) {
1211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa                Log.e(TAG, "RemoteException at unregisterSink");
1221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            }
1231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public int getSupportedBatchSize() {
1271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            return mLocationHardware.getSupportedBatchSize();
1291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at getSupportedBatchSize");
1311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            return 0;
1321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void startBatching(int id, GmsFusedBatchOptions batchOptions) {
1361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            mLocationHardware.startBatching(id, batchOptions.getParcelableOptions());
1381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at startBatching");
1401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1411af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void stopBatching(int id) {
1441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            mLocationHardware.stopBatching(id);
1461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at stopBatching");
1481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void updateBatchingOptions(int id, GmsFusedBatchOptions batchOptions) {
1521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            mLocationHardware.updateBatchingOptions(id, batchOptions.getParcelableOptions());
1541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at updateBatchingOptions");
1561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void requestBatchOfLocations(int batchSizeRequest) {
1601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            mLocationHardware.requestBatchOfLocations(batchSizeRequest);
1621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at requestBatchOfLocations");
1641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public boolean supportsDiagnosticDataInjection() {
1681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1691af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            return mLocationHardware.supportsDiagnosticDataInjection();
1701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at supportsDiagnisticDataInjection");
1721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            return false;
1731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void injectDiagnosticData(String data) {
1771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            mLocationHardware.injectDiagnosticData(data);
1791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at injectDiagnosticData");
1811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public boolean supportsDeviceContextInjection() {
1851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            return mLocationHardware.supportsDeviceContextInjection();
1871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at supportsDeviceContextInjection");
1891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            return false;
1901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    public void injectDeviceContext(int deviceEnabledContext) {
1941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        try {
1951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            mLocationHardware.injectDeviceContext(deviceEnabledContext);
1961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        } catch(RemoteException e) {
1971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Log.e(TAG, "RemoteException at injectDeviceContext");
1981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
1991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
2001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    /*
20264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa     * Helper methods and classes
2031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa     */
20464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    private class DispatcherHandler extends Handler {
20564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public static final int DISPATCH_LOCATION = 1;
20664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public static final int DISPATCH_DIAGNOSTIC_DATA = 2;
20764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
20864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public DispatcherHandler(Looper looper) {
20964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            super(looper, null /*callback*/ , true /*async*/);
21064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        }
21164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
21264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        @Override
21364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public void handleMessage(Message message) {
21464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            MessageCommand command = (MessageCommand) message.obj;
21564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            switch(message.what) {
21664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                case DISPATCH_LOCATION:
21764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    command.dispatchLocation();
21864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    break;
21964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                case DISPATCH_DIAGNOSTIC_DATA:
22064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    command.dispatchDiagnosticData();
22164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                default:
22264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    Log.e(TAG, "Invalid dispatch message");
22364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    break;
22464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            }
22564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        }
22664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    }
22764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
22864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    private class MessageCommand {
22964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        private final FusedLocationHardwareSink mSink;
23064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        private final Location[] mLocations;
23164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        private final String mData;
23264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
23364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public MessageCommand(
23464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                FusedLocationHardwareSink sink,
23564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                Location[] locations,
23664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                String data) {
23764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mSink = sink;
23864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mLocations = locations;
23964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mData = data;
24064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        }
24164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
24264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public void dispatchLocation() {
24364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mSink.onLocationAvailable(mLocations);
24464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        }
24564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
24664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        public void dispatchDiagnosticData() {
24764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            mSink.onDiagnosticDataAvailable(mData);
24864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        }
24964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa    }
25064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa
2511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    private void dispatchLocations(Location[] locations) {
25264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
2531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        synchronized (mSinkList) {
25464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            sinks = mSinkList;
2551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
2561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
25764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
25864be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            Message message = Message.obtain(
25964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    entry.getValue(),
26064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    DispatcherHandler.DISPATCH_LOCATION,
26164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    new MessageCommand(entry.getKey(), locations, null /*data*/));
26264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            message.sendToTarget();
2631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
2641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
2651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    private void dispatchDiagnosticData(String data) {
26764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
2681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        synchronized(mSinkList) {
26964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            sinks = mSinkList;
2701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
2711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
27264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
27364be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            Message message = Message.obtain(
27464be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    entry.getValue(),
27564be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    DispatcherHandler.DISPATCH_DIAGNOSTIC_DATA,
27664be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                    new MessageCommand(entry.getKey(), null /*locations*/, data));
27764be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa            message.sendToTarget();
2781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
2791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
2801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
281