summaryrefslogtreecommitdiffstats
path: root/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java')
-rw-r--r--tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java445
1 files changed, 445 insertions, 0 deletions
diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java b/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java
new file mode 100644
index 0000000..e7fdc494
--- /dev/null
+++ b/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.locationtracker;
+
+import com.google.android.locationtracker.data.TrackerDataHelper;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.preference.PreferenceManager;
+import android.telephony.CellLocation;
+import android.telephony.PhoneStateListener;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaCellLocation;
+import android.telephony.gsm.GsmCellLocation;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Location Tracking service
+ *
+ * Records location updates for all registered location providers, and cell
+ * location updates
+ */
+public class TrackerService extends Service {
+
+ private List<LocationTrackingListener> mListeners;
+
+ private static final String LOG_TAG = TrackerActivity.LOG_TAG;
+
+ // controls which location providers to track
+ private Set<String> mTrackedProviders;
+
+ private TrackerDataHelper mTrackerData;
+
+ private TelephonyManager mTelephonyManager;
+ private Location mNetworkLocation;
+
+ // Handlers and Receivers for phone and network state
+ private NetworkStateBroadcastReceiver mNetwork;
+ private static final String CELL_PROVIDER_TAG = "cell";
+ // signal strength updates
+ private static final String SIGNAL_PROVIDER_TAG = "signal";
+ private static final String WIFI_PROVIDER_TAG = "wifi";
+ // tracking tag for data connectivity issues
+ private static final String DATA_CONN_PROVIDER_TAG = "data";
+
+ // preference constants
+ private static final String MIN_TIME_PREF = "mintime_preference";
+ private static final String MIN_DIS_PREF = "mindistance_preference";
+ private static final String GPS_PREF = "gps_preference";
+ private static final String NETWORK_PREF = "network_preference";
+ private static final String SIGNAL_PREF = "signal_preference";
+ private static final String DEBUG_PREF = "advanced_log_preference";
+
+ private PreferenceListener mPrefListener;
+
+ public TrackerService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // ignore - nothing to do
+ return null;
+ }
+
+ /**
+ * registers location listeners
+ *
+ * @param intent
+ * @param startId
+ */
+ @Override
+ public void onStart(Intent intent, int startId) {
+ super.onStart(intent, startId);
+ mNetworkLocation = null;
+
+ initLocationListeners();
+ Toast.makeText(this, "Tracking service started", Toast.LENGTH_SHORT);
+ }
+
+ private synchronized void initLocationListeners() {
+ mTrackerData = new TrackerDataHelper(this);
+ LocationManager lm = getLocationManager();
+
+ mTrackedProviders = getTrackedProviders();
+
+ List<String> locationProviders = lm.getAllProviders();
+ mListeners = new ArrayList<LocationTrackingListener>(
+ locationProviders.size());
+
+ long minUpdateTime = getLocationUpdateTime();
+ float minDistance = getLocationMinDistance();
+
+ for (String providerName : locationProviders) {
+ if (mTrackedProviders.contains(providerName)) {
+ Log.d(LOG_TAG, "Adding location listener for provider " +
+ providerName);
+ if (doDebugLogging()) {
+ mTrackerData.writeEntry("init", String.format(
+ "start listening to %s : %d ms; %f meters",
+ providerName, minUpdateTime, minDistance));
+ }
+ LocationTrackingListener listener =
+ new LocationTrackingListener();
+ lm.requestLocationUpdates(providerName, minUpdateTime,
+ minDistance, listener);
+ mListeners.add(listener);
+ }
+ }
+ mTelephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
+
+ if (doDebugLogging()) {
+ // register for cell location updates
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_LOCATION);
+
+ // Register for Network (Wifi or Mobile) updates
+ mNetwork = new NetworkStateBroadcastReceiver();
+ IntentFilter mIntentFilter;
+ mIntentFilter = new IntentFilter();
+ mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+ mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ mIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ Log.d(LOG_TAG, "registering receiver");
+ registerReceiver(mNetwork, mIntentFilter);
+ }
+
+ if (trackSignalStrength()) {
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+ }
+
+ // register for preference changes, so we can restart listeners on
+ // pref changes
+ mPrefListener = new PreferenceListener();
+ getPreferences().registerOnSharedPreferenceChangeListener(mPrefListener);
+ }
+
+ private Set<String> getTrackedProviders() {
+ Set<String> providerSet = new HashSet<String>();
+
+ if (trackGPS()) {
+ providerSet.add(LocationManager.GPS_PROVIDER);
+ }
+ if (trackNetwork()) {
+ providerSet.add(LocationManager.NETWORK_PROVIDER);
+ }
+ return providerSet;
+ }
+
+ private SharedPreferences getPreferences() {
+ return PreferenceManager.getDefaultSharedPreferences(this);
+ }
+
+ private boolean trackNetwork() {
+ return getPreferences().getBoolean(NETWORK_PREF, true);
+ }
+
+ private boolean trackGPS() {
+ return getPreferences().getBoolean(GPS_PREF, true);
+ }
+
+ private boolean doDebugLogging() {
+ return getPreferences().getBoolean(DEBUG_PREF, true);
+ }
+
+ private boolean trackSignalStrength() {
+ return getPreferences().getBoolean(SIGNAL_PREF, true);
+ }
+
+ private float getLocationMinDistance() {
+ try {
+ String disString = getPreferences().getString(MIN_DIS_PREF, "0");
+ return Float.parseFloat(disString);
+ }
+ catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Invalid preference for location min distance", e);
+ }
+ return 0;
+ }
+
+ private long getLocationUpdateTime() {
+ try {
+ String timeString = getPreferences().getString(MIN_TIME_PREF, "0");
+ long secondsTime = Long.valueOf(timeString);
+ return secondsTime * 1000;
+ }
+ catch (NumberFormatException e) {
+ Log.e(LOG_TAG, "Invalid preference for location min time", e);
+ }
+ return 0;
+ }
+
+ /**
+ * Shuts down this service
+ */
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(LOG_TAG, "Removing location listeners");
+ stopListeners();
+ Toast.makeText(this, "Tracking service stopped", Toast.LENGTH_SHORT);
+ }
+
+ /**
+ * De-registers all location listeners, closes persistent storage
+ */
+ protected synchronized void stopListeners() {
+ LocationManager lm = getLocationManager();
+ if (mListeners != null) {
+ for (LocationTrackingListener listener : mListeners) {
+ lm.removeUpdates(listener);
+ }
+ mListeners.clear();
+ }
+ mListeners = null;
+
+ // stop cell state listener
+ if (mTelephonyManager != null) {
+ mTelephonyManager.listen(mPhoneStateListener, 0);
+ }
+
+ // stop network/wifi listener
+ if (mNetwork != null) {
+ unregisterReceiver(mNetwork);
+ }
+ mNetwork = null;
+
+ mTrackerData = null;
+ if (mPrefListener != null) {
+ getPreferences().unregisterOnSharedPreferenceChangeListener(mPrefListener);
+ mPrefListener = null;
+ }
+ }
+
+ private LocationManager getLocationManager() {
+ return (LocationManager) getSystemService(Context.LOCATION_SERVICE);
+ }
+
+ /**
+ * Determine the current distance from given location to the last
+ * approximated network location
+ *
+ * @param location - new location
+ *
+ * @return float distance in meters
+ */
+ private synchronized float getDistanceFromNetwork(Location location) {
+ float value = 0;
+ if (mNetworkLocation != null) {
+ value = location.distanceTo(mNetworkLocation);
+ }
+ if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
+ mNetworkLocation = location;
+ }
+ return value;
+ }
+
+ private class LocationTrackingListener implements LocationListener {
+
+ /**
+ * Writes details of location update to tracking file, including
+ * recording the distance between this location update and the last
+ * network location update
+ *
+ * @param location - new location
+ */
+ public void onLocationChanged(Location location) {
+ if (location == null) {
+ return;
+ }
+ float distance = getDistanceFromNetwork(location);
+ mTrackerData.writeEntry(location, distance);
+ }
+
+ /**
+ * Writes update to tracking file
+ *
+ * @param provider - name of disabled provider
+ */
+ public void onProviderDisabled(String provider) {
+ if (doDebugLogging()) {
+ mTrackerData.writeEntry(provider, "provider disabled");
+ }
+ }
+
+ /**
+ * Writes update to tracking file
+ *
+ * @param provider - name of enabled provider
+ */
+ public void onProviderEnabled(String provider) {
+ if (doDebugLogging()) {
+ mTrackerData.writeEntry(provider, "provider enabled");
+ }
+ }
+
+ /**
+ * Writes update to tracking file
+ *
+ * @param provider - name of provider whose status changed
+ * @param status - new status
+ * @param extras - optional set of extra status messages
+ */
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ if (doDebugLogging()) {
+ mTrackerData.writeEntry(provider, "status change: " + status);
+ }
+ }
+ }
+
+ PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCellLocationChanged(CellLocation location) {
+ try {
+ if (location instanceof GsmCellLocation) {
+ GsmCellLocation cellLocation = (GsmCellLocation)location;
+ String updateMsg = "cid=" + cellLocation.getCid() +
+ ", lac=" + cellLocation.getLac();
+ mTrackerData.writeEntry(CELL_PROVIDER_TAG, updateMsg);
+ } else if (location instanceof CdmaCellLocation) {
+ CdmaCellLocation cellLocation = (CdmaCellLocation)location;
+ String updateMsg = "BID=" + cellLocation.getBaseStationId() +
+ ", SID=" + cellLocation.getSystemId() +
+ ", NID=" + cellLocation.getNetworkId() +
+ ", lat=" + cellLocation.getBaseStationLatitude() +
+ ", long=" + cellLocation.getBaseStationLongitude() +
+ ", SID=" + cellLocation.getSystemId() +
+ ", NID=" + cellLocation.getNetworkId();
+ mTrackerData.writeEntry(CELL_PROVIDER_TAG, updateMsg);
+ }
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Exception in CellStateHandler.handleMessage:", e);
+ }
+ }
+
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+ String updateMsg = "cdma dBM=" + signalStrength.getCdmaDbm();
+ mTrackerData.writeEntry(SIGNAL_PROVIDER_TAG, updateMsg);
+ } else if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
+ String updateMsg = "gsm signal=" + signalStrength.getGsmSignalStrength();
+ mTrackerData.writeEntry(SIGNAL_PROVIDER_TAG, updateMsg);
+ }
+ }
+ };
+
+ /**
+ * Listener + recorder for mobile or wifi updates
+ */
+ private class NetworkStateBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ WifiManager wifiManager =
+ (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ List<ScanResult> wifiScanResults = wifiManager.getScanResults();
+ String updateMsg = "num scan results=" +
+ (wifiScanResults == null ? "0" : wifiScanResults.size());
+ mTrackerData.writeEntry(WIFI_PROVIDER_TAG, updateMsg);
+
+ } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ String updateMsg;
+ boolean noConnectivity =
+ intent.getBooleanExtra(
+ ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
+ if (noConnectivity) {
+ updateMsg = "no connectivity";
+ }
+ else {
+ updateMsg = "connection available";
+ }
+ mTrackerData.writeEntry(DATA_CONN_PROVIDER_TAG, updateMsg);
+
+ } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN);
+
+ String stateString = "unknown";
+ switch (state) {
+ case WifiManager.WIFI_STATE_DISABLED:
+ stateString = "disabled";
+ break;
+ case WifiManager.WIFI_STATE_DISABLING:
+ stateString = "disabling";
+ break;
+ case WifiManager.WIFI_STATE_ENABLED:
+ stateString = "enabled";
+ break;
+ case WifiManager.WIFI_STATE_ENABLING:
+ stateString = "enabling";
+ break;
+ }
+ mTrackerData.writeEntry(WIFI_PROVIDER_TAG,
+ "state = " + stateString);
+ }
+ }
+ }
+
+ private class PreferenceListener implements OnSharedPreferenceChangeListener {
+
+ public void onSharedPreferenceChanged(
+ SharedPreferences sharedPreferences, String key) {
+ Log.d(LOG_TAG, "restarting listeners due to preference change");
+ synchronized (TrackerService.this) {
+ stopListeners();
+ initLocationListeners();
+ }
+ }
+ }
+}