diff options
7 files changed, 184 insertions, 14 deletions
diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java index 4696b2a..5d40e94 100644 --- a/core/java/android/hardware/location/GeofenceHardwareImpl.java +++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java @@ -53,6 +53,7 @@ public final class GeofenceHardwareImpl { private IFusedGeofenceHardware mFusedService; private IGpsGeofenceHardware mGpsService; + private int mCapabilities; private int[] mSupportedMonitorTypes = new int[GeofenceHardware.NUM_MONITORS]; @@ -89,6 +90,9 @@ public final class GeofenceHardwareImpl { private static final int RESOLUTION_LEVEL_COARSE = 2; private static final int RESOLUTION_LEVEL_FINE = 3; + // Capability constant corresponding to fused_location.h entry when geofencing supports GNNS. + private static final int CAPABILITY_GNSS = 1; + public synchronized static GeofenceHardwareImpl getInstance(Context context) { if (sInstance == null) { sInstance = new GeofenceHardwareImpl(context); @@ -141,7 +145,9 @@ public final class GeofenceHardwareImpl { private void updateFusedHardwareAvailability() { boolean fusedSupported; try { - fusedSupported = (mFusedService != null ? mFusedService.isSupported() : false); + fusedSupported = (mFusedService != null + ? mFusedService.isSupported() && (mCapabilities & CAPABILITY_GNSS) != 0 + : false); } catch (RemoteException e) { Log.e(TAG, "RemoteException calling LocationManagerService"); fusedSupported = false; @@ -166,6 +172,11 @@ public final class GeofenceHardwareImpl { } } + public void onCapabilities(int capabilities) { + mCapabilities = capabilities; + updateFusedHardwareAvailability(); + } + public void setFusedGeofenceHardware(IFusedGeofenceHardware service) { if(mFusedService == null) { mFusedService = service; @@ -212,6 +223,20 @@ public final class GeofenceHardwareImpl { } } + public int getCapabilitiesForMonitoringType(int monitoringType) { + switch (mSupportedMonitorTypes[monitoringType]) { + case GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE: + switch (monitoringType) { + case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE: + return CAPABILITY_GNSS; + case GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE: + return mCapabilities; + } + break; + } + return 0; + } + public boolean addCircularFence( int monitoringType, GeofenceHardwareRequestParcelable request, diff --git a/core/java/android/hardware/location/GeofenceHardwareService.java b/core/java/android/hardware/location/GeofenceHardwareService.java index 4816c5f..c0bcb27 100644 --- a/core/java/android/hardware/location/GeofenceHardwareService.java +++ b/core/java/android/hardware/location/GeofenceHardwareService.java @@ -65,14 +65,17 @@ public class GeofenceHardwareService extends Service { } private IBinder mBinder = new IGeofenceHardware.Stub() { + @Override public void setGpsGeofenceHardware(IGpsGeofenceHardware service) { mGeofenceHardwareImpl.setGpsHardwareGeofence(service); } + @Override public void setFusedGeofenceHardware(IFusedGeofenceHardware service) { mGeofenceHardwareImpl.setFusedGeofenceHardware(service); } + @Override public int[] getMonitoringTypes() { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); @@ -80,12 +83,15 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.getMonitoringTypes(); } + @Override public int getStatusOfMonitoringType(int monitoringType) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); return mGeofenceHardwareImpl.getStatusOfMonitoringType(monitoringType); } + + @Override public boolean addCircularFence( int monitoringType, GeofenceHardwareRequestParcelable request, @@ -96,6 +102,7 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.addCircularFence(monitoringType, request, callback); } + @Override public boolean removeGeofence(int id, int monitoringType) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); @@ -104,6 +111,7 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.removeGeofence(id, monitoringType); } + @Override public boolean pauseGeofence(int id, int monitoringType) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); @@ -112,6 +120,7 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.pauseGeofence(id, monitoringType); } + @Override public boolean resumeGeofence(int id, int monitoringType, int monitorTransitions) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); @@ -120,6 +129,7 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.resumeGeofence(id, monitoringType, monitorTransitions); } + @Override public boolean registerForMonitorStateChangeCallback(int monitoringType, IGeofenceHardwareMonitorCallback callback) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, @@ -130,6 +140,7 @@ public class GeofenceHardwareService extends Service { callback); } + @Override public boolean unregisterForMonitorStateChangeCallback(int monitoringType, IGeofenceHardwareMonitorCallback callback) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, diff --git a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl index a11d8ab..2107ae8 100644 --- a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl +++ b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl @@ -30,12 +30,18 @@ interface IFusedLocationHardwareSink { * * @param locations The batch of location information available. */ - void onLocationAvailable(in Location[] locations); + void onLocationAvailable(in Location[] locations) = 0; /** * Event generated from FLP HAL to provide diagnostic data to the platform. * * @param data The diagnostic data provided by FLP HAL. */ - void onDiagnosticDataAvailable(in String data); + void onDiagnosticDataAvailable(in String data) = 1; + + /** + * Event generated from FLP HAL to provide a mask of supported + * capabilities. Should be called immediatly after init. + */ + void onCapabilities(int capabilities) = 2; }
\ No newline at end of file diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardware.java b/location/lib/java/com/android/location/provider/FusedLocationHardware.java index bc5a8a1..44cb199 100644 --- a/location/lib/java/com/android/location/provider/FusedLocationHardware.java +++ b/location/lib/java/com/android/location/provider/FusedLocationHardware.java @@ -34,7 +34,7 @@ import java.util.Map; * Class that exposes IFusedLocationHardware functionality to unbundled services. */ public final class FusedLocationHardware { - private final String TAG = "FusedLocationHardware"; + private static final String TAG = "FusedLocationHardware"; private IFusedLocationHardware mLocationHardware; @@ -52,6 +52,11 @@ public final class FusedLocationHardware { public void onDiagnosticDataAvailable(String data) { dispatchDiagnosticData(data); } + + @Override + public void onCapabilities(int capabilities) { + dispatchCapabilities(capabilities); + } }; /** @@ -204,6 +209,7 @@ public final class FusedLocationHardware { private class DispatcherHandler extends Handler { public static final int DISPATCH_LOCATION = 1; public static final int DISPATCH_DIAGNOSTIC_DATA = 2; + public static final int DISPATCH_CAPABILITIES = 3; public DispatcherHandler(Looper looper) { super(looper, null /*callback*/ , true /*async*/); @@ -218,6 +224,10 @@ public final class FusedLocationHardware { break; case DISPATCH_DIAGNOSTIC_DATA: command.dispatchDiagnosticData(); + break; + case DISPATCH_CAPABILITIES: + command.dispatchCapabilities(); + break; default: Log.e(TAG, "Invalid dispatch message"); break; @@ -229,14 +239,17 @@ public final class FusedLocationHardware { private final FusedLocationHardwareSink mSink; private final Location[] mLocations; private final String mData; + private final int mCapabilities; public MessageCommand( FusedLocationHardwareSink sink, Location[] locations, - String data) { + String data, + int capabilities) { mSink = sink; mLocations = locations; mData = data; + mCapabilities = capabilities; } public void dispatchLocation() { @@ -246,6 +259,10 @@ public final class FusedLocationHardware { public void dispatchDiagnosticData() { mSink.onDiagnosticDataAvailable(mData); } + + public void dispatchCapabilities() { + mSink.onCapabilities(mCapabilities); + } } private void dispatchLocations(Location[] locations) { @@ -258,7 +275,7 @@ public final class FusedLocationHardware { Message message = Message.obtain( entry.getValue(), DispatcherHandler.DISPATCH_LOCATION, - new MessageCommand(entry.getKey(), locations, null /*data*/)); + new MessageCommand(entry.getKey(), locations, null /*data*/, 0)); message.sendToTarget(); } } @@ -273,7 +290,22 @@ public final class FusedLocationHardware { Message message = Message.obtain( entry.getValue(), DispatcherHandler.DISPATCH_DIAGNOSTIC_DATA, - new MessageCommand(entry.getKey(), null /*locations*/, data)); + new MessageCommand(entry.getKey(), null /*locations*/, data, 0)); + message.sendToTarget(); + } + } + + private void dispatchCapabilities(int capabilities) { + HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks; + synchronized(mSinkList) { + sinks = mSinkList; + } + + for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) { + Message message = Message.obtain( + entry.getValue(), + DispatcherHandler.DISPATCH_CAPABILITIES, + new MessageCommand(entry.getKey(), null /*locations*/, null, capabilities)); message.sendToTarget(); } } diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java index 2c39fa8..aaef773 100644 --- a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java +++ b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java @@ -20,11 +20,34 @@ import android.location.Location; /** * Base class for sinks to interact with FusedLocationHardware. + * + * <p>Default implementations allow new methods to be added without crashing + * clients compiled against an old library version. */ -public abstract class FusedLocationHardwareSink { - /* - * Methods to provide a facade for IFusedLocationHardware +public class FusedLocationHardwareSink { + /** + * Called when one or more locations are available from the FLP + * HAL. + */ + public void onLocationAvailable(Location[] locations) { + // default do nothing + } + + /** + * Called when diagnostic data is available from the FLP HAL. + */ + public void onDiagnosticDataAvailable(String data) { + // default do nothing + } + + /** + * Called when capabilities are available from the FLP HAL. + * Should be called once right after initialization. + * + * @param capabilities A bitmask of capabilities defined in + * fused_location.h. */ - public abstract void onLocationAvailable(Location[] locations); - public abstract void onDiagnosticDataAvailable(String data); + public void onCapabilities(int capabilities) { + // default do nothing + } }
\ No newline at end of file diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java index 530ad4b..94a1cd8 100644 --- a/services/core/java/com/android/server/location/FlpHardwareProvider.java +++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java @@ -44,6 +44,9 @@ import android.util.Log; public class FlpHardwareProvider { private GeofenceHardwareImpl mGeofenceHardwareSink = null; private IFusedLocationHardwareSink mLocationSink = null; + // Capabilities provided by FlpCallbacks + private boolean mHaveBatchingCapabilities; + private int mBatchingCapabilities; private static FlpHardwareProvider sSingletonInstance = null; @@ -124,6 +127,33 @@ public class FlpHardwareProvider { } } + private void onBatchingCapabilities(int capabilities) { + synchronized (mLocationSinkLock) { + mHaveBatchingCapabilities = true; + mBatchingCapabilities = capabilities; + } + + maybeSendCapabilities(); + } + + private void maybeSendCapabilities() { + IFusedLocationHardwareSink sink; + boolean haveBatchingCapabilities; + int batchingCapabilities; + synchronized (mLocationSinkLock) { + sink = mLocationSink; + haveBatchingCapabilities = mHaveBatchingCapabilities; + batchingCapabilities = mBatchingCapabilities; + } + try { + if (sink != null && haveBatchingCapabilities) { + sink.onCapabilities(batchingCapabilities); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException calling onLocationAvailable"); + } + } + // FlpDiagnosticCallbacks members private void onDataReport(String data) { IFusedLocationHardwareSink sink; @@ -209,6 +239,10 @@ public class FlpHardwareProvider { translateToGeofenceHardwareStatus(result)); } + private void onGeofencingCapabilities(int capabilities) { + getGeofenceHardwareSink().onCapabilities(capabilities); + } + /** * Private native methods accessing FLP HAL. */ @@ -277,6 +311,7 @@ public class FlpHardwareProvider { mLocationSink = eventSink; } + maybeSendCapabilities(); } @Override diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp index d5508bc..5b5634b 100644 --- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp +++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp @@ -33,12 +33,14 @@ static hw_device_t* sHardwareDevice = NULL; static jmethodID sOnLocationReport = NULL; static jmethodID sOnDataReport = NULL; +static jmethodID sOnBatchingCapabilities = NULL; static jmethodID sOnGeofenceTransition = NULL; static jmethodID sOnGeofenceMonitorStatus = NULL; static jmethodID sOnGeofenceAdd = NULL; static jmethodID sOnGeofenceRemove = NULL; static jmethodID sOnGeofencePause = NULL; static jmethodID sOnGeofenceResume = NULL; +static jmethodID sOnGeofencingCapabilities = NULL; static const FlpLocationInterface* sFlpInterface = NULL; static const FlpDiagnosticInterface* sFlpDiagnosticInterface = NULL; @@ -85,6 +87,19 @@ static bool IsValidCallbackThread() { return true; } +static void BatchingCapabilitiesCallback(int32_t capabilities) { + if(!IsValidCallbackThread()) { + return; + } + + sCallbackEnv->CallVoidMethod( + sCallbacksObj, + sOnBatchingCapabilities, + capabilities + ); + CheckExceptions(sCallbackEnv, __FUNCTION__); +} + static int SetThreadEvent(ThreadEvent event) { JavaVM* javaVm = AndroidRuntime::getJavaVM(); @@ -156,6 +171,14 @@ static void ClassInit(JNIEnv* env, jclass clazz) { "onDataReport", "(Ljava/lang/String;)V" ); + sOnBatchingCapabilities = env->GetMethodID( + clazz, + "onBatchingCapabilities", + "(I)V"); + sOnGeofencingCapabilities = env->GetMethodID( + clazz, + "onGeofencingCapabilities", + "(I)V"); sOnGeofenceTransition = env->GetMethodID( clazz, "onGeofenceTransition", @@ -534,7 +557,8 @@ FlpCallbacks sFlpCallbacks = { LocationCallback, AcquireWakelock, ReleaseWakelock, - SetThreadEvent + SetThreadEvent, + BatchingCapabilitiesCallback }; static void ReportData(char* data, int length) { @@ -670,6 +694,19 @@ static void GeofenceResumeCallback(int32_t geofenceId, int32_t result) { CheckExceptions(sCallbackEnv, __FUNCTION__); } +static void GeofencingCapabilitiesCallback(int32_t capabilities) { + if(!IsValidCallbackThread()) { + return; + } + + sCallbackEnv->CallVoidMethod( + sCallbacksObj, + sOnGeofencingCapabilities, + capabilities + ); + CheckExceptions(sCallbackEnv, __FUNCTION__); +} + FlpGeofenceCallbacks sFlpGeofenceCallbacks = { sizeof(FlpGeofenceCallbacks), GeofenceTransitionCallback, @@ -678,7 +715,8 @@ FlpGeofenceCallbacks sFlpGeofenceCallbacks = { GeofenceRemoveCallback, GeofencePauseCallback, GeofenceResumeCallback, - SetThreadEvent + SetThreadEvent, + GeofencingCapabilitiesCallback }; /* |