Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- mateor@mateor-HP-Pavilion-dv6700:~/android/system/CM10b/frameworks/base$ git diff 126a201b051a18bef5e1e700be8c70967001da5c
- diff --git a/core/java/android/provider/Settings.java b/core/java/android/provid
- index 8870944..d82d207 100644
- --- a/core/java/android/provider/Settings.java
- +++ b/core/java/android/provider/Settings.java
- @@ -4708,6 +4708,13 @@ public final class Settings {
- */
- public static final String WIMAX_ON = "wimax_on";
- + /*
- + * Ported from CM10 (by Cuong)
- + * External GPS source/device
- + * @hide
- + */
- + public static final String EXTERNAL_GPS_BT_DEVICE = "0";
- +
- /**
- * This are the settings to be backed up.
- *
- diff --git a/location/java/android/location/ILocationManager.aidl b/location/jav
- index f663e0a..3ee131a 100644
- --- a/location/java/android/location/ILocationManager.aidl
- +++ b/location/java/android/location/ILocationManager.aidl
- @@ -60,6 +60,9 @@ interface ILocationManager
- boolean sendNiResponse(int notifId, int userResponse);
- + // add set gps source--from CM10
- + void setGPSSource(String device);
- +
- // --- deprecated ---
- List<String> getAllProviders();
- List<String> getProviders(in Criteria criteria, boolean enabledOnly);
- diff --git a/location/java/android/location/LocationManager.java b/location/java
- index 5a2f71b..71e22d8 100644
- --- a/location/java/android/location/LocationManager.java
- +++ b/location/java/android/location/LocationManager.java
- @@ -291,6 +291,16 @@ public class LocationManager {
- return new LocationProvider(name, properties);
- }
- + // From CM10-- external GPS
- + public void setGPSSource(String device) {
- + try {
- + mService.setGPSSource(device);
- + } catch (RemoteException e) {
- + Log.e(TAG, e.getMessage());
- + }
- + }
- +
- +
- /**
- * Returns a list of the names of all known location providers.
- * <p>All providers are returned, including ones that are not permitted to
- diff --git a/services/java/com/android/server/LocationManagerService.java b/serv
- index 0f08c56..1a076ea 100644
- --- a/services/java/com/android/server/LocationManagerService.java
- +++ b/services/java/com/android/server/LocationManagerService.java
- @@ -56,12 +56,15 @@ import android.os.SystemClock;
- import android.os.UserHandle;
- import android.os.WorkSource;
- import android.provider.Settings;
- +import android.text.TextUtils;
- import android.util.Log;
- import android.util.Slog;
- import com.android.internal.content.PackageMonitor;
- import com.android.internal.location.ProviderProperties;
- import com.android.internal.location.ProviderRequest;
- +
- +import com.android.server.location.BTGpsLocationProvider;
- import com.android.server.location.GeocoderProxy;
- import com.android.server.location.GeofenceManager;
- import com.android.server.location.GpsLocationProvider;
- @@ -320,6 +323,36 @@ public class LocationManagerService extends ILocationManage
- + "partition. The fallback must also be marked coreApp=\"true\"
- }
- + public void setGPSSource(String device) {
- + synchronized (mLock) {
- + if (mGpsLocationProvider != null &&
- + mProvidersByName.containsKey(mGpsLocationProvider.getName()
- + Slog.i(TAG, "Disable and removing provider " + mGpsLocationProv
- + mGpsLocationProvider.disable();
- + Settings.Secure.setLocationProviderEnabled(mContext.getContentR
- + LocationManager.GPS_PROVIDER, false);
- + removeProvider(mGpsLocationProvider);
- + mGpsLocationProvider = null;
- + }
- + Slog.i(TAG, "Setting GPS Source to: " + device);
- + if ("0".equals(device)) {
- + if (mGpsLocationProvider != null && !GpsLocationProvider.isSupp
- + return;
- + GpsLocationProvider gpsProvider = new GpsLocationProvider(mCont
- + mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
- + mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
- + addProvider(gpsProvider);
- + mGpsLocationProvider = gpsProvider;
- + } else {
- + BTGpsLocationProvider gpsProvider = new BTGpsLocationProvider(m
- + mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
- + mNetInitiatedListener = null;
- + addProvider(gpsProvider);
- + mGpsLocationProvider = gpsProvider;
- + }
- + }
- + }
- +
- private void loadProvidersLocked() {
- // create a passive location provider, which is always enabled
- PassiveProvider passiveProvider = new PassiveProvider(this);
- @@ -327,14 +360,16 @@ public class LocationManagerService extends ILocationManag
- mEnabledProviders.add(passiveProvider.getName());
- mPassiveProvider = passiveProvider;
- - if (GpsLocationProvider.isSupported()) {
- - // Create a gps location provider
- - GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext,
- - mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
- - mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
- - addProviderLocked(gpsProvider);
- - mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
- + // Create a gps location provider based on the setting EXTERNAL_GPS_BT_
- + String btDevice = Settings.System.getString(mContext.getContentResolver
- + Settings.Secure.EXTERNAL_GPS_BT_DEVICE);
- + if (TextUtils.isEmpty(btDevice)) {
- + // default option
- + btDevice = "0";
- + Settings.System.putString(mContext.getContentResolver(),
- + Settings.Secure.EXTERNAL_GPS_BT_DEVICE, btDevice);
- }
- + setGPSSource(btDevice);
- /*
- Load package name(s) containing location provider support.
- diff --git a/services/java/com/android/server/location/BTGPSService.java b/servi
- new file mode 100644
- index 0000000..49aa20d
- --- /dev/null
- +++ b/services/java/com/android/server/location/BTGPSService.java
- @@ -0,0 +1,465 @@
- +/*
- + * Copyright (C) 2011 Cuong Bui
- + *
- + * 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.android.server.location;
- +
- +import java.io.BufferedReader;
- +import java.io.IOException;
- +import java.io.InputStream;
- +import java.io.InputStreamReader;
- +import java.io.OutputStream;
- +import java.util.UUID;
- +
- +import android.bluetooth.BluetoothAdapter;
- +import android.bluetooth.BluetoothDevice;
- +import android.bluetooth.BluetoothSocket;
- +import android.os.Handler;
- +import android.os.Message;
- +import android.util.Log;
- +
- +public class BTGPSService {
- + private static final boolean D = true;
- + private static final String TAG = "BTGPSService";
- + private static final UUID BT_UUID = UUID.fromString("00001101-0000-1000-800
- + private final BluetoothAdapter mAdapter;
- + private final Handler mHandler;
- + private WatchdogThread mWatchdogThread = null;
- + private ConnectThread mConnectThread = null;
- + private ConnectedThread mConnectedThread = null;
- + private final int mMaxNMEABuffer=4096;
- + private final char[] buffer = new char[mMaxNMEABuffer];
- + int bytes;
- + private long refreshRate = 1000;
- + private long lastActivity = 0;
- + // MAX_ACTIVITY_TIMEOUT * refresh time window should have at least one acti
- + private int MAX_ACTIVITY_TIMEOUT = 5;
- + // Maximum connect retry attempt
- + private int MAX_RECONNECT_RETRIES = 5;
- + // time window for one single connection (ms). socket connect timeout is ar
- + private int MAX_CONNECT_TIMEOUT = 13000;
- + // last connected device. is used to auto reconnect.
- + private BluetoothDevice lastConnectedDevice=null;
- +
- + private int mState = 0;
- + // Constants that indicate the current connection state
- + public static final int STATE_NONE = 0; // we're doing nothing
- + public static final int STATE_LISTEN = 1; // now listening for incoming
- + public static final int STATE_CONNECTING = 2; // now initiating an outgoing
- + public static final int STATE_CONNECTED = 3; // now connected to a remote
- +
- + public synchronized void setRefreshRate(long r) {
- + refreshRate = r;
- + }
- +
- + public synchronized long getRefreshRate() {
- + return refreshRate;
- + }
- +
- + public BTGPSService(Handler h) {
- + mAdapter = BluetoothAdapter.getDefaultAdapter();
- + mHandler = h;
- + }
- +
- + private void sendMessage(int message, int arg, Object obj) {
- + Message m = Message.obtain(mHandler, message);
- + m.arg1 = arg;
- + m.obj = obj;
- + mHandler.sendMessage(m);
- + }
- +
- + private void handleFailedConnection() {
- + if (getServiceState() != STATE_NONE) {
- + if (D) Log.d(TAG, "Connection failed with status != 0. try to recon
- + connect(lastConnectedDevice);
- + } else {
- + if (D) Log.d(TAG, "Connection stopped with status = 0.");
- + }
- + }
- +
- + /**
- + * Set the current state of the chat connection
- + * @param state An integer defining the current connection state
- + */
- + private synchronized void setState(int state) {
- + if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
- + mState = state;
- + if (mState == STATE_NONE) {
- + sendMessage(BTGpsLocationProvider.GPS_STATUS_UPDATE, 0, null);
- + } else if (mState == STATE_CONNECTED) {
- + sendMessage(BTGpsLocationProvider.GPS_STATUS_UPDATE, 1, null);
- + }
- + }
- +
- + /**
- + * Return the current connection state. */
- + public synchronized int getServiceState() {
- + return mState;
- + }
- +
- + /**
- + * Start the chat service. Specifically start AcceptThread to begin a
- + * session in listening (server) mode. Called by the Activity onResume() */
- + public synchronized void start() {
- +
- + if (D) Log.d(TAG, "start");
- + if (!mAdapter.isEnabled()) {
- + setState(STATE_NONE);
- + return;
- + }
- + // Cancel any thread attempting to make a connection
- + if (mConnectThread != null) {
- + mConnectThread.cancel();
- + mConnectThread = null;
- + }
- + // Cancel any thread currently running a connection
- + if (mConnectedThread != null) {
- + mConnectedThread.cancel();
- + mConnectedThread = null;
- + }
- + setState(STATE_LISTEN);
- + }
- +
- + /**
- + * Start the ConnectThread to initiate a connection to a remote device.
- + * @param device The BluetoothDevice to connect
- + */
- + public synchronized boolean connect(BluetoothDevice device) {
- + lastConnectedDevice = device;
- + if (D) Log.d(TAG, "connect to: " + device);
- + // Cancel any thread attempting to make a connection
- + if (mConnectThread != null) {
- + mConnectThread.cancel();
- + mConnectThread = null;
- + }
- + if (mWatchdogThread != null) {
- + mWatchdogThread.cancel();
- + mWatchdogThread = null;
- + }
- + // Cancel any thread currently running a connection
- + if (mConnectedThread != null) {
- + mConnectedThread.cancel();
- + mConnectedThread = null;
- + }
- + // Helper thread that monitors and retries to connect after time out
- + mWatchdogThread = new WatchdogThread(device);
- + mWatchdogThread.start();
- + return true;
- + }
- +
- + /**
- + * Start the ConnectedThread to begin managing a Bluetooth connection
- + * @param socket The BluetoothSocket on which the connection was made
- + * @param device The BluetoothDevice that has been connected
- + */
- + public synchronized void connected(BluetoothSocket socket) {
- + // reset connect thread
- + if (mConnectThread != null) mConnectThread = null;
- +
- + // kill watchdog, since we are connected
- + if (mWatchdogThread != null) {
- + mWatchdogThread.cancel();
- + mWatchdogThread = null;
- + }
- + // Cancel any thread currently running a connection
- + if (mConnectedThread != null) {
- + mConnectedThread.cancel();
- + mConnectedThread = null;
- + }
- +
- + // Start the thread to manage the connection and perform transmissions
- + mConnectedThread = new ConnectedThread(socket);
- + mConnectedThread.start();
- + setState(STATE_CONNECTED);
- + }
- +
- + /**
- + * Stop all threads
- + */
- + public synchronized void stop() {
- + if (D) Log.d(TAG, "Stopping btsvc, Set state to None");
- + setState(STATE_NONE);
- +
- + if (mWatchdogThread != null) {
- + if (D) Log.d(TAG, "Cancelling watchdog thread");
- + mWatchdogThread.cancel();
- + mWatchdogThread = null;
- + }
- +
- + if (mConnectThread != null) {
- + if (D) Log.d(TAG, "Cancelling connect thread");
- + mConnectThread.cancel();
- + mConnectThread = null;
- + }
- + if (mConnectedThread != null) {
- + if (D) Log.d(TAG, "Cancelling connected thread");
- + mConnectedThread.cancel();
- + mConnectedThread = null;
- + }
- + }
- +
- + /**
- + * Write to the ConnectedThread in an unsynchronized manner
- + * @param out The bytes to write
- + * @see ConnectedThread#write(byte[])
- + */
- + public void write(byte[] out) {
- + // Create temporary object
- + ConnectedThread r;
- + // Synchronize a copy of the ConnectedThread
- + synchronized (this) {
- + if (mState != STATE_CONNECTED) return;
- + r = mConnectedThread;
- + }
- + r.write(out);
- + }
- +
- + /**
- + * This thread runs while attempting to make an outgoing connection
- + * with a device. It runs straight through; the connection either
- + * succeeds or fails.
- + */
- + private class ConnectThread extends Thread {
- + private BluetoothSocket mmSocket;
- + private final BluetoothDevice mmDevice;
- + private String mSocketType;
- +
- + public ConnectThread(BluetoothDevice device) {
- + mmDevice = device;
- + }
- +
- + private void closeSocket() {
- + if (D) Log.d(TAG, getId()+":close socket");
- + if (mmSocket == null) {
- + Log.e(TAG, getId()+":Socket not ready. Aborting Close");
- + return;
- + }
- +
- + try {
- + mmSocket.close();
- + mmSocket = null;
- + } catch (IOException e) {
- + Log.e(TAG, getId()+":close() of connect " + mSocketType + " soc
- + }
- + }
- +
- + public void run() {
- + Log.i(TAG, getId() + ":begin mConnectThread");
- + BluetoothSocket tmp = null;
- + // Always cancel discovery because it will slow down a connection
- +
- + try {
- + tmp = mmDevice.createRfcommSocketToServiceRecord(BT_UUID);
- + } catch (IOException e) {
- + Log.e(TAG, "Socket create() failed", e);
- + return;
- + }
- + mmSocket = tmp;
- + // Make a connection to the BluetoothSocket
- + if (mAdapter.isEnabled()) mAdapter.cancelDiscovery();
- + try {
- + // This is a blocking call and will only return on a
- + // successful connection or an exception
- + if (D) Log.d(TAG, getId() + ":Connecting to socket...");
- + mmSocket.connect();
- + if (D) Log.d(TAG, "connected with remote device: "
- + + mmDevice.getName() + " at address " + mmDevice.getAdd
- + connected(mmSocket);
- + } catch (IOException e) {
- + Log.w(TAG, getId() + ":connect failed.", e);
- + return;
- + }
- + }
- +
- + public synchronized void cancel() {
- + closeSocket();
- + }
- + }
- +
- + /**
- + * This thread runs during a connection with a remote device.
- + * It handles all incoming and outgoing transmissions.
- + */
- + private class ConnectedThread extends Thread {
- + private BluetoothSocket mmSocket;
- + private InputStream mmInStream;
- + private OutputStream mmOutStream;
- + private boolean cancelled = false;
- +
- + private void closeSocket() {
- + if (D) Log.d(TAG, getId()+":close socket");
- + if (mmSocket == null) {
- + Log.e(TAG, getId()+":Socket not ready. Aborting Close");
- + return;
- + }
- + try {
- + mmSocket.close();
- + mmSocket = null;
- + } catch (IOException e) {
- + Log.e(TAG, getId()+": close() of connect socket failed", e);
- + }
- + }
- +
- + public ConnectedThread(BluetoothSocket socket) {
- + Log.d(TAG, getId() + ":begin ConnectedThread");
- + mmSocket = socket;
- + InputStream tmpIn = null;
- + OutputStream tmpOut = null;
- +
- + // Get the BluetoothSocket input and output streams
- + try {
- + tmpIn = socket.getInputStream();
- + tmpOut = socket.getOutputStream();
- + } catch (IOException e) {
- + Log.e(TAG, "temp sockets not created", e);
- + }
- + mmInStream = tmpIn;
- + mmOutStream = tmpOut;
- + }
- +
- + public void run() {
- + if (mmSocket == null || mmInStream == null) {
- + Log.e(TAG, "Input stream or socket is null. Aborting thread");
- + return;
- + }
- + if (D) Log.d(TAG, getId() + ":BEGIN mConnectedThread");
- + java.util.Arrays.fill(buffer, (char) ' ');
- + // reset refresh rate to 1000
- + refreshRate = 1000;
- + lastActivity = 0;
- + BufferedReader reader = new BufferedReader(new InputStreamReader(mm
- + // Keep listening to the InputStream while connected
- + while (true) {
- + try {
- + if (reader.ready()) {
- + bytes = reader.read(buffer, 0, mMaxNMEABuffer);
- + Message msg = mHandler.obtainMessage(
- + BTGpsLocationProvider.GPS_DATA_AVAILABLE,buffer
- + lastActivity = System.currentTimeMillis();
- + msg.arg1 = bytes;
- + mHandler.sendMessage(msg);
- + }
- + if (lastActivity != 0 && (System.currentTimeMillis() - last
- + MAX_ACTIVITY_TIMEOUT*refreshRate) {
- + Log.w(TAG, getId() + ":BT activity timeout.");
- + closeSocket();
- + handleFailedConnection();
- + return;
- + }
- + try {
- + // get default sleep time
- + Thread.sleep(getRefreshRate());
- + } catch (InterruptedException e) {
- + if (cancelled) {
- + closeSocket();
- + return;
- + }
- + }
- + } catch (IOException e) {
- + Log.w(TAG, getId() + ":disconnected.", e);
- + closeSocket();
- + handleFailedConnection();
- + return;
- + }
- + }
- + }
- +
- + /**
- + * Write to the connected OutStream.
- + * @param buffer The bytes to write
- + */
- + public void write(byte[] buffer) {
- + try {
- + mmOutStream.write(buffer);
- + mmOutStream.flush();
- + } catch (IOException e) {
- + Log.e(TAG, "Exception during write", e);
- + }
- + }
- +
- + public void cancel() {
- + try {
- + if (mmSocket == null) {
- + Log.e(TAG, "Input stream null. Aborting Cacnel");
- + return;
- + }
- + mmSocket.close();
- + } catch (IOException e) {
- + Log.e(TAG, "close() of connect socket failed", e);
- + } finally {
- + cancelled = true;
- + interrupt();
- + }
- + }
- + }
- + /*
- + * Thread that starts the connection thread an monitors it.
- + * Thread will be cancelled if timeot occurs
- + */
- + private class WatchdogThread extends Thread {
- + private final BluetoothDevice btdevice;
- + private int retries = 0;
- + private boolean sleep = false;
- + private boolean cancelled = false;
- +
- + public WatchdogThread(BluetoothDevice dev) {
- + btdevice = dev;
- + }
- +
- + public void run() {
- + while(retries < MAX_RECONNECT_RETRIES) {
- + if (mConnectThread != null) {
- + mConnectThread.cancel();
- + mConnectThread = null;
- + }
- + if (mConnectedThread != null) {
- + mConnectedThread.cancel();
- + mConnectedThread = null;
- + }
- +
- + mConnectThread = new ConnectThread(btdevice);
- + mConnectThread.start();
- + setState(STATE_CONNECTING);
- + // monitor connection and cancel if timeout
- + if (D) Log.d(TAG, getId() + ":Waiting " + MAX_CONNECT_TIMEOUT
- + + " (ms) for service to connect...");
- + try {
- + sleep = true;
- + Thread.sleep(MAX_CONNECT_TIMEOUT);
- + sleep = false;
- + if (D) Log.d(TAG, getId() + ":Connecting timeout.");
- + } catch (InterruptedException e) {
- + if (D) Log.d(TAG, getId() + ":Watchdog interrupted. probabl
- + }
- + if (getServiceState() == STATE_CONNECTED) {
- + if (D) Log.d(TAG, getId() + ":Connected. aborting watchdog"
- + return;
- + }
- + if (cancelled) {
- + if (D) Log.d(TAG, getId() + ":Cancelled. aborting watchdog"
- + return;
- + }
- + retries++;
- + }
- + // max timeout, so stopping service
- + if (D) Log.d(TAG, getId() + ":Max connection retries exceeded. stop
- + BTGPSService.this.stop();
- + }
- +
- + public void cancel() {
- + cancelled = true;
- + if (sleep) interrupt();
- + }
- + }
- +}
- diff --git a/services/java/com/android/server/location/BTGpsLocationProvider.jav
- new file mode 100644
- index 0000000..8f2bbab
- --- /dev/null
- +++ b/services/java/com/android/server/location/BTGpsLocationProvider.java
- @@ -0,0 +1,858 @@
- +/*
- + * Copyright (C) 2011 Cuong Bui
- + *
- + * 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.android.server.location;
- +
- +
- +import java.util.ArrayList;
- +import java.util.concurrent.CountDownLatch;
- +
- +import android.bluetooth.BluetoothAdapter;
- +import android.bluetooth.BluetoothDevice;
- +import android.content.BroadcastReceiver;
- +import android.content.Context;
- +import android.content.Intent;
- +import android.content.IntentFilter;
- +import android.location.Criteria;
- +import android.location.IGpsStatusListener;
- +import android.location.IGpsStatusProvider;
- +import android.location.ILocationManager;
- +import android.location.Location;
- +import android.location.LocationManager;
- +import android.location.LocationProvider;
- +import android.net.NetworkInfo;
- +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.RemoteException;
- +import android.os.ServiceManager;
- +import android.os.SystemClock;
- +import android.os.WorkSource;
- +import android.provider.Settings;
- +import android.text.TextUtils;
- +import android.util.Log;
- +import android.util.SparseIntArray;
- +
- +import com.android.internal.app.IBatteryStats;
- +
- +
- +public class BTGpsLocationProvider implements LocationProviderInterface {
- + private static final boolean D = true;
- + private final String PROVIDER = "External Bleutooth Location Provider";
- + private final String TAG = "BTGpsLocationProvider";
- + private final NMEAParser nmeaparser = new NMEAParser(PROVIDER);
- +
- + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapte
- +
- + // GPS update codes
- + public static final int GPS_DATA_AVAILABLE = 1000;
- + public static final int GPS_STATUS_UPDATE = 1001;
- + public static final int GPS_CUSTOM_COMMAND = 1002;
- +
- +
- + // Wakelocks
- + private final static String WAKELOCK_KEY = "GpsLocationProvider";
- + private final PowerManager.WakeLock mWakeLock;
- + // bitfield of pending messages to our Handler
- + // used only for messages that cannot have multiple instances queued
- + private int mPendingMessageBits;
- + // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
- + // which might have multiple instances queued
- + private int mPendingListenerMessages;
- +
- + private final IBatteryStats mBatteryStats;
- + private final SparseIntArray mClientUids = new SparseIntArray();
- + // 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 int REQUEST_SINGLE_SHOT = 10;
- +
- + // for calculating time to first fix
- + private long mFixRequestTime = 0;
- + // time to first fix for most recent session
- + private int mTTFF = 0;
- + // time we received our last fix
- + private long mLastFixTime;
- +
- + // time for last status update
- + private long mStatusUpdateTime = SystemClock.elapsedRealtime();
- +
- + // true if we are enabled
- + private volatile boolean mEnabled;
- +
- + // true if GPS is navigating
- + private boolean mNavigating;
- +
- + private int mSvCount;
- + // current status
- + private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
- +
- + private Bundle mLocationExtras = new Bundle();
- + private Location mLocation = new Location(PROVIDER);
- +
- + private final Context mContext;
- + private final ILocationManager mLocationManager;
- +
- + private final IntentFilter mIntentBTFilter;
- +
- + private final Thread mMessageLoopThread = new BTGPSMessageThread();
- + private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
- +
- + /**
- + *Listen for BT changes. If BT is turned off, disable GPS services
- + */
- + private final BroadcastReceiver mReceiver;
- +
- + /**
- + * Message handler
- + * Receives nmea sentences
- + * receives connection lost signals
- + * enabling/disabling gps signals
- + * adding/removing listeners
- + */
- + private Handler mHandler;
- +
- + // BT gps service. This class handles the actual BT connection and data xfe
- + private final BTGPSService btsvc;
- +
- + // BT Location provider , uses the same method signature as the org GPS loc
- + public BTGpsLocationProvider(Context context, ILocationManager locationMana
- +
- + mContext = context;
- + mLocationManager = locationManager;
- + // innit message handler
- + mMessageLoopThread.start();
- + // wait for message handler to be ready
- + while (true) {
- + try {
- + mInitializedLatch.await();
- + break;
- + } catch (InterruptedException e) {
- + Thread.currentThread().interrupt();
- + }
- + }
- + // instantiate BTGPSService
- + btsvc = new BTGPSService(mHandler);
- +
- + // Create a wake lock.
- + PowerManager powerManager = (PowerManager) mContext.getSystemService(Co
- + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WA
- + mWakeLock.setReferenceCounted(false);
- +
- + // Battery statistics service to be notified when GPS turns on or off
- + mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getServic
- +
- + // receive BT state changes
- + mReceiver = new BroadcastReceiver() {
- + @Override
- + public void onReceive(Context context, Intent intent) {
- + String action = intent.getAction();
- + if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
- + int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE
- + BluetoothAdapter.ERROR);
- + switch (state) {
- + case BluetoothAdapter.STATE_ON:
- + if (D) Log.i(TAG, "BT turned on -> notify services?");
- + break;
- + case BluetoothAdapter.STATE_TURNING_OFF:
- + if (btsvc.getServiceState() != BTGPSService.STATE_NONE)
- + if (D) Log.i(TAG, "BT turned off -> stopping servic
- + btsvc.stop();
- + }
- + break;
- + }
- + }
- + }
- + };
- + mIntentBTFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGE
- + mContext.registerReceiver(mReceiver, mIntentBTFilter);
- + }
- +
- + private final class BTGPSMessageThread extends Thread {
- +
- + public void run() {
- + try {
- + Looper.prepare();
- + } catch (RuntimeException e) {
- + // ignored: Looper already prepared
- + }
- + mHandler = new Handler() {
- + @Override
- + public void handleMessage(Message msg) {
- + int message = msg.what;
- + switch (message) {
- + case GPS_DATA_AVAILABLE:
- + char[] writeBuf = (char[]) msg.obj;
- + int bytes = msg.arg1;
- + if ((writeBuf != null) && (mEnabled && bytes > 0)) {
- + String writeMessage = new String(writeBuf, 0, bytes
- + handleNMEAMessages(writeMessage);
- + java.util.Arrays.fill(writeBuf, (char) ' ');
- + }
- + break;
- + case GPS_STATUS_UPDATE:
- + notifyEnableDisableGPS(msg.arg1 == 1);
- + break;
- + case GPS_CUSTOM_COMMAND:
- + if (mEnabled && btsvc.getServiceState() == BTGPSService
- + // sends custom commands
- + byte[] cmds = (byte[]) msg.obj;
- + btsvc.write(cmds);
- + }
- + break;
- + case ENABLE:
- + if (msg.arg1 == 1) {
- + handleEnable();
- + } else {
- + handleDisable();
- + }
- + break;
- + case REQUEST_SINGLE_SHOT:
- + case ENABLE_TRACKING:
- + case UPDATE_NETWORK_STATE:
- + case INJECT_NTP_TIME:
- + case DOWNLOAD_XTRA_DATA:
- + break;
- + case UPDATE_LOCATION:
- + handleUpdateLocation((Location)msg.obj);
- + break;
- + case ADD_LISTENER:
- + handleAddListener(msg.arg1);
- + break;
- + case REMOVE_LISTENER:
- + handleRemoveListener(msg.arg1);
- + break;
- + }
- + // release wake lock if no messages are pending
- + synchronized (mWakeLock) {
- + mPendingMessageBits &= ~(1 << message);
- + if (message == ADD_LISTENER || message == REMOVE_LISTEN
- + mPendingListenerMessages--;
- + }
- + if (mPendingMessageBits == 0 && mPendingListenerMessage
- + mWakeLock.release();
- + }
- + }
- + }
- + };
- + mInitializedLatch.countDown();
- + Looper.loop();
- + }
- + }
- +
- + @Override
- + public void enable() {
- + synchronized (mHandler) {
- + sendMessage(ENABLE, 1, null);
- + }
- + }
- +
- + /**
- + * Enables BT GPS provider
- + */
- + private synchronized void handleEnable() {
- + if (D) Log.d(TAG, "handleEnable");
- + if (mEnabled) return;
- + // check if BT is enabled
- + if (!mAdapter.isEnabled()) {
- + int state = mAdapter.getState();
- + if (state == BluetoothAdapter.STATE_OFF) {
- + if (D) Log.d(TAG, "BT not available. Enable and wait for it..."
- + mAdapter.enable();
- + }
- + // wait for adapter to be ready
- + while (true) {
- + try {
- + state = mAdapter.getState();
- + if (state == BluetoothAdapter.STATE_ON) {
- + break;
- + } else if (state == BluetoothAdapter.STATE_TURNING_ON) {
- + if (D) Log.d(TAG, "BT not available yet. waiting for an
- + Thread.sleep(400);
- + } else {
- + if (D) Log.d(TAG, "BT got disabled or interrupted by ot
- + return;
- + }
- +
- + } catch (InterruptedException e) {
- + Log.w(TAG, e.getMessage());
- + }
- + }
- + }
- + if (D) Log.d(TAG, "mEnabled -> true");
- + mEnabled = true;
- + if (D) Log.d(TAG, "mStatus -> temp unavailable");
- + mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
- + if (D) Log.d(TAG, "btservice start");
- + btsvc.start();
- + mFixRequestTime = System.currentTimeMillis();
- + mTTFF = 0;
- + String btDevice = Settings.System.getString(mContext.getContentResolver
- + Settings.Secure.EXTERNAL_GPS_BT_DEVICE);
- + if (D) Log.d(TAG, "Connecting to saved pref: " + btDevice);
- + if ((btDevice != null) && !"0".equals(btDevice)) {
- + if ((mAdapter != null) && (mAdapter.isEnabled())) {
- + for (BluetoothDevice d: mAdapter.getBondedDevices()) {
- + if (btDevice.equals(d.getAddress())) {
- + if (D) Log.d(TAG, "Connecting...");
- + btsvc.connect(d);
- + return;
- + }
- + }
- + }
- + }
- + }
- +
- + /**
- + * Disables this provider.
- + */
- + @Override
- + public void disable() {
- + synchronized (mHandler) {
- + sendMessage(ENABLE, 0, null);
- + }
- + }
- +
- + private synchronized void handleDisable() {
- + if (D) Log.d(TAG, "handleDisable");
- + if (!mEnabled) return;
- + if (D) Log.d(TAG, "mEnabled -> false");
- + mEnabled = false;
- + if (D) Log.d(TAG, "reportstatus notify listeners and system");
- + notifyEnableDisableGPS(false);
- + if (D) Log.d(TAG, "update to out of service");
- + updateStatus(LocationProvider.OUT_OF_SERVICE, mSvCount);
- + if (D) Log.d(TAG, "btservice Stop");
- + btsvc.stop();
- + }
- +
- + /* We do not need to implement scheduled tracking. With internal gps provid
- + * to hibernate and resume periodically. With BT GPS providers it doesn't m
- + * @see com.android.server.location.LocationProviderInterface#enableLocatio
- + */
- + @Override
- + public void enableLocationTracking(boolean enable) {
- + }
- +
- + @Override
- + public int getAccuracy() {
- + return Criteria.ACCURACY_FINE;
- + }
- +
- + /* Debug native state used by normal GPS provider only
- + * @see com.android.server.location.LocationProviderInterface#getInternalSt
- + */
- + @Override
- + public String getInternalState() {
- + return null;
- + }
- +
- + @Override
- + public String getName() {
- + return LocationManager.GPS_PROVIDER;
- + }
- +
- + /**
- + * Returns the power requirement for this provider.
- + *
- + * @return the power requirement for this provider, as one of the
- + * constants Criteria.POWER_REQUIREMENT_*.
- + */
- + public int getPowerRequirement() {
- + return Criteria.POWER_MEDIUM;
- + }
- +
- + /**
- + * Returns true if this provider meets the given criteria,
- + * false otherwise.
- + */
- + public boolean meetsCriteria(Criteria criteria) {
- + return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
- + }
- +
- + @Override
- + public int getStatus(Bundle extras) {
- + if (extras != null) {
- + extras.putInt("satellites", mSvCount);
- + }
- + return mStatus;
- + }
- +
- + @Override
- + public long getStatusUpdateTime() {
- + return mStatusUpdateTime;
- + }
- +
- + @Override
- + public boolean hasMonetaryCost() {
- + return false;
- + }
- +
- + @Override
- + public boolean isEnabled() {
- + return mEnabled;
- + }
- +
- +
- + @Override
- + public boolean requestSingleShotFix() {
- + return false;
- + }
- +
- + @Override
- + public boolean requiresCell() {
- + return false;
- + }
- +
- + @Override
- + public boolean requiresNetwork() {
- + return false;
- + }
- +
- + @Override
- + public boolean requiresSatellite() {
- + return true;
- + }
- +
- + @Override
- + public boolean sendExtraCommand(String command, Bundle extras) {
- + if (TextUtils.isEmpty(command)) return false;
- + synchronized (mHandler) {
- + String customCommand = command + "\r\n";
- + sendMessage(GPS_CUSTOM_COMMAND, customCommand.length(), customComma
- + }
- + return true;
- + }
- +
- + /* GPS scheduling stuff, not needed
- + * @see com.android.server.location.LocationProviderInterface#setMinTime(lo
- + */
- + @Override
- + public void setMinTime(long minTime, WorkSource ws) {
- +
- + }
- +
- + @Override
- + public boolean supportsAltitude() {
- + return mLocation.hasAltitude();
- + }
- +
- + @Override
- + public boolean supportsBearing() {
- + return mLocation.hasBearing();
- + }
- +
- + @Override
- + public boolean supportsSpeed() {
- + return mLocation.hasSpeed();
- + }
- +
- + @Override
- + /**
- + * This is called to inform us when another location provider returns a loc
- + * Someday we might use this for network location injection to aid the GPS
- + */
- + public void updateLocation(Location location) {
- + sendMessage(UPDATE_LOCATION, 0, location);
- + }
- +
- + private void handleUpdateLocation(Location location) {
- + if (location.hasAccuracy()) {
- + // Allow other provider GPS data ? discard for now
- + }
- + }
- +
- + /* unneeded by BT GPS provider
- + * @see com.android.server.location.LocationProviderInterface#updateNetwork
- + */
- + @Override
- + public void updateNetworkState(int state, NetworkInfo info) {
- + // TODO Auto-generated method stub
- +
- + }
- +
- + /**
- + * @param loc Location object representing the fix
- + * @param isValid true if fix was valid
- + */
- + private void reportLocation(Location loc, boolean isValid) {
- +
- + if (!isValid) {
- + if (mStatus == LocationProvider.AVAILABLE && mTTFF > 0) {
- + if (D) Log.d(TAG, "Invalid sat fix -> sending notification to s
- + // send an intent to notify that the GPS is no longer receiving
- + Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTIO
- + intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
- + mContext.sendBroadcast(intent);
- + updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount
- + }
- + return;
- + }
- +
- + synchronized (mLocation) {
- + mLocation.set(loc);
- + mLocation.setProvider(this.getName());
- + if (D) {
- + Log.d(TAG, "reportLocation lat: " + mLocation.getLatitude() +
- + " long: " + mLocation.getLongitude() + " alt: " + mLocation
- + " accuracy: " + mLocation.getAccuracy() + " timestamp: " +
- + }
- + try {
- + mLocationManager.reportLocation(mLocation, false);
- + } catch (RemoteException e) {
- + Log.e(TAG, "RemoteException calling reportLocation");
- + }
- + }
- +
- + mLastFixTime = System.currentTimeMillis();
- + // report time to first fix
- + if ((mTTFF == 0) && (isValid)) {
- + mTTFF = (int)(mLastFixTime - mFixRequestTime);
- + if (D) Log.d(TAG, "TTFF: " + mTTFF);
- +
- + // notify status listeners
- + synchronized(mListeners) {
- + int size = mListeners.size();
- + for (int i = 0; i < size; i++) {
- + Listener listener = mListeners.get(i);
- + try {
- + listener.mListener.onFirstFix(mTTFF);
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in first fix notification")
- + mListeners.remove(listener);
- + // adjust for size of list changing
- + size--;
- + }
- + }
- + }
- + }
- +
- + if (mStatus != LocationProvider.AVAILABLE) {
- + if (D) Log.d(TAG,"Notify that we're receiving fixes");
- + // send an intent to notify that the GPS is receiving fixes.
- + Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
- + intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
- + mContext.sendBroadcast(intent);
- + updateStatus(LocationProvider.AVAILABLE, mSvCount);
- + }
- +
- + }
- +
- + /* report sats status
- + */
- + private void reportSvStatus(int svCount, int mSvs[], float mSnrs[],
- + float mSvElevations[], float mSvAzimuths[], int mSvMasks[]) {
- +
- + if (D) Log.d(TAG,"About to report sat status svcount: " + svCount);
- + synchronized(mListeners) {
- + int size = mListeners.size();
- + for (int i = 0; i < size; i++) {
- + Listener listener = mListeners.get(i);
- + try {
- + listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
- + mSvAzimuths, mSvMasks[NMEAParser.EPHEMERIS_MASK],
- + mSvMasks[NMEAParser.ALMANAC_MASK],
- + mSvMasks[NMEAParser.USED_FOR_FIX_MASK]);
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in reportSvInfo");
- + mListeners.remove(listener);
- + // adjust for size of list changing
- + size--;
- + }
- + }
- + }
- +
- + // return number of sets used in fix instead of total
- + updateStatus(mStatus, Integer.bitCount(mSvMasks[NMEAParser.USED_FOR_FIX
- + }
- +
- + /**
- + * Handles GPS status.
- + * will also inform listeners when GPS started/stopped
- + * @param status new GPS status
- + */
- + private void notifyEnableDisableGPS(boolean status) {
- + if (D) Log.v(TAG, "notifyEnableDisableGPS status: " + status);
- +
- + synchronized(mListeners) {
- + mNavigating = status;
- + int size = mListeners.size();
- + for (int i = 0; i < size; i++) {
- + Listener listener = mListeners.get(i);
- + try {
- + if (status) {
- + listener.mListener.onGpsStarted();
- + } else {
- + listener.mListener.onGpsStopped();
- + }
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in reportStatus");
- + mListeners.remove(listener);
- + // adjust for size of list changing
- + size--;
- + }
- + }
- + try {
- + // update battery stats
- + for (int i=mClientUids.size() - 1; i >= 0; i--) {
- + int uid = mClientUids.keyAt(i);
- + if (mNavigating) {
- + mBatteryStats.noteStartGps(uid);
- + } else {
- + mBatteryStats.noteStopGps(uid);
- + }
- + }
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in reportStatus");
- + }
- + // send an intent to notify that the GPS has been enabled or disabl
- + Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTIO
- + intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, status);
- + mContext.sendBroadcast(intent);
- + }
- + try {
- + if (D) Log.d(TAG, "Setting System GPS status to " + status);
- + Settings.Secure.setLocationProviderEnabled(mContext.getContentResol
- + LocationManager.GPS_PROVIDER, status);
- + } catch (Exception e) {
- + Log.e(TAG, e.getMessage());
- + }
- + }
- +
- + /**
- + * sends nmea sentences to NMEA parsers. Some apps use raw nmea data
- + * @param nmeaString nmea string
- + * @param timestamp time stamp
- + */
- + private void reportNmea(String nmeaString, long timestamp) {
- + synchronized(mListeners) {
- + int size = mListeners.size();
- + if (size > 0) {
- + // don't bother creating the String if we have no listeners
- + for (int i = 0; i < size; i++) {
- + Listener listener = mListeners.get(i);
- + try {
- + listener.mListener.onNmeaReceived(timestamp, nmeaString
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in reportNmea");
- + mListeners.remove(listener);
- + // adjust for size of list changing
- + size--;
- + }
- + }
- + }
- + }
- + }
- +
- + /**
- + * This methods parses the nmea sentences and sends the location updates
- + * and sats updates to listeners.
- + * @param sentences raw nmea sentences received by BT GPS Mouse
- + */
- + private void handleNMEAMessages(String sentences) {
- + String sentenceArray[] = sentences.split("\r\n");
- + nmeaparser.reset();
- + for (int i = 0; i < sentenceArray.length; i++) {
- + if (D) Log.d(TAG, "About to parse: " + sentenceArray[i]);
- + if ((sentenceArray[i] != null) && ("".equals(sentenceArray[i]))) co
- + boolean parsed = nmeaparser.parseNMEALine(sentenceArray[i]);
- + // handle nmea message. Also report messages that we could not pars
- + // might be propriatery messages that other listeners could support
- + reportNmea(sentenceArray[i], System.currentTimeMillis());
- + }
- + Location loc = nmeaparser.getLocation();
- + // handle location update if valid
- + reportLocation(loc , nmeaparser.isValid());
- + if (nmeaparser.isSatdataReady()) {
- + reportSvStatus(nmeaparser.getmSvCount(), nmeaparser.getmSvs(), nmea
- + nmeaparser.getmSvElevations(), nmeaparser.getmSvAzimuths(),
- + nmeaparser.getmSvMasks());
- + }
- +
- + // adjust refresh rate based on received timestamp of mouse
- + // min 1hz and max 10 hz
- + long newRate = nmeaparser.getApproximatedRefreshRate();
- + if (btsvc.getRefreshRate() != newRate) {
- + if (D) Log.d(TAG, "Setting refresh rate to: " + newRate
- + + " was: " + btsvc.getRefreshRate());
- + btsvc.setRefreshRate(newRate);
- + }
- + }
- +
- +
- + /*
- + * Stuff below is taken from the android GPS location provider.
- + * Does handling of messages/listeners and so on.
- + */
- +
- + private void sendMessage(int message, int arg, Object obj) {
- + // hold a wake lock while messages are pending
- + synchronized (mWakeLock) {
- + mPendingMessageBits |= (1 << message);
- + mWakeLock.acquire();
- + mHandler.removeMessages(message);
- + Message m = Message.obtain(mHandler, message);
- + m.arg1 = arg;
- + m.obj = obj;
- + mHandler.sendMessage(m);
- + }
- + }
- +
- +
- + private void updateStatus(int status, int svCount) {
- + if (status != mStatus || svCount != mSvCount) {
- + mStatus = status;
- + mSvCount = svCount;
- + mLocationExtras.putInt("satellites", svCount);
- + mStatusUpdateTime = SystemClock.elapsedRealtime();
- + }
- + }
- + private ArrayList<Listener> mListeners = new ArrayList<Listener>();
- +
- + private final class Listener implements IBinder.DeathRecipient {
- + final IGpsStatusListener mListener;
- +
- + Listener(IGpsStatusListener listener) {
- + mListener = listener;
- + }
- +
- + public void binderDied() {
- + if (D) Log.d(TAG, "GPS status listener died");
- +
- + synchronized(mListeners) {
- + mListeners.remove(this);
- + }
- + if (mListener != null) {
- + mListener.asBinder().unlinkToDeath(this, 0);
- + }
- + }
- + }
- +
- +
- + private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvide
- + public void addGpsStatusListener(IGpsStatusListener listener) throws Re
- + if (listener == null) {
- + throw new NullPointerException("listener is null in addGpsStatu
- + }
- + synchronized(mListeners) {
- + IBinder binder = listener.asBinder();
- + int size = mListeners.size();
- + for (int i = 0; i < size; i++) {
- + Listener test = mListeners.get(i);
- + if (binder.equals(test.mListener.asBinder())) {
- + // listener already added
- + return;
- + }
- + }
- + Listener l = new Listener(listener);
- + binder.linkToDeath(l, 0);
- + mListeners.add(l);
- + }
- + }
- +
- + public void removeGpsStatusListener(IGpsStatusListener listener) {
- + if (listener == null) {
- + throw new NullPointerException("listener is null in addGpsStatu
- + }
- +
- + synchronized(mListeners) {
- + IBinder binder = listener.asBinder();
- + Listener l = null;
- + int size = mListeners.size();
- + for (int i = 0; i < size && l == null; i++) {
- + Listener test = mListeners.get(i);
- + if (binder.equals(test.mListener.asBinder())) {
- + l = test;
- + }
- + }
- +
- + if (l != null) {
- + mListeners.remove(l);
- + binder.unlinkToDeath(l, 0);
- + }
- + }
- + }
- + };
- +
- + public IGpsStatusProvider getGpsStatusProvider() {
- + return mGpsStatusProvider;
- + }
- +
- + public void addListener(int uid) {
- + synchronized (mWakeLock) {
- + mPendingListenerMessages++;
- + mWakeLock.acquire();
- + 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.
- + Log.w(TAG, "Duplicate add listener for uid " + uid);
- + return;
- + }
- + mClientUids.put(uid, 0);
- + if (mNavigating) {
- + try {
- + mBatteryStats.noteStartGps(uid);
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in addListener");
- + }
- + }
- + }
- + }
- +
- + public void removeListener(int uid) {
- + synchronized (mWakeLock) {
- + mPendingListenerMessages++;
- + mWakeLock.acquire();
- + 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.
- + Log.w(TAG, "Unneeded remove listener for uid " + uid);
- + return;
- + }
- + mClientUids.delete(uid);
- + if (mNavigating) {
- + try {
- + mBatteryStats.noteStopGps(uid);
- + } catch (RemoteException e) {
- + Log.w(TAG, "RemoteException in removeListener");
- + }
- + }
- + }
- + }
- +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement