summaryrefslogtreecommitdiffstats
path: root/location/java/com
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2010-03-22 14:23:26 -0400
committerMike Lockwood <lockwood@android.com>2010-03-22 15:14:31 -0400
commit62a8fc159ad8d8044f3cde6ee6d46e9cc56b823f (patch)
tree8137c0a75510af3d5e48c6b8ab1ba91e88c1e96c /location/java/com
parentfb0de34a47a435b57075d7a72cbc40a2daf5ee6c (diff)
downloadframeworks_base-62a8fc159ad8d8044f3cde6ee6d46e9cc56b823f.zip
frameworks_base-62a8fc159ad8d8044f3cde6ee6d46e9cc56b823f.tar.gz
frameworks_base-62a8fc159ad8d8044f3cde6ee6d46e9cc56b823f.tar.bz2
GpsLocationProvider: Do our work in a Handler running in a separate thread.
To avoid adding a new thread to the system, we take the functionality that was in GpsNetworkThread for downloading NTP time and XTRA data and include this in the new thread as well. BUG: 2531728 Change-Id: I2a26b7f0aae0c60faceb36dc6bc29c915c039ae6 Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'location/java/com')
-rwxr-xr-xlocation/java/com/android/internal/location/GpsLocationProvider.java423
1 files changed, 228 insertions, 195 deletions
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 44a5a6b..8dc206c 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -35,8 +35,12 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.SntpClient;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -65,13 +69,13 @@ import java.util.Map.Entry;
*
* {@hide}
*/
-public class GpsLocationProvider implements LocationProviderInterface {
+public class GpsLocationProvider implements LocationProviderInterface, Runnable {
private static final String TAG = "GpsLocationProvider";
private static final boolean DEBUG = false;
private static final boolean VERBOSE = false;
-
+
/**
* Broadcast intent action indicating that the GPS has either been
* enabled or disabled. An intent extra provides this state as a boolean,
@@ -155,6 +159,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
private static final int AGPS_DATA_CONNECTION_OPENING = 1;
private static final int AGPS_DATA_CONNECTION_OPEN = 2;
+ // Handler messages
+ private static final int CHECK_LOCATION = 1;
+ private static final int ENABLE = 2;
+ private static final int ENABLE_TRACKING = 3;
+ private static final int UPDATE_NETWORK_STATE = 4;
+ private static final int INJECT_NTP_TIME = 5;
+ private static final int DOWNLOAD_XTRA_DATA = 6;
+ private static final int UPDATE_LOCATION = 7;
+ private static final int ADD_LISTENER = 8;
+ private static final int REMOVE_LISTENER = 9;
+
private static final String PROPERTIES_FILE = "/etc/gps.conf";
private int mLocationFlags = LOCATION_INVALID;
@@ -180,6 +195,11 @@ public class GpsLocationProvider implements LocationProviderInterface {
// true if we have network connectivity
private boolean mNetworkAvailable;
+ // flags to trigger NTP or XTRA data download when network becomes available
+ // initialized to true so we do NTP and XTRA when the network comes up after booting
+ private boolean mInjectNtpTimePending = true;
+ private boolean mDownloadXtraDataPending = true;
+
// true if GPS is navigating
private boolean mNavigating;
@@ -215,9 +235,9 @@ public class GpsLocationProvider implements LocationProviderInterface {
private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
private Bundle mLocationExtras = new Bundle();
private ArrayList<Listener> mListeners = new ArrayList<Listener>();
- private GpsEventThread mEventThread;
- private GpsNetworkThread mNetworkThread;
- private Object mNetworkThreadLock = new Object();
+
+ private Handler mHandler;
+ private Thread mEventThread;
private String mAGpsApn;
private int mAGpsDataConnectionState;
@@ -333,11 +353,6 @@ public class GpsLocationProvider implements LocationProviderInterface {
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ALARM_WAKEUP);
- intentFilter.addAction(ALARM_TIMEOUT);
- context.registerReceiver(mBroadcastReciever, intentFilter);
-
mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
// Battery statistics service to be notified when GPS turns on or off
@@ -373,6 +388,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
} catch (IOException e) {
Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
}
+
+ Thread thread = new Thread(null, this, "GpsLocationProvider");
+ thread.start();
+ }
+
+ private void initialize() {
+ // register our receiver on our thread rather than the main thread
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ALARM_WAKEUP);
+ intentFilter.addAction(ALARM_TIMEOUT);
+ mContext.registerReceiver(mBroadcastReciever, intentFilter);
}
/**
@@ -391,6 +417,14 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
public void updateNetworkState(int state, NetworkInfo info) {
+ mHandler.removeMessages(UPDATE_NETWORK_STATE);
+ Message m = Message.obtain(mHandler, UPDATE_NETWORK_STATE);
+ m.arg1 = state;
+ m.obj = info;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleUpdateNetworkState(int state, NetworkInfo info) {
mNetworkAvailable = (state == LocationProvider.AVAILABLE);
if (DEBUG) {
@@ -414,10 +448,84 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
- if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
- // signal the network thread when the network becomes available
- mNetworkThread.signal();
- }
+ if (mNetworkAvailable) {
+ if (mInjectNtpTimePending) {
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessage(Message.obtain(mHandler, INJECT_NTP_TIME));
+ }
+ if (mDownloadXtraDataPending) {
+ mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
+ mHandler.sendMessage(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA));
+ }
+ }
+ }
+
+ private void handleInjectNtpTime() {
+ if (!mNetworkAvailable) {
+ // try again when network is up
+ mInjectNtpTimePending = true;
+ return;
+ }
+ mInjectNtpTimePending = false;
+
+ SntpClient client = new SntpClient();
+ long delay;
+
+ if (client.requestTime(mNtpServer, 10000)) {
+ long time = client.getNtpTime();
+ long timeReference = client.getNtpTimeReference();
+ int certainty = (int)(client.getRoundTripTime()/2);
+ long now = System.currentTimeMillis();
+ long systemTimeOffset = time - now;
+
+ Log.d(TAG, "NTP server returned: "
+ + time + " (" + new Date(time)
+ + ") reference: " + timeReference
+ + " certainty: " + certainty
+ + " system time offset: " + systemTimeOffset);
+
+ // sanity check NTP time and do not use if it is too far from system time
+ if (systemTimeOffset < 0) {
+ systemTimeOffset = -systemTimeOffset;
+ }
+ if (systemTimeOffset < MAX_NTP_SYSTEM_TIME_OFFSET) {
+ native_inject_time(time, timeReference, certainty);
+ } else {
+ Log.e(TAG, "NTP time differs from system time by " + systemTimeOffset
+ + "ms. Ignoring.");
+ }
+ delay = NTP_INTERVAL;
+ } else {
+ if (DEBUG) Log.d(TAG, "requestTime failed");
+ delay = RETRY_INTERVAL;
+ }
+
+ // send delayed message for next NTP injection
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+ }
+
+ private void handleDownloadXtraData() {
+ if (!mDownloadXtraDataPending) {
+ // try again when network is up
+ mDownloadXtraDataPending = true;
+ return;
+ }
+ mDownloadXtraDataPending = false;
+
+
+ GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
+ byte[] data = xtraDownloader.downloadXtraData();
+ if (data != null) {
+ if (DEBUG) {
+ Log.d(TAG, "calling native_inject_xtra_data");
+ }
+ native_inject_xtra_data(data, data.length);
+ } else {
+ // try again later
+ mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
+ mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
+ }
}
/**
@@ -425,6 +533,13 @@ public class GpsLocationProvider implements LocationProviderInterface {
* Someday we might use this for network location injection to aid the GPS
*/
public void updateLocation(Location location) {
+ mHandler.removeMessages(UPDATE_LOCATION);
+ Message m = Message.obtain(mHandler, UPDATE_LOCATION);
+ m.obj = location;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleUpdateLocation(Location location) {
if (location.hasAccuracy()) {
native_inject_location(location.getLatitude(), location.getLongitude(),
location.getAccuracy());
@@ -513,8 +628,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
* must be handled. Hardware may be started up
* when the provider is enabled.
*/
- public synchronized void enable() {
- if (DEBUG) Log.d(TAG, "enable");
+ public void enable() {
+ synchronized (mHandler) {
+ mHandler.removeMessages(ENABLE);
+ Message m = Message.obtain(mHandler, ENABLE);
+ m.arg1 = 1;
+ mHandler.sendMessage(m);
+ }
+ }
+
+ private void handleEnable() {
+ if (DEBUG) Log.d(TAG, "handleEnable");
if (mEnabled) return;
mEnabled = native_init();
@@ -529,16 +653,6 @@ public class GpsLocationProvider implements LocationProviderInterface {
// run event listener thread while we are enabled
mEventThread = new GpsEventThread();
mEventThread.start();
-
- if (requiresNetwork()) {
- // run network thread for NTP and XTRA support
- if (mNetworkThread == null) {
- mNetworkThread = new GpsNetworkThread();
- mNetworkThread.start();
- } else {
- mNetworkThread.signal();
- }
- }
} else {
Log.w(TAG, "Failed to enable location provider");
}
@@ -549,8 +663,17 @@ public class GpsLocationProvider implements LocationProviderInterface {
* need not be handled. Hardware may be shut
* down while the provider is disabled.
*/
- public synchronized void disable() {
- if (DEBUG) Log.d(TAG, "disable");
+ public void disable() {
+ synchronized (mHandler) {
+ mHandler.removeMessages(ENABLE);
+ Message m = Message.obtain(mHandler, ENABLE);
+ m.arg1 = 0;
+ mHandler.sendMessage(m);
+ }
+ }
+
+ private void handleDisable() {
+ if (DEBUG) Log.d(TAG, "handleEnable");
if (!mEnabled) return;
mEnabled = false;
@@ -567,11 +690,6 @@ public class GpsLocationProvider implements LocationProviderInterface {
mEventThread = null;
}
- if (mNetworkThread != null) {
- mNetworkThread.setDone();
- mNetworkThread = null;
- }
-
// do this before releasing wakelock
native_cleanup();
@@ -610,6 +728,15 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
public void enableLocationTracking(boolean enable) {
+ synchronized (mHandler) {
+ mHandler.removeMessages(ENABLE_TRACKING);
+ Message m = Message.obtain(mHandler, ENABLE_TRACKING);
+ m.arg1 = (enable ? 1 : 0);
+ mHandler.sendMessage(m);
+ }
+ }
+
+ private void handleEnableLocationTracking(boolean enable) {
if (enable) {
mTTFF = 0;
mLastFixTime = 0;
@@ -659,6 +786,12 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
public void addListener(int uid) {
+ Message m = Message.obtain(mHandler, ADD_LISTENER);
+ m.arg1 = uid;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleAddListener(int uid) {
synchronized(mListeners) {
if (mClientUids.indexOfKey(uid) >= 0) {
// Shouldn't be here -- already have this uid.
@@ -677,6 +810,12 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
public void removeListener(int uid) {
+ Message m = Message.obtain(mHandler, REMOVE_LISTENER);
+ m.arg1 = uid;
+ mHandler.sendMessage(m);
+ }
+
+ private void handleRemoveListener(int uid) {
synchronized(mListeners) {
if (mClientUids.indexOfKey(uid) < 0) {
// Shouldn't be here -- don't have this uid.
@@ -700,10 +839,12 @@ public class GpsLocationProvider implements LocationProviderInterface {
return deleteAidingData(extras);
}
if ("force_time_injection".equals(command)) {
- return forceTimeInjection();
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessage(Message.obtain(mHandler, INJECT_NTP_TIME));
+ return true;
}
if ("force_xtra_injection".equals(command)) {
- if (native_supports_xtra() && mNetworkThread != null) {
+ if (native_supports_xtra()) {
xtraDownloadRequest();
return true;
}
@@ -744,16 +885,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
return false;
}
- private boolean forceTimeInjection() {
- if (DEBUG) Log.d(TAG, "forceTimeInjection");
- if (mNetworkThread != null) {
- mNetworkThread.timeInjectRequest();
- return true;
- }
- return false;
- }
-
- public void startNavigating() {
+ private void startNavigating() {
if (!mStarted) {
if (DEBUG) Log.d(TAG, "startNavigating");
mStarted = true;
@@ -784,7 +916,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
- public void stopNavigating() {
+ private void stopNavigating() {
if (DEBUG) Log.d(TAG, "stopNavigating");
if (mStarted) {
mStarted = false;
@@ -1092,11 +1224,13 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
+ /**
+ * called from native code to request XTRA data
+ */
private void xtraDownloadRequest() {
if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
- if (mNetworkThread != null) {
- mNetworkThread.xtraDownloadRequest();
- }
+ mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
+ mHandler.sendMessage(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA));
}
//=============================================================
@@ -1189,6 +1323,10 @@ public class GpsLocationProvider implements LocationProviderInterface {
mNIHandler.handleNiNotification(notification);
}
+ // this thread is used to receive events from the native code.
+ // native_wait_for_event() will callback to us via reportLocation(), reportStatus(), etc.
+ // this is necessary because native code cannot call Java on a thread that the JVM does
+ // not know about.
private class GpsEventThread extends Thread {
public GpsEventThread() {
@@ -1207,157 +1345,52 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
- private class GpsNetworkThread extends Thread {
-
- private long mNextNtpTime = 0;
- private long mNextXtraTime = 0;
- private boolean mTimeInjectRequested = false;
- private boolean mXtraDownloadRequested = false;
- private boolean mDone = false;
-
- public GpsNetworkThread() {
- super("GpsNetworkThread");
- }
-
- public void run() {
- synchronized (mNetworkThreadLock) {
- if (!mDone) {
- runLocked();
- }
- }
- }
-
- public void runLocked() {
- if (DEBUG) Log.d(TAG, "NetworkThread starting");
-
- SntpClient client = new SntpClient();
- GpsXtraDownloader xtraDownloader = null;
-
- if (native_supports_xtra()) {
- xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
- }
-
- // thread exits after disable() is called
- while (!mDone) {
- long waitTime = getWaitTime();
- do {
- synchronized (this) {
- try {
- if (!mNetworkAvailable) {
- if (DEBUG) Log.d(TAG, "NetworkThread wait for network");
- wait();
- } else if (waitTime > 0) {
- if (DEBUG) {
- Log.d(TAG, "NetworkThread wait for " +
- waitTime + "ms");
- }
- wait(waitTime);
- }
- } catch (InterruptedException e) {
- if (DEBUG) {
- Log.d(TAG, "InterruptedException in GpsNetworkThread");
- }
- }
- }
- waitTime = getWaitTime();
- } while (!mDone && ((!mXtraDownloadRequested &&
- !mTimeInjectRequested && waitTime > 0)
- || !mNetworkAvailable));
- if (DEBUG) Log.d(TAG, "NetworkThread out of wake loop");
- if (!mDone) {
- if (mNtpServer != null &&
- (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
- if (DEBUG) {
- Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
- }
- mTimeInjectRequested = false;
- if (client.requestTime(mNtpServer, 10000)) {
- long time = client.getNtpTime();
- long timeReference = client.getNtpTimeReference();
- int certainty = (int)(client.getRoundTripTime()/2);
- long now = System.currentTimeMillis();
- long systemTimeOffset = time - now;
-
- Log.d(TAG, "NTP server returned: "
- + time + " (" + new Date(time)
- + ") reference: " + timeReference
- + " certainty: " + certainty
- + " system time offset: " + systemTimeOffset);
-
- // sanity check NTP time and do not use if it is too far from system time
- if (systemTimeOffset < 0) {
- systemTimeOffset = -systemTimeOffset;
- }
- if (systemTimeOffset < MAX_NTP_SYSTEM_TIME_OFFSET) {
- native_inject_time(time, timeReference, certainty);
- } else {
- Log.e(TAG, "NTP time differs from system time by " + systemTimeOffset
- + "ms. Ignoring.");
- }
- mNextNtpTime = now + NTP_INTERVAL;
- } else {
- if (DEBUG) Log.d(TAG, "requestTime failed");
- mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
- }
+ private final class ProviderHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg)
+ {
+ switch (msg.what) {
+ case ENABLE:
+ if (msg.arg1 == 1) {
+ handleEnable();
+ } else {
+ handleDisable();
}
-
- if ((mXtraDownloadRequested ||
- (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
- && xtraDownloader != null) {
- mXtraDownloadRequested = false;
- byte[] data = xtraDownloader.downloadXtraData();
- if (data != null) {
- if (DEBUG) {
- Log.d(TAG, "calling native_inject_xtra_data");
- }
- native_inject_xtra_data(data, data.length);
- mNextXtraTime = 0;
- } else {
- mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
- }
+ break;
+ case ENABLE_TRACKING:
+ handleEnableLocationTracking(msg.arg1 == 1);
+ break;
+ case UPDATE_NETWORK_STATE:
+ handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
+ break;
+ case INJECT_NTP_TIME:
+ handleInjectNtpTime();
+ break;
+ case DOWNLOAD_XTRA_DATA:
+ if (native_supports_xtra()) {
+ handleDownloadXtraData();
}
- }
+ break;
+ case UPDATE_LOCATION:
+ handleUpdateLocation((Location)msg.obj);
+ break;
+ case ADD_LISTENER:
+ handleAddListener(msg.arg1);
+ break;
+ case REMOVE_LISTENER:
+ handleRemoveListener(msg.arg1);
+ break;
}
- if (DEBUG) Log.d(TAG, "NetworkThread exiting");
- }
-
- synchronized void xtraDownloadRequest() {
- mXtraDownloadRequested = true;
- notify();
- }
-
- synchronized void timeInjectRequest() {
- mTimeInjectRequested = true;
- notify();
- }
-
- synchronized void signal() {
- notify();
- }
-
- synchronized void setDone() {
- if (DEBUG) Log.d(TAG, "stopping NetworkThread");
- mDone = true;
- notify();
}
+ };
- private long getWaitTime() {
- long now = System.currentTimeMillis();
- long waitTime = Long.MAX_VALUE;
- if (mNtpServer != null) {
- waitTime = mNextNtpTime - now;
- }
- if (mNextXtraTime != 0) {
- long xtraWaitTime = mNextXtraTime - now;
- if (xtraWaitTime < waitTime) {
- waitTime = xtraWaitTime;
- }
- }
- if (waitTime < 0) {
- waitTime = 0;
- }
- return waitTime;
- }
+ public void run()
+ {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ initialize();
+ Looper.prepare();
+ mHandler = new ProviderHandler();
+ Looper.loop();
}
// for GPS SV statistics