Code drop from //branches/cupcake/...@124589
This commit is contained in:
@ -57,9 +57,9 @@ import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.telephony.CellLocation;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
@ -145,24 +145,25 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
private boolean mCellWakeLockAcquired = false;
|
||||
|
||||
/**
|
||||
* Mapping from listener IBinder to local Listener wrappers.
|
||||
* Mapping from listener IBinder/PendingIntent to local Listener wrappers.
|
||||
*/
|
||||
private final HashMap<IBinder,Listener> mListeners =
|
||||
new HashMap<IBinder,Listener>();
|
||||
private final HashMap<Object,Receiver> mListeners =
|
||||
new HashMap<Object,Receiver>();
|
||||
|
||||
/**
|
||||
* Mapping from listener IBinder to a map from provider name to UpdateRecord.
|
||||
* Mapping from listener IBinder/PendingIntent to a map from provider name to UpdateRecord.
|
||||
*/
|
||||
private final HashMap<IBinder,HashMap<String,UpdateRecord>> mLocationListeners =
|
||||
new HashMap<IBinder,HashMap<String,UpdateRecord>>();
|
||||
private final HashMap<Object,HashMap<String,UpdateRecord>> mLocationListeners =
|
||||
new HashMap<Object,HashMap<String,UpdateRecord>>();
|
||||
|
||||
/**
|
||||
* Mapping from listener IBinder to a map from provider name to last broadcast location.
|
||||
* Mapping from listener IBinder/PendingIntent to a map from provider name to last broadcast
|
||||
* location.
|
||||
*/
|
||||
private final HashMap<IBinder,HashMap<String,Location>> mLastFixBroadcast =
|
||||
new HashMap<IBinder,HashMap<String,Location>>();
|
||||
private final HashMap<IBinder,HashMap<String,Long>> mLastStatusBroadcast =
|
||||
new HashMap<IBinder,HashMap<String,Long>>();
|
||||
private final HashMap<Object,HashMap<String,Location>> mLastFixBroadcast =
|
||||
new HashMap<Object,HashMap<String,Location>>();
|
||||
private final HashMap<Object,HashMap<String,Long>> mLastStatusBroadcast =
|
||||
new HashMap<Object,HashMap<String,Long>>();
|
||||
|
||||
/**
|
||||
* Mapping from provider name to all its UpdateRecords
|
||||
@ -178,7 +179,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
new HashMap<String,Location>();
|
||||
|
||||
// Proximity listeners
|
||||
private ProximityListener mProximityListener = null;
|
||||
private Receiver mProximityListener = null;
|
||||
private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
|
||||
new HashMap<PendingIntent,ProximityAlert>();
|
||||
private HashSet<ProximityAlert> mProximitiesEntered =
|
||||
@ -195,7 +196,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
// Last known cell service state
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private ServiceState mServiceState = new ServiceState();
|
||||
private int mSignalStrength = -1;
|
||||
|
||||
// Location collector
|
||||
private LocationCollector mCollector;
|
||||
@ -206,11 +207,82 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
// Wifi Manager
|
||||
private WifiManager mWifiManager;
|
||||
|
||||
private final class Listener implements IBinder.DeathRecipient {
|
||||
/**
|
||||
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
|
||||
* location updates.
|
||||
*/
|
||||
private final class Receiver implements IBinder.DeathRecipient {
|
||||
final ILocationListener mListener;
|
||||
final PendingIntent mPendingIntent;
|
||||
|
||||
Listener(ILocationListener listener) {
|
||||
Receiver(ILocationListener listener) {
|
||||
mListener = listener;
|
||||
mPendingIntent = null;
|
||||
}
|
||||
|
||||
Receiver(PendingIntent intent) {
|
||||
mPendingIntent = intent;
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
if (mListener != null) {
|
||||
return mListener.asBinder();
|
||||
} else {
|
||||
return mPendingIntent;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isListener() {
|
||||
return mListener != null;
|
||||
}
|
||||
|
||||
public boolean isPendingIntent() {
|
||||
return mPendingIntent != null;
|
||||
}
|
||||
|
||||
public ILocationListener getListener() {
|
||||
if (mListener != null) {
|
||||
return mListener;
|
||||
}
|
||||
throw new IllegalStateException("Request for non-existent listener");
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
if (mPendingIntent != null) {
|
||||
return mPendingIntent;
|
||||
}
|
||||
throw new IllegalStateException("Request for non-existent intent");
|
||||
}
|
||||
|
||||
public void onStatusChanged(String provider, int status, Bundle extras)
|
||||
throws RemoteException {
|
||||
if (mListener != null) {
|
||||
mListener.onStatusChanged(provider, status, extras);
|
||||
} else {
|
||||
Intent statusChanged = new Intent();
|
||||
statusChanged.putExtras(extras);
|
||||
statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
|
||||
try {
|
||||
mPendingIntent.send(mContext, 0, statusChanged, null, null);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
_removeUpdates(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onLocationChanged(Location location) throws RemoteException {
|
||||
if (mListener != null) {
|
||||
mListener.onLocationChanged(location);
|
||||
} else {
|
||||
Intent locationChanged = new Intent();
|
||||
locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
|
||||
try {
|
||||
mPendingIntent.send(mContext, 0, locationChanged, null, null);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
_removeUpdates(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void binderDied() {
|
||||
@ -218,7 +290,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
Log.d(TAG, "Location listener died");
|
||||
}
|
||||
synchronized (mLocationListeners) {
|
||||
_removeUpdates(mListener);
|
||||
_removeUpdates(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -228,7 +300,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
String s = null;
|
||||
try {
|
||||
File f = new File(LocationManager.SYSTEM_DIR + "/location."
|
||||
+ provider);
|
||||
+ provider);
|
||||
if (!f.exists()) {
|
||||
return null;
|
||||
}
|
||||
@ -443,13 +515,22 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
// Create location collector
|
||||
mCollector = new LocationCollector(mMasfClient);
|
||||
|
||||
// Alarm manager, needs to be done before calling loadProviders() below
|
||||
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
// Create a wake lock, needs to be done before calling loadProviders() below
|
||||
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
|
||||
|
||||
// Load providers
|
||||
loadProviders();
|
||||
|
||||
// Listen for Radio changes
|
||||
mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
mTelephonyManager.listen(mPhoneStateListener,
|
||||
PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_CELL_LOCATION);
|
||||
PhoneStateListener.LISTEN_CELL_LOCATION |
|
||||
PhoneStateListener.LISTEN_SIGNAL_STRENGTH |
|
||||
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
|
||||
|
||||
// Register for Network (Wifi or Mobile) updates
|
||||
NetworkStateBroadcastReceiver networkReceiver = new NetworkStateBroadcastReceiver();
|
||||
@ -460,9 +541,6 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
networkIntentFilter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
|
||||
context.registerReceiver(networkReceiver, networkIntentFilter);
|
||||
|
||||
// Alarm manager
|
||||
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
// Register for power updates
|
||||
PowerStateBroadcastReceiver powerStateReceiver = new PowerStateBroadcastReceiver();
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
@ -472,10 +550,6 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
context.registerReceiver(powerStateReceiver, intentFilter);
|
||||
|
||||
// Create a wake lock
|
||||
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
|
||||
|
||||
// Get the wifi manager
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
|
||||
@ -510,8 +584,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
// Use system settings
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
String allowedProviders = Settings.System.getString(resolver,
|
||||
Settings.System.LOCATION_PROVIDERS_ALLOWED);
|
||||
String allowedProviders = Settings.Secure.getString(resolver,
|
||||
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
|
||||
|
||||
return ((allowedProviders != null) && (allowedProviders.contains(provider)));
|
||||
}
|
||||
@ -638,16 +712,28 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
synchronized (mRecordsByProvider) {
|
||||
|
||||
HashSet<UpdateRecord> records = mRecordsByProvider.get(provider);
|
||||
if (records != null) {
|
||||
for (UpdateRecord record : records) {
|
||||
// Sends a notification message to the listener
|
||||
// Sends a notification message to the receiver
|
||||
try {
|
||||
if (enabled) {
|
||||
record.mListener.mListener.onProviderEnabled(provider);
|
||||
Receiver receiver = record.mReceiver;
|
||||
if (receiver.isListener()) {
|
||||
if (enabled) {
|
||||
receiver.getListener().onProviderEnabled(provider);
|
||||
} else {
|
||||
receiver.getListener().onProviderDisabled(provider);
|
||||
}
|
||||
} else {
|
||||
record.mListener.mListener.onProviderDisabled(provider);
|
||||
PendingIntent intent = receiver.getPendingIntent();
|
||||
Intent providerIntent = new Intent();
|
||||
providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
|
||||
try {
|
||||
receiver.getPendingIntent().send(mContext, 0,
|
||||
providerIntent, null, null);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
_removeUpdates(receiver);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// The death link will clean this up.
|
||||
@ -694,15 +780,15 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
private class UpdateRecord {
|
||||
String mProvider;
|
||||
Listener mListener;
|
||||
Receiver mReceiver;
|
||||
long mMinTime;
|
||||
float mMinDistance;
|
||||
String[] mPackages;
|
||||
|
||||
UpdateRecord(String provider, long minTime, float minDistance, Listener listener,
|
||||
String[] packages) {
|
||||
UpdateRecord(String provider, long minTime, float minDistance,
|
||||
Receiver receiver, String[] packages) {
|
||||
mProvider = provider;
|
||||
mListener = listener;
|
||||
mReceiver = receiver;
|
||||
mMinTime = minTime;
|
||||
mMinDistance = minDistance;
|
||||
mPackages = packages;
|
||||
@ -740,7 +826,20 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
long minTime, float minDistance, ILocationListener listener) {
|
||||
|
||||
try {
|
||||
_requestLocationUpdates(provider, minTime, minDistance, listener);
|
||||
_requestLocationUpdates(provider, minTime, minDistance,
|
||||
new Receiver(listener));
|
||||
} catch (SecurityException se) {
|
||||
throw se;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "requestUpdates got exception:", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void requestLocationUpdatesPI(String provider,
|
||||
long minTime, float minDistance, PendingIntent intent) {
|
||||
try {
|
||||
_requestLocationUpdates(provider, minTime, minDistance,
|
||||
new Receiver(intent));
|
||||
} catch (SecurityException se) {
|
||||
throw se;
|
||||
} catch (Exception e) {
|
||||
@ -749,9 +848,10 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
private void _requestLocationUpdates(String provider,
|
||||
long minTime, float minDistance, ILocationListener listener) {
|
||||
long minTime, float minDistance, Receiver receiver) {
|
||||
Object key = receiver.getKey();
|
||||
if (Config.LOGD) {
|
||||
Log.d(TAG, "_requestLocationUpdates: listener = " + listener.asBinder());
|
||||
Log.d(TAG, "_requestLocationUpdates: listener = " + key);
|
||||
}
|
||||
|
||||
LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
|
||||
@ -766,24 +866,23 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
// so wakelock calls will succeed
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
Listener myListener = new Listener(listener);
|
||||
UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, myListener, packages);
|
||||
|
||||
UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, packages);
|
||||
synchronized (mLocationListeners) {
|
||||
IBinder binder = listener.asBinder();
|
||||
if (mListeners.get(binder) == null) {
|
||||
if (mListeners.get(key) == null) {
|
||||
try {
|
||||
binder.linkToDeath(myListener, 0);
|
||||
mListeners.put(binder, myListener);
|
||||
if (receiver.isListener()) {
|
||||
receiver.getListener().asBinder().linkToDeath(receiver, 0);
|
||||
}
|
||||
mListeners.put(key, receiver);
|
||||
} catch (RemoteException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HashMap<String,UpdateRecord> records = mLocationListeners.get(binder);
|
||||
HashMap<String,UpdateRecord> records = mLocationListeners.get(key);
|
||||
if (records == null) {
|
||||
records = new HashMap<String,UpdateRecord>();
|
||||
mLocationListeners.put(binder, records);
|
||||
mLocationListeners.put(key, records);
|
||||
}
|
||||
UpdateRecord oldRecord = records.put(provider, r);
|
||||
if (oldRecord != null) {
|
||||
@ -809,9 +908,12 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
} else {
|
||||
try {
|
||||
// Notify the listener that updates are currently disabled
|
||||
listener.onProviderDisabled(provider);
|
||||
if (receiver.isListener()) {
|
||||
receiver.getListener().onProviderDisabled(provider);
|
||||
}
|
||||
} catch(RemoteException e) {
|
||||
Log.w(TAG, "RemoteException calling onProviderDisabled on " + listener);
|
||||
Log.w(TAG, "RemoteException calling onProviderDisabled on " +
|
||||
receiver.getListener());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -822,7 +924,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
public void removeUpdates(ILocationListener listener) {
|
||||
try {
|
||||
_removeUpdates(listener);
|
||||
_removeUpdates(new Receiver(listener));
|
||||
} catch (SecurityException se) {
|
||||
throw se;
|
||||
} catch (Exception e) {
|
||||
@ -830,24 +932,34 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void _removeUpdates(ILocationListener listener) {
|
||||
public void removeUpdatesPI(PendingIntent intent) {
|
||||
try {
|
||||
_removeUpdates(new Receiver(intent));
|
||||
} catch (SecurityException se) {
|
||||
throw se;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "removeUpdates got exception:", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void _removeUpdates(Receiver receiver) {
|
||||
Object key = receiver.getKey();
|
||||
if (Config.LOGD) {
|
||||
Log.d(TAG, "_removeUpdates: listener = " + listener.asBinder());
|
||||
Log.d(TAG, "_removeUpdates: listener = " + key);
|
||||
}
|
||||
|
||||
// so wakelock calls will succeed
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLocationListeners) {
|
||||
IBinder binder = listener.asBinder();
|
||||
Listener myListener = mListeners.remove(binder);
|
||||
if (myListener != null) {
|
||||
binder.unlinkToDeath(myListener, 0);
|
||||
Receiver myReceiver = mListeners.remove(key);
|
||||
if ((myReceiver != null) && (myReceiver.isListener())) {
|
||||
myReceiver.getListener().asBinder().unlinkToDeath(myReceiver, 0);
|
||||
}
|
||||
|
||||
// Record which providers were associated with this listener
|
||||
HashSet<String> providers = new HashSet<String>();
|
||||
HashMap<String,UpdateRecord> oldRecords = mLocationListeners.get(binder);
|
||||
HashMap<String,UpdateRecord> oldRecords = mLocationListeners.get(key);
|
||||
if (oldRecords != null) {
|
||||
// Call dispose() on the obsolete update records.
|
||||
for (UpdateRecord record : oldRecords.values()) {
|
||||
@ -862,9 +974,9 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
providers.addAll(oldRecords.keySet());
|
||||
}
|
||||
|
||||
mLocationListeners.remove(binder);
|
||||
mLastFixBroadcast.remove(binder);
|
||||
mLastStatusBroadcast.remove(binder);
|
||||
mLocationListeners.remove(key);
|
||||
mLastFixBroadcast.remove(key);
|
||||
mLastStatusBroadcast.remove(key);
|
||||
|
||||
// See if the providers associated with this listener have any
|
||||
// other listeners; if one does, inform it of the new smallest minTime
|
||||
@ -894,7 +1006,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
updateWakelockStatus(mScreenOn);
|
||||
updateWakelockStatus(mScreenOn);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
@ -905,6 +1017,11 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
if (mGpsLocationProvider == null) {
|
||||
return false;
|
||||
}
|
||||
if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
|
||||
}
|
||||
|
||||
try {
|
||||
mGpsLocationProvider.addGpsStatusListener(listener);
|
||||
} catch (RemoteException e) {
|
||||
@ -996,7 +1113,6 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
ArrayList<PendingIntent> intentsToRemove = null;
|
||||
|
||||
for (ProximityAlert alert : mProximityAlerts.values()) {
|
||||
|
||||
PendingIntent intent = alert.getIntent();
|
||||
long expiration = alert.getExpiration();
|
||||
|
||||
@ -1115,7 +1231,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
mProximityAlerts.put(intent, alert);
|
||||
|
||||
if (mProximityListener == null) {
|
||||
mProximityListener = new ProximityListener();
|
||||
mProximityListener = new Receiver(new ProximityListener());
|
||||
|
||||
LocationProvider provider = LocationProviderImpl.getProvider(
|
||||
LocationManager.GPS_PROVIDER);
|
||||
@ -1345,15 +1461,15 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
// Broadcast location or status to all listeners
|
||||
for (UpdateRecord r : records) {
|
||||
ILocationListener listener = r.mListener.mListener;
|
||||
IBinder binder = listener.asBinder();
|
||||
Receiver receiver = r.mReceiver;
|
||||
Object key = receiver.getKey();
|
||||
|
||||
// Broadcast location only if it is valid
|
||||
if (locationValid) {
|
||||
HashMap<String,Location> map = mLastFixBroadcast.get(binder);
|
||||
HashMap<String,Location> map = mLastFixBroadcast.get(key);
|
||||
if (map == null) {
|
||||
map = new HashMap<String,Location>();
|
||||
mLastFixBroadcast.put(binder, map);
|
||||
mLastFixBroadcast.put(key, map);
|
||||
}
|
||||
Location lastLoc = map.get(provider);
|
||||
if ((lastLoc == null) || shouldBroadcast(loc, lastLoc, r)) {
|
||||
@ -1364,19 +1480,19 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
lastLoc.set(loc);
|
||||
}
|
||||
try {
|
||||
listener.onLocationChanged(loc);
|
||||
receiver.onLocationChanged(loc);
|
||||
} catch (RemoteException doe) {
|
||||
Log.w(TAG, "RemoteException calling onLocationChanged on " + listener);
|
||||
_removeUpdates(listener);
|
||||
Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
|
||||
_removeUpdates(receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast status message
|
||||
HashMap<String,Long> statusMap = mLastStatusBroadcast.get(binder);
|
||||
HashMap<String,Long> statusMap = mLastStatusBroadcast.get(key);
|
||||
if (statusMap == null) {
|
||||
statusMap = new HashMap<String,Long>();
|
||||
mLastStatusBroadcast.put(binder, statusMap);
|
||||
mLastStatusBroadcast.put(key, statusMap);
|
||||
}
|
||||
long prevStatusUpdateTime =
|
||||
(statusMap.get(provider) != null) ? statusMap.get(provider) : 0;
|
||||
@ -1386,10 +1502,10 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
statusMap.put(provider, newStatusUpdateTime);
|
||||
try {
|
||||
listener.onStatusChanged(provider, status, extras);
|
||||
receiver.onStatusChanged(provider, status, extras);
|
||||
} catch (RemoteException doe) {
|
||||
Log.w(TAG, "RemoteException calling onStatusChanged on " + listener);
|
||||
_removeUpdates(listener);
|
||||
Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
|
||||
_removeUpdates(receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1423,7 +1539,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
if ((mWakeLockAcquireTime != 0) &&
|
||||
(SystemClock.elapsedRealtime() - mWakeLockAcquireTime > MAX_TIME_FOR_WAKE_LOCK)) {
|
||||
(SystemClock.elapsedRealtime() - mWakeLockAcquireTime
|
||||
> MAX_TIME_FOR_WAKE_LOCK)) {
|
||||
|
||||
removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
|
||||
removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
|
||||
@ -1449,7 +1566,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
acquireWakeLock();
|
||||
} else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) {
|
||||
log("LocationWorkerHandler: Release");
|
||||
|
||||
|
||||
// Update wakelock status so the next alarm is set before releasing wakelock
|
||||
updateWakelockStatus(mScreenOn);
|
||||
releaseWakeLock();
|
||||
@ -1462,22 +1579,24 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||
|
||||
private CellState mLastCellState = null;
|
||||
@Override
|
||||
public void onCellLocationChanged(CellLocation cellLocation) {
|
||||
try {
|
||||
ServiceState serviceState = mServiceState;
|
||||
int asu = mSignalStrength;
|
||||
|
||||
// Gets cell state
|
||||
CellState cellState = new CellState(serviceState, cellLocation);
|
||||
mLastCellState = new CellState(mTelephonyManager, cellLocation, asu);
|
||||
|
||||
// Notify collector
|
||||
mCollector.updateCellState(cellState);
|
||||
mCollector.updateCellState(mLastCellState);
|
||||
|
||||
// Updates providers
|
||||
List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
|
||||
for (LocationProviderImpl provider : providers) {
|
||||
if (provider.requiresCell()) {
|
||||
provider.updateCellState(cellState);
|
||||
provider.updateCellState(mLastCellState);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -1486,8 +1605,19 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceStateChanged(ServiceState serviceState) {
|
||||
mServiceState = serviceState;
|
||||
public void onSignalStrengthChanged(int asu) {
|
||||
mSignalStrength = asu;
|
||||
|
||||
if (mLastCellState != null) {
|
||||
mLastCellState.updateSignalStrength(asu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataConnectionStateChanged(int state) {
|
||||
if (mLastCellState != null) {
|
||||
mLastCellState.updateRadioType(mTelephonyManager);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1578,7 +1708,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
} else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION)) {
|
||||
|
||||
final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false);
|
||||
final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED,
|
||||
false);
|
||||
|
||||
if (!enabled) {
|
||||
// When GPS is disabled, we are OK to release wake-lock
|
||||
@ -1608,7 +1739,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
if (screenOn) {
|
||||
startGps();
|
||||
} else if (mScreenOn && !screenOn) {
|
||||
|
||||
|
||||
// We just turned the screen off so stop navigating
|
||||
stopGps();
|
||||
}
|
||||
@ -1641,13 +1772,23 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
private void acquireWakeLock() {
|
||||
try {
|
||||
acquireWakeLockX();
|
||||
} catch (Exception e) {
|
||||
// This is to catch a runtime exception thrown when we try to release an
|
||||
// already released lock.
|
||||
Log.e(TAG, "exception in acquireWakeLock()", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void acquireWakeLockX() {
|
||||
if (mWakeLock.isHeld()) {
|
||||
log("Must release wakelock before acquiring");
|
||||
mWakeLockAcquireTime = 0;
|
||||
mWakeLock.release();
|
||||
}
|
||||
|
||||
boolean networkActive = (mNetworkLocationProvider != null)
|
||||
boolean networkActive = (mNetworkLocationProvider != null)
|
||||
&& mNetworkLocationProvider.isLocationTracking();
|
||||
boolean gpsActive = (mGpsLocationProvider != null)
|
||||
&& mGpsLocationProvider.isLocationTracking();
|
||||
@ -1668,7 +1809,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
// Start the gps provider
|
||||
startGps();
|
||||
|
||||
|
||||
// Acquire cell lock
|
||||
if (mCellWakeLockAcquired) {
|
||||
// Lock is already acquired
|
||||
@ -1700,7 +1841,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
private void startGps() {
|
||||
boolean gpsActive = (mGpsLocationProvider != null)
|
||||
boolean gpsActive = (mGpsLocationProvider != null)
|
||||
&& mGpsLocationProvider.isLocationTracking();
|
||||
if (gpsActive) {
|
||||
mGpsLocationProvider.startNavigating();
|
||||
@ -1708,7 +1849,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
private void stopGps() {
|
||||
boolean gpsActive = mGpsLocationProvider != null
|
||||
boolean gpsActive = mGpsLocationProvider != null
|
||||
&& mGpsLocationProvider.isLocationTracking();
|
||||
if (gpsActive) {
|
||||
mGpsLocationProvider.stopNavigating();
|
||||
@ -1716,6 +1857,16 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
private void releaseWakeLock() {
|
||||
try {
|
||||
releaseWakeLockX();
|
||||
} catch (Exception e) {
|
||||
// This is to catch a runtime exception thrown when we try to release an
|
||||
// already released lock.
|
||||
Log.e(TAG, "exception in releaseWakeLock()", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseWakeLockX() {
|
||||
// Release wifi lock
|
||||
WifiManager.WifiLock wifiLock = getWifiWakelock();
|
||||
if (wifiLock != null) {
|
||||
@ -1726,22 +1877,22 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
if (!mScreenOn) {
|
||||
|
||||
|
||||
// Stop the gps
|
||||
stopGps();
|
||||
}
|
||||
|
||||
|
||||
// Release cell lock
|
||||
if (mCellWakeLockAcquired) {
|
||||
mTelephonyManager.disableLocationUpdates();
|
||||
mCellWakeLockAcquired = false;
|
||||
}
|
||||
|
||||
|
||||
// Notify NetworkLocationProvider
|
||||
if (mNetworkLocationProvider != null) {
|
||||
mNetworkLocationProvider.updateCellLockStatus(mCellWakeLockAcquired);
|
||||
}
|
||||
|
||||
|
||||
// Release wake lock
|
||||
mWakeLockAcquireTime = 0;
|
||||
if (mWakeLock.isHeld()) {
|
||||
@ -1751,7 +1902,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
log("Can't release wakelock again!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Geocoder
|
||||
|
||||
public String getFromLocation(double latitude, double longitude, int maxResults,
|
||||
@ -1903,14 +2054,29 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return mSupportsSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMockPermissions() {
|
||||
boolean allowMocks = false;
|
||||
try {
|
||||
allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ALLOW_MOCK_LOCATION) == 1;
|
||||
} catch (SettingNotFoundException e) {
|
||||
// Do nothing
|
||||
}
|
||||
if (!allowMocks) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
|
||||
}
|
||||
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
}
|
||||
|
||||
public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
|
||||
boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
|
||||
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
|
||||
MockProvider provider = new MockProvider(name, requiresNetwork, requiresSatellite,
|
||||
requiresCell, hasMonetaryCost, supportsAltitude,
|
||||
@ -1923,10 +2089,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void removeTestProvider(String provider) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
|
||||
if (p == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
@ -1936,10 +2099,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void setTestProviderLocation(String provider, Location loc) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
if (LocationProviderImpl.getProvider(provider) == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
}
|
||||
@ -1947,10 +2107,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void clearTestProviderLocation(String provider) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
if (LocationProviderImpl.getProvider(provider) == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
}
|
||||
@ -1958,10 +2115,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void setTestProviderEnabled(String provider, boolean enabled) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
if (LocationProviderImpl.getProvider(provider) == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
}
|
||||
@ -1976,10 +2130,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void clearTestProviderEnabled(String provider) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
if (LocationProviderImpl.getProvider(provider) == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
}
|
||||
@ -1989,10 +2140,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
if (LocationProviderImpl.getProvider(provider) == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
}
|
||||
@ -2002,10 +2150,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
|
||||
public void clearTestProviderStatus(String provider) {
|
||||
if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
|
||||
}
|
||||
checkMockPermissions();
|
||||
if (LocationProviderImpl.getProvider(provider) == null) {
|
||||
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
|
||||
}
|
||||
|
Reference in New Issue
Block a user