location: Use ILocationProvider Binder interface for all location providers.

This change eliminates the LocationProviderImpl class which had been used
for location providers running in the system process.
Now the LocationProvider base class is only used to implement the
LocationManager.createProvider() method for retrieving provider information.
Added a new IGpsStatusProvider interface for providers that serve GPS status.

Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2009-05-01 07:53:28 -04:00
parent a56b318cf2
commit 15e3d0f082
9 changed files with 281 additions and 428 deletions

View File

@ -116,6 +116,7 @@ LOCAL_SRC_FILES += \
im/java/android/im/IImPlugin.aidl \
location/java/android/location/IGeocodeProvider.aidl \
location/java/android/location/IGpsStatusListener.aidl \
location/java/android/location/IGpsStatusProvider.aidl \
location/java/android/location/ILocationCollector.aidl \
location/java/android/location/ILocationListener.aidl \
location/java/android/location/ILocationManager.aidl \

View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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 android.location;
import android.location.IGpsStatusListener;
/**
* An interface for location providers that provide GPS status information.
*
* {@hide}
*/
interface IGpsStatusProvider {
void addGpsStatusListener(IGpsStatusListener listener);
void removeGpsStatusListener(IGpsStatusListener listener);
}

View File

@ -19,13 +19,11 @@ package android.location;
import android.os.Bundle;
/**
* An interface for location providers implemented outside of the system process.
* Binder interface for location providers.
*
* {@hide}
*/
interface ILocationProvider {
/* for LocationProvider */
boolean requiresNetwork();
boolean requiresSatellite();
boolean requiresCell();
@ -35,8 +33,6 @@ interface ILocationProvider {
boolean supportsBearing();
int getPowerRequirement();
int getAccuracy();
/* for LocationProviderImpl */
void enable();
void disable();
boolean isEnabled();

View File

@ -22,7 +22,9 @@ 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.ILocationProvider;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
@ -54,7 +56,7 @@ import java.util.Properties;
*
* {@hide}
*/
public class GpsLocationProvider extends LocationProviderImpl {
public class GpsLocationProvider extends ILocationProvider.Stub {
private static final String TAG = "GpsLocationProvider";
@ -142,7 +144,7 @@ public class GpsLocationProvider extends LocationProviderImpl {
private int mLocationFlags = LOCATION_INVALID;
// current status
private int mStatus = TEMPORARILY_UNAVAILABLE;
private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
// time for last status update
private long mStatusUpdateTime = SystemClock.elapsedRealtime();
@ -178,7 +180,8 @@ public class GpsLocationProvider extends LocationProviderImpl {
private Properties mProperties;
private String mNtpServer;
private Context mContext;
private final Context mContext;
private final ILocationManager mLocationManager;
private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
private Bundle mLocationExtras = new Bundle();
private ArrayList<Listener> mListeners = new ArrayList<Listener>();
@ -203,6 +206,57 @@ public class GpsLocationProvider extends LocationProviderImpl {
// current setting - 5 minutes
private static final long RETRY_INTERVAL = 5*60*1000;
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
if (listener == null) {
throw new NullPointerException("listener is null in addGpsStatusListener");
}
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 addGpsStatusListener");
}
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;
}
private class TelephonyBroadcastReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@ -231,8 +285,8 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
public GpsLocationProvider(Context context, ILocationManager locationManager) {
super(LocationManager.GPS_PROVIDER, locationManager);
mContext = context;
mLocationManager = locationManager;
TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
@ -270,7 +324,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* Returns true if the provider requires access to a
* data network (e.g., the Internet), false otherwise.
*/
@Override
public boolean requiresNetwork() {
// We want updateNetworkState() to get called when the network state changes
// for XTRA and NTP time injection support.
@ -295,7 +348,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* satellite-based positioning system (e.g., GPS), false
* otherwise.
*/
@Override
public boolean requiresSatellite() {
return true;
}
@ -305,7 +357,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* cellular network (e.g., to make use of cell tower IDs), false
* otherwise.
*/
@Override
public boolean requiresCell() {
return false;
}
@ -315,7 +366,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* monetary charge to the user, false if use is free. It is up to
* each provider to give accurate information.
*/
@Override
public boolean hasMonetaryCost() {
return false;
}
@ -326,7 +376,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* under most circumstances but may occassionally not report it
* should return true.
*/
@Override
public boolean supportsAltitude() {
return true;
}
@ -337,7 +386,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* under most circumstances but may occassionally not report it
* should return true.
*/
@Override
public boolean supportsSpeed() {
return true;
}
@ -348,7 +396,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* under most circumstances but may occassionally not report it
* should return true.
*/
@Override
public boolean supportsBearing() {
return true;
}
@ -359,7 +406,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* @return the power requirement for this provider, as one of the
* constants Criteria.POWER_REQUIREMENT_*.
*/
@Override
public int getPowerRequirement() {
return Criteria.POWER_HIGH;
}
@ -370,7 +416,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* @return the accuracy of location from this provider, as one
* of the constants Criteria.ACCURACY_*.
*/
@Override
public int getAccuracy() {
return Criteria.ACCURACY_FINE;
}
@ -380,7 +425,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* must be handled. Hardware may be started up
* when the provider is enabled.
*/
@Override
public synchronized void enable() {
if (Config.LOGD) Log.d(TAG, "enable");
if (mEnabled) return;
@ -410,7 +454,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
* need not be handled. Hardware may be shut
* down while the provider is disabled.
*/
@Override
public synchronized void disable() {
if (Config.LOGD) Log.d(TAG, "disable");
if (!mEnabled) return;
@ -443,12 +486,10 @@ public class GpsLocationProvider extends LocationProviderImpl {
native_cleanup();
}
@Override
public boolean isEnabled() {
return mEnabled;
}
@Override
public int getStatus(Bundle extras) {
if (extras != null) {
extras.putInt("satellites", mSvCount);
@ -465,14 +506,11 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
}
@Override
public long getStatusUpdateTime() {
return mStatusUpdateTime;
}
@Override
public void enableLocationTracking(boolean enable) {
super.enableLocationTracking(enable);
if (enable) {
mFixRequestTime = System.currentTimeMillis();
mTTFF = 0;
@ -483,9 +521,7 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
}
@Override
public void setMinTime(long minTime) {
super.setMinTime(minTime);
if (Config.LOGD) Log.d(TAG, "setMinTime " + minTime);
if (minTime >= 0) {
@ -516,48 +552,12 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
}
public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
if (listener == null) throw new NullPointerException("listener is null in addGpsStatusListener");
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 addGpsStatusListener");
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 void wakeLockAcquired() {
}
public void wakeLockReleased() {
}
@Override
public void addListener(int uid) {
mClientUids.put(uid, 0);
if (mNavigating) {
@ -569,7 +569,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
}
@Override
public void removeListener(int uid) {
mClientUids.delete(uid);
if (mNavigating) {
@ -581,7 +580,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
}
@Override
public boolean sendExtraCommand(String command, Bundle extras) {
if ("delete_aiding_data".equals(command)) {
@ -632,7 +630,7 @@ public class GpsLocationProvider extends LocationProviderImpl {
}
// reset SV count to zero
updateStatus(TEMPORARILY_UNAVAILABLE, 0);
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
}
}
@ -646,7 +644,7 @@ public class GpsLocationProvider extends LocationProviderImpl {
mLocationFlags = LOCATION_INVALID;
// reset SV count to zero
updateStatus(TEMPORARILY_UNAVAILABLE, 0);
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
}
}
@ -709,15 +707,19 @@ public class GpsLocationProvider extends LocationProviderImpl {
mLocation.removeAccuracy();
}
reportLocationChanged(mLocation);
try {
mLocationManager.setLocation(mLocation);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
}
if (mStarted && mStatus != AVAILABLE) {
if (mStarted && mStatus != LocationProvider.AVAILABLE) {
// send an intent to notify that the GPS is receiving fixes.
Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
intent.putExtra(EXTRA_ENABLED, true);
mContext.sendBroadcast(intent);
updateStatus(AVAILABLE, mSvCount);
updateStatus(LocationProvider.AVAILABLE, mSvCount);
}
}
@ -812,13 +814,13 @@ public class GpsLocationProvider extends LocationProviderImpl {
updateStatus(mStatus, svCount);
if (mNavigating && mStatus == AVAILABLE && mLastFixTime > 0 &&
if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
// send an intent to notify that the GPS is no longer receiving fixes.
Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
intent.putExtra(EXTRA_ENABLED, false);
mContext.sendBroadcast(intent);
updateStatus(TEMPORARILY_UNAVAILABLE, mSvCount);
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
}
}

View File

@ -1,234 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* 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.internal.location;
import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
/**
* An abstract superclass for location provider implementations.
* Location provider implementations are typically instantiated by the
* location manager service in the system process, and location
* information is made available to implementations via the manager.
*
* {@hide}
*/
public abstract class LocationProviderImpl extends LocationProvider {
private static final String TAG = "LocationProviderImpl";
private static ArrayList<LocationProviderImpl> sProviders =
new ArrayList<LocationProviderImpl>();
private static HashMap<String, LocationProviderImpl> sProvidersByName
= new HashMap<String, LocationProviderImpl>();
private final ILocationManager mLocationManager;
private boolean mLocationTracking = false;
private long mMinTime = 0;
protected LocationProviderImpl(String name, ILocationManager locationManager) {
super(name);
mLocationManager = locationManager;
}
public static void addProvider(LocationProviderImpl provider) {
sProviders.add(provider);
sProvidersByName.put(provider.getName(), provider);
}
public static void removeProvider(LocationProviderImpl provider) {
sProviders.remove(provider);
sProvidersByName.remove(provider.getName());
}
public static ArrayList<LocationProviderImpl> getProviders() {
return sProviders;
}
public static LocationProviderImpl getProvider(String name) {
return sProvidersByName.get(name);
}
public void reportLocationChanged(Location location) {
try {
mLocationManager.setLocation(location);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ILocationManager.setLocation");
}
}
/**
* Enables this provider. When enabled, calls to {@link #getStatus()}
* must be handled. Hardware may be started up
* when the provider is enabled.
*/
public abstract void enable();
/**
* Disables this provider. When disabled, calls to {@link #getStatus()}
* need not be handled. Hardware may be shut
* down while the provider is disabled.
*/
public abstract void disable();
/**
* Returns true if this provider is enabled, false otherwise;
*/
public abstract boolean isEnabled();
/**
* Returns a information on the status of this provider.
* {@link #OUT_OF_SERVICE} is returned if the provider is
* out of service, and this is not expected to change in the near
* future; {@link #TEMPORARILY_UNAVAILABLE} is returned if
* the provider is temporarily unavailable but is expected to be
* available shortly; and {@link #AVAILABLE} is returned
* if the provider is currently available.
*/
public int getStatus() {
return getStatus(null);
}
/**
* Returns a information on the status of this provider.
* {@link #OUT_OF_SERVICE} is returned if the provider is
* out of service, and this is not expected to change in the near
* future; {@link #TEMPORARILY_UNAVAILABLE} is returned if
* the provider is temporarily unavailable but is expected to be
* available shortly; and {@link #AVAILABLE} is returned
* if the provider is currently available.
*
* <p> If extras is non-null, additional status information may be
* added to it in the form of provider-specific key/value pairs.
*/
public abstract int getStatus(Bundle extras);
/**
* Returns the time at which the status was last updated. It is the
* responsibility of the provider to appropriately set this value
* using {@link android.os.SystemClock.elapsedRealtime()} each time
* there is a status update that it wishes to broadcast to all its
* listeners. The provider should be careful not to broadcast
* the same status again.
*
* @return time of last status update in millis since last reboot
*/
public long getStatusUpdateTime() {
return 0;
}
/**
* Notifies the location provider that clients are listening for locations.
* Called with enable set to true when the first client is added and
* called with enable set to false when the last client is removed.
* This allows the provider to prepare for receiving locations,
* and to shut down when no clients are remaining.
*
* @param enable true if location tracking should be enabled.
*/
public void enableLocationTracking(boolean enable) {
mLocationTracking = enable;
}
/**
* Returns true if the provider has any listeners
*
* @return true if provider is being tracked
*/
public boolean isLocationTracking() {
return mLocationTracking;
}
/**
* Notifies the location provider of the smallest minimum time between updates amongst
* all clients that are listening for locations. This allows the provider to reduce
* the frequency of updates to match the requested frequency.
*
* @param minTime the smallest minTime value over all listeners for this provider.
*/
public void setMinTime(long minTime) {
mMinTime = minTime;
}
/**
* Gets the smallest minimum time between updates amongst all the clients listening
* for locations. By default this value is 0 (as frqeuently as possible)
*
* @return the smallest minTime value over all listeners for this provider
*/
public long getMinTime() {
return mMinTime;
}
/**
* Updates the network state for the given provider. This function must
* be overwritten if {@link #requiresNetwork} returns true. The state is
* {@link #TEMPORARILY_UNAVAILABLE} (disconnected), OR {@link #AVAILABLE}
* (connected or connecting).
*
* @param state data state
*/
public void updateNetworkState(int state) {
}
/**
* Implements addditional location provider specific additional commands.
*
* @param command name of the command to send to the provider.
* @param extras optional arguments for the command (or null).
* The provider may optionally fill the extras Bundle with results from the command.
*
* @return true if the command succeeds.
*/
public boolean sendExtraCommand(String command, Bundle extras) {
return false;
}
/**
* Informs the location provider when a new client is listening for location information
*
* @param uid the uid of the client proces
*/
public void addListener(int uid) {
}
/**
* Informs the location provider when a client is no longer listening for location information
*
* @param uid the uid of the client proces
*/
public void removeListener(int uid) {
}
/**
* Informs the location provider when the location manager service has acquired its wake lock
*/
public void wakeLockAcquired() {
}
/**
* Informs the location provider when the location manager service has released its wake lock
*/
public void wakeLockReleased() {
}
}

View File

@ -17,7 +17,6 @@
package com.android.internal.location;
import android.location.Address;
import android.location.ILocationManager;
import android.location.ILocationProvider;
import android.location.Location;
import android.location.LocationManager;
@ -32,19 +31,24 @@ import java.util.List;
*
* {@hide}
*/
public class LocationProviderProxy extends LocationProviderImpl {
public class LocationProviderProxy {
private static final String TAG = "LocationProviderProxy";
private final String mName;
private final ILocationProvider mProvider;
private boolean mLocationTracking = false;
private long mMinTime = 0;
public LocationProviderProxy(String name, ILocationManager locationManager,
ILocationProvider provider) {
super(name, locationManager);
public LocationProviderProxy(String name, ILocationProvider provider) {
mName = name;
mProvider = provider;
}
@Override
public String getName() {
return mName;
}
public boolean requiresNetwork() {
try {
return mProvider.requiresNetwork();
@ -54,7 +58,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean requiresSatellite() {
try {
return mProvider.requiresSatellite();
@ -64,7 +67,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean requiresCell() {
try {
return mProvider.requiresCell();
@ -74,7 +76,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean hasMonetaryCost() {
try {
return mProvider.hasMonetaryCost();
@ -84,7 +85,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean supportsAltitude() {
try {
return mProvider.supportsAltitude();
@ -94,7 +94,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean supportsSpeed() {
try {
return mProvider.supportsSpeed();
@ -104,8 +103,7 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean supportsBearing() {
public boolean supportsBearing() {
try {
return mProvider.supportsBearing();
} catch (RemoteException e) {
@ -114,7 +112,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public int getPowerRequirement() {
try {
return mProvider.getPowerRequirement();
@ -124,7 +121,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public int getAccuracy() {
try {
return mProvider.getAccuracy();
@ -134,7 +130,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public void enable() {
try {
mProvider.enable();
@ -143,7 +138,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public void disable() {
try {
mProvider.disable();
@ -152,7 +146,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean isEnabled() {
try {
return mProvider.isEnabled();
@ -162,7 +155,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public int getStatus(Bundle extras) {
try {
return mProvider.getStatus(extras);
@ -172,7 +164,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public long getStatusUpdateTime() {
try {
return mProvider.getStatusUpdateTime();
@ -182,27 +173,32 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean isLocationTracking() {
return mLocationTracking;
}
public void enableLocationTracking(boolean enable) {
mLocationTracking = enable;
try {
super.enableLocationTracking(enable);
mProvider.enableLocationTracking(enable);
} catch (RemoteException e) {
Log.e(TAG, "enableLocationTracking failed", e);
}
}
@Override
public long getMinTime() {
return mMinTime;
}
public void setMinTime(long minTime) {
mMinTime = minTime;
try {
super.setMinTime(minTime);
mProvider.setMinTime(minTime);
} catch (RemoteException e) {
Log.e(TAG, "setMinTime failed", e);
}
}
@Override
public void updateNetworkState(int state) {
try {
mProvider.updateNetworkState(state);
@ -211,7 +207,6 @@ public class LocationProviderProxy extends LocationProviderImpl {
}
}
@Override
public boolean sendExtraCommand(String command, Bundle extras) {
try {
return mProvider.sendExtraCommand(command, extras);

View File

@ -17,8 +17,12 @@
package com.android.internal.location;
import android.location.ILocationManager;
import android.location.ILocationProvider;
import android.location.Location;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.util.PrintWriterPrinter;
import java.io.PrintWriter;
@ -28,7 +32,9 @@ import java.io.PrintWriter;
*
* {@hide}
*/
public class MockProvider extends LocationProviderImpl {
public class MockProvider extends ILocationProvider.Stub {
private final String mName;
private final ILocationManager mLocationManager;
private final boolean mRequiresNetwork;
private final boolean mRequiresSatellite;
private final boolean mRequiresCell;
@ -46,12 +52,14 @@ public class MockProvider extends LocationProviderImpl {
private boolean mHasStatus;
private boolean mEnabled;
private static final String TAG = "MockProvider";
public MockProvider(String name, ILocationManager locationManager,
boolean requiresNetwork, boolean requiresSatellite,
boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
super(name, locationManager);
mName = name;
mLocationManager = locationManager;
mRequiresNetwork = requiresNetwork;
mRequiresSatellite = requiresSatellite;
mRequiresCell = requiresCell;
@ -64,78 +72,64 @@ public class MockProvider extends LocationProviderImpl {
mLocation = new Location(name);
}
@Override
public void disable() {
mEnabled = false;
}
@Override
public void enable() {
mEnabled = true;
}
@Override
public int getStatus(Bundle extras) {
if (mHasStatus) {
extras.clear();
extras.putAll(mExtras);
return mStatus;
} else {
return AVAILABLE;
return LocationProvider.AVAILABLE;
}
}
@Override
public long getStatusUpdateTime() {
return mStatusUpdateTime;
}
@Override
public boolean isEnabled() {
return mEnabled;
}
@Override
public int getAccuracy() {
return mAccuracy;
}
@Override
public int getPowerRequirement() {
return mPowerRequirement;
}
@Override
public boolean hasMonetaryCost() {
return mHasMonetaryCost;
}
@Override
public boolean requiresCell() {
return mRequiresCell;
}
@Override
public boolean requiresNetwork() {
return mRequiresNetwork;
}
@Override
public boolean requiresSatellite() {
return mRequiresSatellite;
}
@Override
public boolean supportsAltitude() {
return mSupportsAltitude;
}
@Override
public boolean supportsBearing() {
return mSupportsBearing;
}
@Override
public boolean supportsSpeed() {
return mSupportsSpeed;
}
@ -143,7 +137,11 @@ public class MockProvider extends LocationProviderImpl {
public void setLocation(Location l) {
mLocation.set(l);
mHasLocation = true;
reportLocationChanged(mLocation);
try {
mLocationManager.setLocation(mLocation);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
}
public void clearLocation() {
@ -165,8 +163,33 @@ public class MockProvider extends LocationProviderImpl {
mStatusUpdateTime = 0;
}
public void enableLocationTracking(boolean enable) {
}
public void setMinTime(long minTime) {
}
public void updateNetworkState(int state) {
}
public boolean sendExtraCommand(String command, Bundle extras) {
return false;
}
public void addListener(int uid) {
}
public void removeListener(int uid) {
}
public void wakeLockAcquired() {
}
public void wakeLockReleased() {
}
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + getName());
pw.println(prefix + mName);
pw.println(prefix + "mHasLocation=" + mHasLocation);
pw.println(prefix + "mLocation:");
mLocation.dump(new PrintWriterPrinter(pw), prefix + " ");

View File

@ -46,6 +46,7 @@ import android.database.Cursor;
import android.location.Address;
import android.location.IGeocodeProvider;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
import android.location.ILocationCollector;
import android.location.ILocationListener;
import android.location.ILocationManager;
@ -72,7 +73,6 @@ import android.util.PrintWriterPrinter;
import android.util.SparseIntArray;
import com.android.internal.location.GpsLocationProvider;
import com.android.internal.location.LocationProviderImpl;
import com.android.internal.location.LocationProviderProxy;
import com.android.internal.location.MockProvider;
import com.android.server.am.BatteryStatsService;
@ -119,9 +119,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
private static boolean sProvidersLoaded = false;
private final Context mContext;
private GpsLocationProvider mGpsLocationProvider;
private LocationProviderProxy mGpsLocationProvider;
private LocationProviderProxy mNetworkLocationProvider;
private IGeocodeProvider mGeocodeProvider;
private IGpsStatusProvider mGpsStatusProvider;
private LocationWorkerHandler mLocationHandler;
// Handler messages
@ -143,6 +144,15 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
*/
private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
/**
* List of location providers.
*/
private final ArrayList<LocationProviderProxy> mProviders =
new ArrayList<LocationProviderProxy>();
private final HashMap<String, LocationProviderProxy> mProvidersByName
= new HashMap<String, LocationProviderProxy>();
/**
* Object used internally for synchronization
*/
@ -502,6 +512,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
}
private void addProvider(LocationProviderProxy provider) {
mProviders.add(provider);
mProvidersByName.put(provider.getName(), provider);
}
private void removeProvider(LocationProviderProxy provider) {
mProviders.remove(provider);
mProvidersByName.remove(provider.getName());
}
/**
* Load providers from /data/location/<provider_name>/
* class
@ -535,8 +555,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// Attempt to load "real" providers first
if (GpsLocationProvider.isSupported()) {
// Create a gps location provider
mGpsLocationProvider = new GpsLocationProvider(mContext, this);
LocationProviderImpl.addProvider(mGpsLocationProvider);
GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
mGpsStatusProvider = provider.getGpsStatusProvider();
mGpsLocationProvider =
new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
addProvider(mGpsLocationProvider);
}
updateProvidersLocked();
@ -611,8 +634,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
synchronized (mLock) {
mNetworkLocationProvider =
new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, this, provider);
LocationProviderImpl.addProvider(mNetworkLocationProvider);
new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, provider);
addProvider(mNetworkLocationProvider);
updateProvidersLocked();
// notify NetworkLocationProvider of any events it might have missed
@ -703,10 +726,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (LOCAL_LOGV) {
Log.v(TAG, "getAllProviders");
}
ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
ArrayList<String> out = new ArrayList<String>(providers.size());
for (int i = providers.size() - 1; i >= 0; i--) {
LocationProviderImpl p = providers.get(i);
ArrayList<String> out = new ArrayList<String>(mProviders.size());
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderProxy p = mProviders.get(i);
out.add(p.getName());
}
return out;
@ -729,10 +751,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (LOCAL_LOGV) {
Log.v(TAG, "getProviders");
}
ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
ArrayList<String> out = new ArrayList<String>(providers.size());
for (int i = providers.size() - 1; i >= 0; i--) {
LocationProviderImpl p = providers.get(i);
ArrayList<String> out = new ArrayList<String>(mProviders.size());
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderProxy p = mProviders.get(i);
String name = p.getName();
if (isAllowedProviderSafe(name)) {
if (enabledOnly && !isAllowedBySettingsLocked(name)) {
@ -745,9 +766,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
private void updateProvidersLocked() {
ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
for (int i = providers.size() - 1; i >= 0; i--) {
LocationProviderImpl p = providers.get(i);
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderProxy p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
@ -764,7 +784,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
private void updateProviderListenersLocked(String provider, boolean enabled) {
int listeners = 0;
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
return;
}
@ -966,8 +986,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
}
LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
if (impl == null) {
LocationProviderProxy proxy = mProvidersByName.get(provider);
if (proxy == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@ -985,14 +1005,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
if (newUid) {
impl.addListener(callingUid);
proxy.addListener(callingUid);
}
boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
if (isProviderEnabled) {
long minTimeForProvider = getMinTimeLocked(provider);
impl.setMinTime(minTimeForProvider);
impl.enableLocationTracking(true);
proxy.setMinTime(minTimeForProvider);
proxy.enableLocationTracking(true);
updateWakelockStatusLocked();
} else {
// Notify the listener that updates are currently disabled
@ -1047,10 +1067,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// Call dispose() on the obsolete update records.
for (UpdateRecord record : oldRecords.values()) {
if (!providerHasListener(record.mProvider, callingUid, receiver)) {
LocationProviderImpl impl =
LocationProviderImpl.getProvider(record.mProvider);
if (impl != null) {
impl.removeListener(callingUid);
LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
if (proxy != null) {
proxy.removeListener(callingUid);
}
}
record.disposeLocked();
@ -1074,7 +1093,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
hasOtherListener = true;
}
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
LocationProviderProxy p = mProvidersByName.get(provider);
if (p != null) {
if (hasOtherListener) {
p.setMinTime(getMinTimeLocked(provider));
@ -1091,7 +1110,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
public boolean addGpsStatusListener(IGpsStatusListener listener) {
if (mGpsLocationProvider == null) {
if (mGpsStatusProvider == null) {
return false;
}
if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) !=
@ -1100,9 +1119,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
try {
mGpsLocationProvider.addGpsStatusListener(listener);
mGpsStatusProvider.addGpsStatusListener(listener);
} catch (RemoteException e) {
Log.w(TAG, "RemoteException in addGpsStatusListener");
Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
return false;
}
return true;
@ -1110,7 +1129,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
public void removeGpsStatusListener(IGpsStatusListener listener) {
synchronized (mLock) {
mGpsLocationProvider.removeGpsStatusListener(listener);
try {
mGpsStatusProvider.removeGpsStatusListener(listener);
} catch (Exception e) {
Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
}
}
}
@ -1124,12 +1147,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
synchronized (mLock) {
LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
LocationProviderProxy proxy = mProvidersByName.get(provider);
if (provider == null) {
return false;
}
return impl.sendExtraCommand(command, extras);
return proxy.sendExtraCommand(command, extras);
}
}
@ -1359,14 +1382,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
mProximityListener = new ProximityListener();
mProximityReceiver = new Receiver(mProximityListener);
LocationProvider provider = LocationProviderImpl.getProvider(
LocationManager.GPS_PROVIDER);
LocationProviderProxy provider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
if (provider != null) {
requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
}
provider =
LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER);
provider = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
if (provider != null) {
requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
}
@ -1417,7 +1438,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
}
private Bundle _getProviderInfoLocked(String provider) {
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
return null;
}
@ -1460,7 +1481,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
private boolean _isProviderEnabledLocked(String provider) {
checkPermissionsSafe(provider);
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@ -1483,7 +1504,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
private Location _getLastKnownLocationLocked(String provider) {
checkPermissionsSafe(provider);
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@ -1534,7 +1555,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
return;
}
LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
LocationProviderProxy p = mProvidersByName.get(provider);
if (p == null) {
return;
}
@ -1550,9 +1571,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (LocationManager.NETWORK_PROVIDER.equals(p.getName())) {
mWakeLockNetworkReceived = true;
} else if (p instanceof GpsLocationProvider) {
// Gps location received signal is in NetworkStateBroadcastReceiver
}
// Gps location received signal is in NetworkStateBroadcastReceiver
// Fetch latest status update time
long newStatusUpdateTime = p.getStatusUpdateTime();
@ -1720,9 +1740,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// Notify location providers of current network state
synchronized (mLock) {
ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
for (int i = providers.size() - 1; i >= 0; i--) {
LocationProviderImpl provider = providers.get(i);
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderProxy provider = mProviders.get(i);
if (provider.requiresNetwork()) {
provider.updateNetworkState(mNetworkState);
}
@ -1930,10 +1949,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
requiresNetwork, requiresSatellite,
requiresCell, hasMonetaryCost, supportsAltitude,
supportsSpeed, supportsBearing, powerRequirement, accuracy);
if (LocationProviderImpl.getProvider(name) != null) {
if (mProvidersByName.get(name) != null) {
throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
}
LocationProviderImpl.addProvider(provider);
addProvider(new LocationProviderProxy(name, provider));
mMockProviders.put(name, provider);
updateProvidersLocked();
}
@ -1946,7 +1965,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
if (mockProvider == null) {
throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
}
LocationProviderImpl.removeProvider(mockProvider);
removeProvider(mProvidersByName.get(provider));
mMockProviders.remove(mockProvider);
updateProvidersLocked();
}

View File

@ -19,17 +19,19 @@ package android.test;
import android.location.Criteria;
import android.location.ILocationManager;
import android.location.ILocationProvider;
import android.location.Location;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
import com.android.internal.location.LocationProviderImpl;
import android.util.Log;
/**
* @hide - This is part of a framework that is under development and should not be used for
* active development.
*/
public class TestLocationProvider extends LocationProviderImpl {
public class TestLocationProvider extends ILocationProvider.Stub {
public static final String PROVIDER_NAME = "test";
public static final double LAT = 0;
@ -37,9 +39,12 @@ public class TestLocationProvider extends LocationProviderImpl {
public static final double ALTITUDE = 10000;
public static final float SPEED = 10;
public static final float BEARING = 1;
public static final int STATUS = AVAILABLE;
public static final int STATUS = LocationProvider.AVAILABLE;
private static final long LOCATION_INTERVAL = 1000;
private static final String TAG = "TestLocationProvider";
private final ILocationManager mLocationManager;
private Location mLocation;
private boolean mEnabled;
private TestLocationProviderThread mThread;
@ -75,59 +80,46 @@ public class TestLocationProvider extends LocationProviderImpl {
}
public TestLocationProvider(ILocationManager locationManager) {
super(PROVIDER_NAME, locationManager);
mLocationManager = locationManager;
mLocation = new Location(PROVIDER_NAME);
}
//LocationProvider methods
@Override
public int getAccuracy() {
return Criteria.ACCURACY_COARSE;
}
@Override
public int getPowerRequirement() {
return Criteria.NO_REQUIREMENT;
}
@Override
public boolean hasMonetaryCost() {
return false;
}
@Override
public boolean requiresCell() {
return false;
}
@Override
public boolean requiresNetwork() {
return false;
}
@Override
public boolean requiresSatellite() {
return false;
}
@Override
public boolean supportsAltitude() {
return true;
}
@Override
public boolean supportsBearing() {
return true;
}
@Override
public boolean supportsSpeed() {
return true;
}
//LocationProviderImpl methods
@Override
public synchronized void disable() {
mEnabled = false;
if (mThread != null) {
@ -140,23 +132,49 @@ public class TestLocationProvider extends LocationProviderImpl {
}
}
@Override
public synchronized void enable() {
mEnabled = true;
mThread = new TestLocationProviderThread();
mThread.start();
}
@Override
public boolean isEnabled() {
return mEnabled;
}
@Override
public int getStatus(Bundle extras) {
return STATUS;
}
public long getStatusUpdateTime() {
return 0;
}
public void enableLocationTracking(boolean enable) {
}
public void setMinTime(long minTime) {
}
public void updateNetworkState(int state) {
}
public boolean sendExtraCommand(String command, Bundle extras) {
return false;
}
public void addListener(int uid) {
}
public void removeListener(int uid) {
}
public void wakeLockAcquired() {
}
public void wakeLockReleased() {
}
private void updateLocation() {
long time = SystemClock.uptimeMillis();
long multiplier = (time/5000)%500000;
@ -170,7 +188,11 @@ public class TestLocationProvider extends LocationProviderImpl {
extras.putInt("extraTest", 24);
mLocation.setExtras(extras);
mLocation.setTime(time);
reportLocationChanged(mLocation);
try {
mLocationManager.setLocation(mLocation);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling updateLocation");
}
}
}