use of com.android.server.location.LocationProviderInterface in project platform_frameworks_base by android.
the class LocationManagerService method updateProviderListenersLocked.
private void updateProviderListenersLocked(String provider, boolean enabled) {
int listeners = 0;
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null)
return;
ArrayList<Receiver> deadReceivers = null;
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records != null) {
final int N = records.size();
for (int i = 0; i < N; i++) {
UpdateRecord record = records.get(i);
if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
// Sends a notification message to the receiver
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<Receiver>();
}
deadReceivers.add(record.mReceiver);
}
listeners++;
}
}
}
if (deadReceivers != null) {
for (int i = deadReceivers.size() - 1; i >= 0; i--) {
removeUpdatesLocked(deadReceivers.get(i));
}
}
if (enabled) {
p.enable();
if (listeners > 0) {
applyRequirementsLocked(provider);
}
} else {
p.disable();
}
}
use of com.android.server.location.LocationProviderInterface in project platform_frameworks_base by android.
the class LocationManagerService method getLastLocation.
@Override
public Location getLastLocation(LocationRequest request, String packageName) {
if (D)
Log.d(TAG, "getLastLocation: " + request);
if (request == null)
request = DEFAULT_LOCATION_REQUEST;
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
checkPackageName(packageName);
checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, request.getProvider());
// no need to sanitize this request, as only the provider name is used
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
try {
if (mBlacklist.isBlacklisted(packageName)) {
if (D)
Log.d(TAG, "not returning last loc for blacklisted app: " + packageName);
return null;
}
if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
if (D)
Log.d(TAG, "not returning last loc for no op app: " + packageName);
return null;
}
synchronized (mLock) {
// Figure out the provider. Either its explicitly request (deprecated API's),
// or use the fused provider
String name = request.getProvider();
if (name == null)
name = LocationManager.FUSED_PROVIDER;
LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null)
return null;
if (!isAllowedByUserSettingsLocked(name, uid))
return null;
Location location;
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
// Make sure that an app with coarse permissions can't get frequent location
// updates by calling LocationManager.getLastKnownLocation repeatedly.
location = mLastLocationCoarseInterval.get(name);
} else {
location = mLastLocation.get(name);
}
if (location == null) {
return null;
}
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation != null) {
return new Location(mLocationFudger.getOrCreate(noGPSLocation));
}
} else {
return new Location(location);
}
}
return null;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
use of com.android.server.location.LocationProviderInterface in project platform_frameworks_base by android.
the class LocationManagerService method updateProvidersLocked.
private void updateProvidersLocked() {
boolean changesMade = false;
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderInterface p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
if (isEnabled && !shouldBeEnabled) {
updateProviderListenersLocked(name, false);
// If any provider has been disabled, clear all last locations for all providers.
// This is to be on the safe side in case a provider has location derived from
// this disabled provider.
mLastLocation.clear();
mLastLocationCoarseInterval.clear();
changesMade = true;
} else if (!isEnabled && shouldBeEnabled) {
updateProviderListenersLocked(name, true);
changesMade = true;
}
}
if (changesMade) {
mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), UserHandle.ALL);
mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION), UserHandle.ALL);
}
}
use of com.android.server.location.LocationProviderInterface in project android_frameworks_base by DirtyUnicorns.
the class LocationManagerService method handleLocationChangedLocked.
private void handleLocationChangedLocked(Location location, boolean passive) {
if (D)
Log.d(TAG, "incoming location: " + location);
long now = SystemClock.elapsedRealtime();
String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
// Skip if the provider is unknown.
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null)
return;
// Update last known locations
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Location lastNoGPSLocation = null;
Location lastLocation = mLastLocation.get(provider);
if (lastLocation == null) {
lastLocation = new Location(provider);
mLastLocation.put(provider, lastLocation);
} else {
lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation == null && lastNoGPSLocation != null) {
// New location has no no-GPS location: adopt last no-GPS location. This is set
// directly into location because we do not want to notify COARSE clients.
location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
}
}
lastLocation.set(location);
// Update last known coarse interval location if enough time has passed.
Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
if (lastLocationCoarseInterval == null) {
lastLocationCoarseInterval = new Location(location);
mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
}
long timeDiffNanos = location.getElapsedRealtimeNanos() - lastLocationCoarseInterval.getElapsedRealtimeNanos();
if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
lastLocationCoarseInterval.set(location);
}
// Don't ever return a coarse location that is more recent than the allowed update
// interval (i.e. don't allow an app to keep registering and unregistering for
// location updates to overcome the minimum interval).
noGPSLocation = lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
// Skip if there are no UpdateRecords for this provider.
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null || records.size() == 0)
return;
// Fetch coarse location
Location coarseLocation = null;
if (noGPSLocation != null) {
coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
}
// Fetch latest status update time
long newStatusUpdateTime = p.getStatusUpdateTime();
// Get latest status
Bundle extras = new Bundle();
int status = p.getStatus(extras);
ArrayList<Receiver> deadReceivers = null;
ArrayList<UpdateRecord> deadUpdateRecords = null;
// Broadcast location or status to all listeners
for (UpdateRecord r : records) {
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
int receiverUserId = UserHandle.getUserId(receiver.mUid);
if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) {
if (D) {
Log.d(TAG, "skipping loc update for background user " + receiverUserId + " (current user: " + mCurrentUserId + ", app: " + receiver.mPackageName + ")");
}
continue;
}
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
if (D)
Log.d(TAG, "skipping loc update for blacklisted app: " + receiver.mPackageName);
continue;
}
if (!reportLocationAccessNoThrow(receiver.mPid, receiver.mUid, receiver.mPackageName, receiver.mAllowedResolutionLevel)) {
if (D)
Log.d(TAG, "skipping loc update for no op app: " + receiver.mPackageName);
continue;
}
Location notifyLocation = null;
if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
// use coarse location
notifyLocation = coarseLocation;
} else {
// use fine location
notifyLocation = lastLocation;
}
if (notifyLocation != null) {
Location lastLoc = r.mLastFixBroadcast;
if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
if (lastLoc == null) {
lastLoc = new Location(notifyLocation);
r.mLastFixBroadcast = lastLoc;
} else {
lastLoc.set(notifyLocation);
}
if (!receiver.callLocationChangedLocked(notifyLocation)) {
Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
receiverDead = true;
}
r.mRequest.decrementNumUpdates();
}
}
long prevStatusUpdateTime = r.mLastStatusBroadcast;
if ((newStatusUpdateTime > prevStatusUpdateTime) && (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
r.mLastStatusBroadcast = newStatusUpdateTime;
if (!receiver.callStatusChangedLocked(provider, status, extras)) {
receiverDead = true;
Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
}
}
// track expired records
if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
if (deadUpdateRecords == null) {
deadUpdateRecords = new ArrayList<UpdateRecord>();
}
deadUpdateRecords.add(r);
}
// track dead receivers
if (receiverDead) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<Receiver>();
}
if (!deadReceivers.contains(receiver)) {
deadReceivers.add(receiver);
}
}
}
// remove dead records and receivers outside the loop
if (deadReceivers != null) {
for (Receiver receiver : deadReceivers) {
removeUpdatesLocked(receiver);
}
}
if (deadUpdateRecords != null) {
for (UpdateRecord r : deadUpdateRecords) {
r.disposeLocked(true);
}
applyRequirementsLocked(provider);
}
}
use of com.android.server.location.LocationProviderInterface in project android_frameworks_base by DirtyUnicorns.
the class LocationManagerService method requestLocationUpdatesLocked.
private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, int pid, int uid, String packageName) {
// use the fused provider
if (request == null)
request = DEFAULT_LOCATION_REQUEST;
String name = request.getProvider();
if (name == null) {
throw new IllegalArgumentException("provider name must not be null");
}
if (D)
Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " + name + " " + request + " from " + packageName + "(" + uid + ")");
LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null) {
throw new IllegalArgumentException("provider doesn't exist: " + name);
}
UpdateRecord record = new UpdateRecord(name, request, receiver);
UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
if (oldRecord != null) {
oldRecord.disposeLocked(false);
}
boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
if (isProviderEnabled) {
applyRequirementsLocked(name);
} else {
// Notify the listener that updates are currently disabled
receiver.callProviderEnabledLocked(name, false);
}
// Update the monitoring here just in case multiple location requests were added to the
// same receiver (this request may be high power and the initial might not have been).
receiver.updateMonitoring(true);
}
Aggregations