1c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood/*
28ab8b411b81e4581060a31a97a0cb204a803b2e5Mike Lockwood * Copyright (C) 2008 The Android Open Source Project
3c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood *
4c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
5c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * you may not use this file except in compliance with the License.
6c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * You may obtain a copy of the License at
7c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood *
8c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
9c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood *
10c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * Unless required by applicable law or agreed to in writing, software
11c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
12c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * See the License for the specific language governing permissions and
14c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * limitations under the License.
15c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood */
16c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
17191d898468d2f4910a684f429bec518320843744Mike Lockwoodpackage com.android.locationtracker;
18c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
191e47b321dd5977b30f72d49a900b882891347be9Victoria Leaseimport com.android.locationtracker.data.TrackerDataHelper;
201e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
21c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.app.Service;
22c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.content.BroadcastReceiver;
23c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.content.Context;
24c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.content.Intent;
25c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.content.IntentFilter;
26c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.content.SharedPreferences;
27c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.content.SharedPreferences.OnSharedPreferenceChangeListener;
28c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.location.Location;
29c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.location.LocationListener;
30c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.location.LocationManager;
31c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.net.ConnectivityManager;
32c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.net.wifi.ScanResult;
33c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.net.wifi.WifiManager;
34c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.os.Bundle;
35c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.os.IBinder;
36c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.preference.PreferenceManager;
37c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.telephony.CellLocation;
38c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.telephony.PhoneStateListener;
39c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.telephony.SignalStrength;
40c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.telephony.TelephonyManager;
41c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.telephony.cdma.CdmaCellLocation;
42c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.telephony.gsm.GsmCellLocation;
43c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.util.Log;
44c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport android.widget.Toast;
45c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
461e47b321dd5977b30f72d49a900b882891347be9Victoria Leaseimport java.util.ArrayList;
471e47b321dd5977b30f72d49a900b882891347be9Victoria Leaseimport java.util.HashSet;
48c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodimport java.util.List;
491e47b321dd5977b30f72d49a900b882891347be9Victoria Leaseimport java.util.Set;
50c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
51c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood/**
52c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * Location Tracking service
53c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood *
54c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * Records location updates for all registered location providers, and cell
55c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood * location updates
56c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood */
57c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwoodpublic class TrackerService extends Service {
58c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
591e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private List<LocationTrackingListener> mListeners;
60c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
61c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String LOG_TAG = TrackerActivity.LOG_TAG;
62c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
631e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    // controls which location providers to track
641e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private Set<String> mTrackedProviders;
651e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
66c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private TrackerDataHelper mTrackerData;
67c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
68c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private TelephonyManager mTelephonyManager;
69c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private Location mNetworkLocation;
70c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
71c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    // Handlers and Receivers for phone and network state
72c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private NetworkStateBroadcastReceiver mNetwork;
73c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String CELL_PROVIDER_TAG = "cell";
74c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    // signal strength updates
75c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String SIGNAL_PROVIDER_TAG = "signal";
76c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String WIFI_PROVIDER_TAG = "wifi";
77c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    // tracking tag for data connectivity issues
78c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String DATA_CONN_PROVIDER_TAG = "data";
79c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
80c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    // preference constants
81c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String MIN_TIME_PREF = "mintime_preference";
821e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private static final String MIN_DIS_PREF = "mindistance_preference";
83c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String GPS_PREF = "gps_preference";
84c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String NETWORK_PREF = "network_preference";
85c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String SIGNAL_PREF = "signal_preference";
86c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private static final String DEBUG_PREF = "advanced_log_preference";
87c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
88c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private PreferenceListener mPrefListener;
89c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
90c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    public TrackerService() {
91c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
92c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
93c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    @Override
94c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    public IBinder onBind(Intent intent) {
95c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        // ignore - nothing to do
96c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        return null;
97c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
98c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
99c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    /**
100c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * registers location listeners
101c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     *
102c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * @param intent
103c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * @param startId
104c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     */
105c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    @Override
1061e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    public void onStart(Intent intent, int startId) {
1071e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        super.onStart(intent, startId);
108c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        mNetworkLocation = null;
109c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
110c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        initLocationListeners();
111c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        Toast.makeText(this, "Tracking service started", Toast.LENGTH_SHORT);
112c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
113c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
114c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private synchronized void initLocationListeners() {
115c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        mTrackerData = new TrackerDataHelper(this);
116722876a989fe1c1514dfacecd1b384f8a47c2816David Hu        LocationManager lm = getLocationManager();
117c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
1181e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        mTrackedProviders = getTrackedProviders();
119722876a989fe1c1514dfacecd1b384f8a47c2816David Hu
1201e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        List<String> locationProviders = lm.getAllProviders();
1211e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        mListeners = new ArrayList<LocationTrackingListener>(
1221e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                locationProviders.size());
123722876a989fe1c1514dfacecd1b384f8a47c2816David Hu
1241e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        long minUpdateTime = getLocationUpdateTime();
1251e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        float minDistance = getLocationMinDistance();
1261e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
1271e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        for (String providerName : locationProviders) {
1281e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            if (mTrackedProviders.contains(providerName)) {
1291e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                Log.d(LOG_TAG, "Adding location listener for provider " +
1301e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                        providerName);
1311e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                if (doDebugLogging()) {
1321e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                    mTrackerData.writeEntry("init", String.format(
1331e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                            "start listening to %s : %d ms; %f meters",
1341e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                            providerName, minUpdateTime, minDistance));
1351e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                }
1361e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                LocationTrackingListener listener =
1371e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                    new LocationTrackingListener();
1381e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                lm.requestLocationUpdates(providerName, minUpdateTime,
1391e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                        minDistance, listener);
1401e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                mListeners.add(listener);
1411e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            }
1421e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        }
143c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        mTelephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
144c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
145c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (doDebugLogging()) {
146c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            // register for cell location updates
147c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_LOCATION);
148c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
149c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            // Register for Network (Wifi or Mobile) updates
150c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mNetwork = new NetworkStateBroadcastReceiver();
151c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            IntentFilter mIntentFilter;
152c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mIntentFilter = new IntentFilter();
153c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
154c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
155c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
156c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            Log.d(LOG_TAG, "registering receiver");
157c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            registerReceiver(mNetwork, mIntentFilter);
158c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
159c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
160c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (trackSignalStrength()) {
161c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mTelephonyManager.listen(mPhoneStateListener,
162c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
163c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
164c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
165c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        // register for preference changes, so we can restart listeners on
166c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        // pref changes
167c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        mPrefListener = new PreferenceListener();
168c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        getPreferences().registerOnSharedPreferenceChangeListener(mPrefListener);
169c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
170c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
1711e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private Set<String> getTrackedProviders() {
1721e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        Set<String> providerSet = new HashSet<String>();
1731e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
1741e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        if (trackGPS()) {
1751e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            providerSet.add(LocationManager.GPS_PROVIDER);
1761e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        }
1771e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        if (trackNetwork()) {
1781e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            providerSet.add(LocationManager.NETWORK_PROVIDER);
1791e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        }
1801e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        return providerSet;
1811e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    }
1821e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
183c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private SharedPreferences getPreferences() {
184c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        return PreferenceManager.getDefaultSharedPreferences(this);
185c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
186c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
1871e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private boolean trackNetwork() {
1881e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        return getPreferences().getBoolean(NETWORK_PREF, true);
1891e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    }
1901e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
1911e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private boolean trackGPS() {
1921e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        return getPreferences().getBoolean(GPS_PREF, true);
1931e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    }
1941e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
195c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private boolean doDebugLogging() {
19627a7a6cbfeebf7ca6a97efaed43500139e9d23dcMike Lockwood        return getPreferences().getBoolean(DEBUG_PREF, false);
197c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
198c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
199c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private boolean trackSignalStrength() {
20027a7a6cbfeebf7ca6a97efaed43500139e9d23dcMike Lockwood        return getPreferences().getBoolean(SIGNAL_PREF, false);
201c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
202c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
2031e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    private float getLocationMinDistance() {
2041e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        try {
2051e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            String disString = getPreferences().getString(MIN_DIS_PREF, "0");
2061e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            return Float.parseFloat(disString);
2071e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        }
2081e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        catch (NumberFormatException e) {
2091e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            Log.e(LOG_TAG, "Invalid preference for location min distance", e);
2101e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        }
2111e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        return 0;
2121e47b321dd5977b30f72d49a900b882891347be9Victoria Lease    }
2131e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
214c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private long getLocationUpdateTime() {
215c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        try {
216c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            String timeString = getPreferences().getString(MIN_TIME_PREF, "0");
217c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            long secondsTime = Long.valueOf(timeString);
218c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            return secondsTime * 1000;
219c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
220c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        catch (NumberFormatException e) {
221c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            Log.e(LOG_TAG, "Invalid preference for location min time", e);
222c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
223c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        return 0;
224c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
225c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
226c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    /**
227c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * Shuts down this service
228c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     */
229c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    @Override
230c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    public void onDestroy() {
231c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        super.onDestroy();
232c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        Log.d(LOG_TAG, "Removing location listeners");
233c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        stopListeners();
234c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        Toast.makeText(this, "Tracking service stopped", Toast.LENGTH_SHORT);
235c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
236c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
237c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    /**
238c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * De-registers all location listeners, closes persistent storage
239c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     */
240c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    protected synchronized void stopListeners() {
241c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        LocationManager lm = getLocationManager();
2421e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        if (mListeners != null) {
2431e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            for (LocationTrackingListener listener : mListeners) {
2441e47b321dd5977b30f72d49a900b882891347be9Victoria Lease                lm.removeUpdates(listener);
2451e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            }
2461e47b321dd5977b30f72d49a900b882891347be9Victoria Lease            mListeners.clear();
247c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
2481e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        mListeners = null;
249c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
250c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        // stop cell state listener
251c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (mTelephonyManager != null) {
252c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mTelephonyManager.listen(mPhoneStateListener, 0);
2531e47b321dd5977b30f72d49a900b882891347be9Victoria Lease        }
2541e47b321dd5977b30f72d49a900b882891347be9Victoria Lease
255c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        // stop network/wifi listener
256c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (mNetwork != null) {
257c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            unregisterReceiver(mNetwork);
258c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
259c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        mNetwork = null;
260c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
261c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        mTrackerData = null;
262c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (mPrefListener != null) {
263c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            getPreferences().unregisterOnSharedPreferenceChangeListener(mPrefListener);
264c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mPrefListener = null;
265c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
266c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
267c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
268c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private LocationManager getLocationManager() {
269c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        return (LocationManager) getSystemService(Context.LOCATION_SERVICE);
270c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
271c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
272c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    /**
273c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * Determine the current distance from given location to the last
274c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * approximated network location
275c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     *
276c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * @param location - new location
277c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     *
278c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * @return float distance in meters
279c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     */
280c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private synchronized float getDistanceFromNetwork(Location location) {
281c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        float value = 0;
282c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (mNetworkLocation != null) {
283c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            value = location.distanceTo(mNetworkLocation);
284c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
285c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
286c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mNetworkLocation = location;
287c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
288c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        return value;
289c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
290c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
291c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private class LocationTrackingListener implements LocationListener {
292c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
293c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        /**
294c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * Writes details of location update to tracking file, including
295c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * recording the distance between this location update and the last
296c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * network location update
297c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         *
298c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * @param location - new location
299c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         */
300c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onLocationChanged(Location location) {
301c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            if (location == null) {
302c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                return;
303c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
304c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            float distance = getDistanceFromNetwork(location);
305c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            mTrackerData.writeEntry(location, distance);
306c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
307c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
308c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        /**
309c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * Writes update to tracking file
310c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         *
311c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * @param provider - name of disabled provider
312c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         */
313c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onProviderDisabled(String provider) {
314c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            if (doDebugLogging()) {
315c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(provider, "provider disabled");
316c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
317c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
318c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
319c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        /**
320c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * Writes update to tracking file
3211e47b321dd5977b30f72d49a900b882891347be9Victoria Lease         *
322c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * @param provider - name of enabled provider
323c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         */
324c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onProviderEnabled(String provider) {
325c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            if (doDebugLogging()) {
326c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(provider,  "provider enabled");
327c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
328c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
329c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
330c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        /**
3311e47b321dd5977b30f72d49a900b882891347be9Victoria Lease         * Writes update to tracking file
3321e47b321dd5977b30f72d49a900b882891347be9Victoria Lease         *
333c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * @param provider - name of provider whose status changed
334c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * @param status - new status
335c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         * @param extras - optional set of extra status messages
336c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood         */
337c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onStatusChanged(String provider, int status, Bundle extras) {
338c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            if (doDebugLogging()) {
339c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(provider,  "status change: " + status);
340c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
341c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
342c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
343c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
344c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
345c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        @Override
346c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onCellLocationChanged(CellLocation location) {
347c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            try {
348c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                if (location instanceof GsmCellLocation) {
349c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    GsmCellLocation cellLocation = (GsmCellLocation)location;
350c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    String updateMsg = "cid=" + cellLocation.getCid() +
351c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", lac=" + cellLocation.getLac();
352c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    mTrackerData.writeEntry(CELL_PROVIDER_TAG, updateMsg);
353c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                } else if (location instanceof CdmaCellLocation) {
354c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    CdmaCellLocation cellLocation = (CdmaCellLocation)location;
355c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    String updateMsg = "BID=" + cellLocation.getBaseStationId() +
356c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", SID=" + cellLocation.getSystemId() +
357c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", NID=" + cellLocation.getNetworkId() +
358c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", lat=" + cellLocation.getBaseStationLatitude() +
359c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", long=" + cellLocation.getBaseStationLongitude() +
360c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", SID=" + cellLocation.getSystemId() +
361c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ", NID=" + cellLocation.getNetworkId();
362c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    mTrackerData.writeEntry(CELL_PROVIDER_TAG, updateMsg);
363c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                }
364c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            } catch (Exception e) {
365c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                Log.e(LOG_TAG, "Exception in CellStateHandler.handleMessage:", e);
366c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
367c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
368c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
369c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
370c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
371c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                String updateMsg = "cdma dBM=" + signalStrength.getCdmaDbm();
372c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(SIGNAL_PROVIDER_TAG, updateMsg);
373c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            } else if  (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
374c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                String updateMsg = "gsm signal=" + signalStrength.getGsmSignalStrength();
375c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(SIGNAL_PROVIDER_TAG, updateMsg);
376c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
377c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
378c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    };
379c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
380c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    /**
381c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     * Listener + recorder for mobile or wifi updates
382c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood     */
383c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private class NetworkStateBroadcastReceiver extends BroadcastReceiver {
384c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        @Override
385c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onReceive(Context context, Intent intent) {
386c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            String action = intent.getAction();
387c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
388c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
389c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                WifiManager wifiManager =
390c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
391c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                List<ScanResult> wifiScanResults = wifiManager.getScanResults();
392c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                String updateMsg = "num scan results=" +
393c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    (wifiScanResults == null ? "0" : wifiScanResults.size());
394c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(WIFI_PROVIDER_TAG, updateMsg);
395c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
396c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
397c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                String updateMsg;
398c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                boolean noConnectivity =
399c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    intent.getBooleanExtra(
400c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
401c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                if (noConnectivity) {
402c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    updateMsg = "no connectivity";
403c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                }
404c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                else {
405c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    updateMsg = "connection available";
406c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                }
407c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(DATA_CONN_PROVIDER_TAG, updateMsg);
408c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
409c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
410c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
411c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    WifiManager.WIFI_STATE_UNKNOWN);
412c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
413c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                String stateString = "unknown";
414c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                switch (state) {
415c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    case WifiManager.WIFI_STATE_DISABLED:
416c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        stateString = "disabled";
417c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        break;
418c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    case WifiManager.WIFI_STATE_DISABLING:
419c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        stateString = "disabling";
420c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        break;
421c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    case WifiManager.WIFI_STATE_ENABLED:
422c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        stateString = "enabled";
423c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        break;
424c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                    case WifiManager.WIFI_STATE_ENABLING:
425c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        stateString = "enabling";
426c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        break;
427c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                }
428c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                mTrackerData.writeEntry(WIFI_PROVIDER_TAG,
429c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                        "state = " + stateString);
430c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
431c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
432c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
433c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
434c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    private class PreferenceListener implements OnSharedPreferenceChangeListener {
435c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood
436c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        public void onSharedPreferenceChanged(
437c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                SharedPreferences sharedPreferences, String key) {
438c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            Log.d(LOG_TAG, "restarting listeners due to preference change");
439c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            synchronized (TrackerService.this) {
440c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                stopListeners();
441c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood                initLocationListeners();
442c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood            }
443c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood        }
444c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood    }
445c9d3be3f0e10b62fa6d4899ce827866299d41783Mike Lockwood}
446