GPS Hardware geofencing.
Add support for doing geofencing in hardware. Change-Id: I6d5015190e8d84e1f4beb1010ed977a71c1622d0
This commit is contained in:
@@ -124,6 +124,8 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/hardware/display/IDisplayManagerCallback.aidl \
|
||||
core/java/android/hardware/input/IInputManager.aidl \
|
||||
core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
|
||||
core/java/android/hardware/location/IGeofenceHardware.aidl \
|
||||
core/java/android/hardware/location/IGeofenceHardwareCallback.aidl \
|
||||
core/java/android/hardware/usb/IUsbManager.aidl \
|
||||
core/java/android/net/IConnectivityManager.aidl \
|
||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||
@@ -207,10 +209,12 @@ LOCAL_SRC_FILES += \
|
||||
location/java/android/location/ICountryDetector.aidl \
|
||||
location/java/android/location/ICountryListener.aidl \
|
||||
location/java/android/location/IGeocodeProvider.aidl \
|
||||
location/java/android/location/IGeofenceProvider.aidl \
|
||||
location/java/android/location/IGpsStatusListener.aidl \
|
||||
location/java/android/location/IGpsStatusProvider.aidl \
|
||||
location/java/android/location/ILocationListener.aidl \
|
||||
location/java/android/location/ILocationManager.aidl \
|
||||
location/java/android/location/IGpsGeofenceHardware.aidl \
|
||||
location/java/android/location/INetInitiatedListener.aidl \
|
||||
location/java/com/android/internal/location/ILocationProvider.aidl \
|
||||
media/java/android/media/IAudioService.aidl \
|
||||
|
||||
@@ -69,6 +69,7 @@ package android {
|
||||
field public static final java.lang.String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
|
||||
field public static final java.lang.String INTERNET = "android.permission.INTERNET";
|
||||
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
|
||||
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
|
||||
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
|
||||
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
|
||||
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
|
||||
@@ -10443,6 +10444,43 @@ package android.hardware.input {
|
||||
|
||||
}
|
||||
|
||||
package android.hardware.location {
|
||||
|
||||
public final class GeofenceHardware {
|
||||
method public boolean addCircularFence(int, double, double, double, int, int, int, int, int, android.hardware.location.GeofenceHardwareCallback);
|
||||
method public int[] getMonitoringTypesAndStatus();
|
||||
method public boolean pauseGeofence(int, int);
|
||||
method public boolean registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareCallback);
|
||||
method public boolean removeGeofence(int, int);
|
||||
method public boolean resumeGeofence(int, int, int);
|
||||
method public boolean unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareCallback);
|
||||
field public static final int GEOFENCE_ENTERED = 1; // 0x1
|
||||
field public static final int GEOFENCE_ERROR_ID_EXISTS = 2; // 0x2
|
||||
field public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3; // 0x3
|
||||
field public static final int GEOFENCE_ERROR_INVALID_TRANSITION = 4; // 0x4
|
||||
field public static final int GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 1; // 0x1
|
||||
field public static final int GEOFENCE_EXITED = 2; // 0x2
|
||||
field public static final int GEOFENCE_FAILURE = 5; // 0x5
|
||||
field public static final int GEOFENCE_SUCCESS = 0; // 0x0
|
||||
field public static final int GEOFENCE_UNCERTAIN = 4; // 0x4
|
||||
field public static final int MONITORING_TYPE_GPS_HARDWARE = 0; // 0x0
|
||||
field public static final int MONITOR_CURRENTLY_AVAILABLE = 0; // 0x0
|
||||
field public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1; // 0x1
|
||||
field public static final int MONITOR_UNSUPPORTED = 2; // 0x2
|
||||
}
|
||||
|
||||
public abstract class GeofenceHardwareCallback {
|
||||
ctor public GeofenceHardwareCallback();
|
||||
method public void onGeofenceAdd(int, int);
|
||||
method public void onGeofenceChange(int, int, android.location.Location, long, int);
|
||||
method public void onGeofencePause(int, int);
|
||||
method public void onGeofenceRemove(int, int);
|
||||
method public void onGeofenceResume(int, int);
|
||||
method public void onMonitoringSystemChange(int, boolean, android.location.Location);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.hardware.usb {
|
||||
|
||||
public class UsbAccessory implements android.os.Parcelable {
|
||||
|
||||
439
core/java/android/hardware/location/GeofenceHardware.java
Normal file
439
core/java/android/hardware/location/GeofenceHardware.java
Normal file
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.hardware.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* This class handles geofences managed by various hardware subsystems. It contains
|
||||
* the public APIs that is needed to accomplish the task.
|
||||
*
|
||||
* <p>The APIs should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* <p> There are 3 states associated with a Geofence: Inside, Outside, Unknown.
|
||||
* There are 3 transitions: {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED},
|
||||
* {@link #GEOFENCE_UNCERTAIN}. The APIs only expose the transitions.
|
||||
*
|
||||
* <p> Inside state: The hardware subsystem is reasonably confident that the user is inside
|
||||
* the geofence. Outside state: The hardware subsystem is reasonably confident that the user
|
||||
* is outside the geofence Unknown state: Unknown state can be interpreted as a state in which the
|
||||
* monitoring subsystem isn't confident enough that the user is either inside or
|
||||
* outside the Geofence. If the accuracy does not improve for a sufficient period of time,
|
||||
* the {@link #GEOFENCE_UNCERTAIN} transition would be triggered. If the accuracy improves later,
|
||||
* an appropriate transition would be triggered. The "reasonably confident" parameter
|
||||
* depends on the hardware system and the positioning algorithms used.
|
||||
* For instance, {@link #MONITORING_TYPE_GPS_HARDWARE} uses 95% as a confidence level.
|
||||
*/
|
||||
public final class GeofenceHardware {
|
||||
private IGeofenceHardware mService;
|
||||
|
||||
// Hardware systems that do geofence monitoring.
|
||||
static final int NUM_MONITORS = 1;
|
||||
|
||||
/**
|
||||
* Constant for geofence monitoring done by the GPS hardware.
|
||||
*/
|
||||
public static final int MONITORING_TYPE_GPS_HARDWARE = 0;
|
||||
|
||||
/**
|
||||
* Constant to indiciate that the monitoring system is currently
|
||||
* available for monitoring geofences.
|
||||
*/
|
||||
public static final int MONITOR_CURRENTLY_AVAILABLE = 0;
|
||||
|
||||
/**
|
||||
* Constant to indiciate that the monitoring system is currently
|
||||
* unavailable for monitoring geofences.
|
||||
*/
|
||||
public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1;
|
||||
|
||||
/**
|
||||
* Constant to indiciate that the monitoring system is unsupported
|
||||
* for hardware geofence monitoring.
|
||||
*/
|
||||
public static final int MONITOR_UNSUPPORTED = 2;
|
||||
|
||||
// The following constants need to match geofence flags in gps.h
|
||||
/**
|
||||
* The constant to indicate that the user has entered the geofence.
|
||||
*/
|
||||
public static final int GEOFENCE_ENTERED = 1<<0L;
|
||||
|
||||
/**
|
||||
* The constant to indicate that the user has exited the geofence.
|
||||
*/
|
||||
public static final int GEOFENCE_EXITED = 1<<1L;
|
||||
|
||||
/**
|
||||
* The constant to indicate that the user is uncertain with respect to a
|
||||
* geofence. nn
|
||||
*/
|
||||
public static final int GEOFENCE_UNCERTAIN = 1<<2L;
|
||||
|
||||
/**
|
||||
* The constant used to indicate success of the particular geofence call
|
||||
*/
|
||||
public static final int GEOFENCE_SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* The constant used to indicate that too many geofences have been registered.
|
||||
*/
|
||||
public static final int GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 1;
|
||||
|
||||
/**
|
||||
* The constant used to indicate that the geofence id already exists.
|
||||
*/
|
||||
public static final int GEOFENCE_ERROR_ID_EXISTS = 2;
|
||||
|
||||
/**
|
||||
* The constant used to indicate that the geofence id is unknown.
|
||||
*/
|
||||
public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3;
|
||||
|
||||
/**
|
||||
* The constant used to indicate that the transition requested for the geofence is invalid.
|
||||
*/
|
||||
public static final int GEOFENCE_ERROR_INVALID_TRANSITION = 4;
|
||||
|
||||
/**
|
||||
* The constant used to indicate that the geofence operation has failed.
|
||||
*/
|
||||
public static final int GEOFENCE_FAILURE = 5;
|
||||
|
||||
static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
|
||||
static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
|
||||
|
||||
private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>
|
||||
mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>();
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public GeofenceHardware(IGeofenceHardware service) {
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the hardware geofence monitoring systems and their status.
|
||||
* Status can be one of {@link #MONITOR_CURRENTLY_AVAILABLE},
|
||||
* {@link #MONITOR_CURRENTLY_UNAVAILABLE} or {@link #MONITOR_UNSUPPORTED}
|
||||
*
|
||||
* <p> Some supported hardware monitoring systems might not be available
|
||||
* for monitoring geofences in certain scenarios. For example, when a user
|
||||
* enters a building, the GPS hardware subsystem might not be able monitor
|
||||
* geofences and will change from {@link #MONITOR_CURRENTLY_AVAILABLE} to
|
||||
* {@link #MONITOR_CURRENTLY_UNAVAILABLE}.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* @return An array indexed by the various monitoring types and their status.
|
||||
* An array of length 0 is returned in case of errors.
|
||||
*/
|
||||
public int[] getMonitoringTypesAndStatus() {
|
||||
try {
|
||||
return mService.getMonitoringTypesAndStatus();
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a circular geofence which is monitored by subsystems in the hardware.
|
||||
*
|
||||
* <p> When the device detects that is has entered, exited or is uncertain
|
||||
* about the area specified by the geofence, the given callback will be called.
|
||||
*
|
||||
* <p> The {@link GeofenceHardwareCallback#onGeofenceChange} callback will be called,
|
||||
* with the following parameters
|
||||
* <ul>
|
||||
* <li> The geofence Id
|
||||
* <li> The location object indicating the last known location.
|
||||
* <li> The transition associated with the geofence. One of
|
||||
* {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
|
||||
* <li> The timestamp when the geofence transition occured.
|
||||
* <li> The monitoring type ({@link #MONITORING_TYPE_GPS_HARDWARE} is one such example)
|
||||
* that was used.
|
||||
* </ul>
|
||||
*
|
||||
* <p> The geofence will be monitored by the subsystem specified by monitoring_type parameter.
|
||||
* The application does not need to hold a wakelock when the monitoring
|
||||
* is being done by the underlying hardware subsystem. If the same geofence Id is being
|
||||
* monitored by two different monitoring systems, the same id can be used for both calls, as
|
||||
* long as the same callback object is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
|
||||
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* <p>This API should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* @param latitude Latitude of the area to be monitored.
|
||||
* @param longitude Longitude of the area to be monitored.
|
||||
* @param radius Radius (in meters) of the area to be monitored.
|
||||
* @param lastTransition The current state of the geofence. Can be one of
|
||||
* {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED},
|
||||
* {@link #GEOFENCE_UNCERTAIN}.
|
||||
* @param monitorTransitions Bitwise OR of {@link #GEOFENCE_ENTERED},
|
||||
* {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
|
||||
* @param notificationResponsivenes Defines the best-effort description
|
||||
* of how soon should the callback be called when the transition
|
||||
* associated with the Geofence is triggered. For instance, if
|
||||
* set to 1000 millseconds with {@link #GEOFENCE_ENTERED},
|
||||
* the callback will be called 1000 milliseconds within entering
|
||||
* the geofence. This parameter is defined in milliseconds.
|
||||
* @param unknownTimer The time limit after which the
|
||||
* {@link #GEOFENCE_UNCERTAIN} transition
|
||||
* should be triggered. This paramter is defined in milliseconds.
|
||||
* @param monitoringType The type of the hardware subsystem that should be used
|
||||
* to monitor the geofence.
|
||||
* @param callback {@link GeofenceHardwareCallback} that will be use to notify the
|
||||
* transition.
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean addCircularFence(int geofenceId, double latitude, double longitude,
|
||||
double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes,
|
||||
int unknownTimer, int monitoringType, GeofenceHardwareCallback callback) {
|
||||
try {
|
||||
return mService.addCircularFence(geofenceId, latitude, longitude, radius,
|
||||
lastTransition, monitorTransitions, notificationResponsivenes, unknownTimer,
|
||||
monitoringType, getCallbackWrapper(callback));
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a geofence added by {@link #addCircularFence} call.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
|
||||
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* <p>This API should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* @param geofenceId The id of the geofence.
|
||||
* @param monitoringType The type of the hardware subsystem that should be used
|
||||
* to monitor the geofence.
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean removeGeofence(int geofenceId, int monitoringType) {
|
||||
try {
|
||||
return mService.removeGeofence(geofenceId, monitoringType);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the monitoring of a geofence added by {@link #addCircularFence} call.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
|
||||
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* <p>This API should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* @param geofenceId The id of the geofence.
|
||||
* @param monitoringType The type of the hardware subsystem that should be used
|
||||
* to monitor the geofence.
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean pauseGeofence(int geofenceId, int monitoringType) {
|
||||
try {
|
||||
return mService.pauseGeofence(geofenceId, monitoringType);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the monitoring of a geofence added by {@link #pauseGeofence} call.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
|
||||
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* <p>This API should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* @param geofenceId The id of the geofence.
|
||||
* @param monitorTransition Bitwise OR of {@link #GEOFENCE_ENTERED},
|
||||
* {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
|
||||
* @param monitoringType The type of the hardware subsystem that should be used
|
||||
* to monitor the geofence.
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean resumeGeofence(int geofenceId, int monitorTransition, int monitoringType) {
|
||||
try {
|
||||
return mService.resumeGeofence(geofenceId, monitorTransition, monitoringType);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the callback to be notified when the state of a hardware geofence
|
||||
* monitoring system changes. For instance, it can change from
|
||||
* {@link #MONITOR_CURRENTLY_AVAILABLE} to {@link #MONITOR_CURRENTLY_UNAVAILABLE}
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
|
||||
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* <p>This API should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* <p> The same callback object can be used to be informed of geofence transitions
|
||||
* and state changes of the underlying hardware subsystem.
|
||||
*
|
||||
* @param monitoringType Type of the monitor
|
||||
* @param callback Callback that will be called.
|
||||
* @return true on success
|
||||
*/
|
||||
public boolean registerForMonitorStateChangeCallback(int monitoringType,
|
||||
GeofenceHardwareCallback callback) {
|
||||
try {
|
||||
return mService.registerForMonitorStateChangeCallback(monitoringType,
|
||||
getCallbackWrapper(callback));
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the callback that was used with {@link #registerForMonitorStateChangeCallback}
|
||||
* to notify when the state of the hardware geofence monitoring system changes.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
|
||||
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
|
||||
*
|
||||
* <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
|
||||
* geofencing in hardware.
|
||||
*
|
||||
* <p>This API should not be called directly by the app developers. A higher level api
|
||||
* which abstracts the hardware should be used instead. All the checks are done by the higher
|
||||
* level public API. Any needed locking should be handled by the higher level API.
|
||||
*
|
||||
* @param monitoringType Type of the monitor
|
||||
* @param callback Callback that will be called.
|
||||
* @return true on success
|
||||
*/
|
||||
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
|
||||
GeofenceHardwareCallback callback) {
|
||||
boolean result = false;
|
||||
try {
|
||||
result = mService.unregisterForMonitorStateChangeCallback(monitoringType,
|
||||
getCallbackWrapper(callback));
|
||||
if (result) removeCallback(callback);
|
||||
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private void removeCallback(GeofenceHardwareCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
mCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
private GeofenceHardwareCallbackWrapper getCallbackWrapper(GeofenceHardwareCallback callback) {
|
||||
synchronized (mCallbacks) {
|
||||
GeofenceHardwareCallbackWrapper wrapper = mCallbacks.get(callback);
|
||||
if (wrapper == null) {
|
||||
wrapper = new GeofenceHardwareCallbackWrapper(callback);
|
||||
mCallbacks.put(callback, wrapper);
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub {
|
||||
private WeakReference<GeofenceHardwareCallback> mCallback;
|
||||
|
||||
GeofenceHardwareCallbackWrapper(GeofenceHardwareCallback c) {
|
||||
mCallback = new WeakReference<GeofenceHardwareCallback>(c);
|
||||
}
|
||||
|
||||
public void onMonitoringSystemChange(int monitoringType, boolean available,
|
||||
Location location) {
|
||||
GeofenceHardwareCallback c = mCallback.get();
|
||||
if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
|
||||
}
|
||||
|
||||
public void onGeofenceChange(int geofenceId, int transition, Location location,
|
||||
long timestamp, int monitoringType) {
|
||||
GeofenceHardwareCallback c = mCallback.get();
|
||||
if (c != null) {
|
||||
c.onGeofenceChange(geofenceId, transition, location, timestamp,
|
||||
monitoringType);
|
||||
}
|
||||
}
|
||||
|
||||
public void onGeofenceAdd(int geofenceId, int status) {
|
||||
GeofenceHardwareCallback c = mCallback.get();
|
||||
if (c != null) c.onGeofenceAdd(geofenceId, status);
|
||||
}
|
||||
|
||||
public void onGeofenceRemove(int geofenceId, int status) {
|
||||
GeofenceHardwareCallback c = mCallback.get();
|
||||
if (c != null) {
|
||||
c.onGeofenceRemove(geofenceId, status);
|
||||
removeCallback(c);
|
||||
}
|
||||
}
|
||||
|
||||
public void onGeofencePause(int geofenceId, int status) {
|
||||
GeofenceHardwareCallback c = mCallback.get();
|
||||
if (c != null) c.onGeofencePause(geofenceId, status);
|
||||
}
|
||||
|
||||
public void onGeofenceResume(int geofenceId, int status) {
|
||||
GeofenceHardwareCallback c = mCallback.get();
|
||||
if (c != null) c.onGeofenceResume(geofenceId, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.hardware.location;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
/**
|
||||
* The callback class associated with the APIs in {@link GeofenceHardware}
|
||||
*/
|
||||
public abstract class GeofenceHardwareCallback {
|
||||
|
||||
/**
|
||||
* The callback called when the state of a monitoring system changes.
|
||||
* {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a
|
||||
* monitoring system.
|
||||
*
|
||||
* @param monitoringType The type of the monitoring system.
|
||||
* @param available Indicates whether the system is currently available or not.
|
||||
* @param location The last known location according to the monitoring system.
|
||||
*/
|
||||
public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback called when there is a transition to report for the specific
|
||||
* geofence.
|
||||
*
|
||||
* @param geofenceId The geofence ID of the geofence
|
||||
* @param transition One of {@link GeofenceHardware#GEOFENCE_ENTERED},
|
||||
* {@link GeofenceHardware#GEOFENCE_EXITED}, {@link GeofenceHardware#GEOFENCE_UNCERTAIN}
|
||||
* @param location The last known location according to the monitoring system.
|
||||
* @param timestamp The timestamp (elapsed real time in milliseconds) when the transition was
|
||||
* detected
|
||||
* @param monitoringType Type of the monitoring system.
|
||||
*/
|
||||
public void onGeofenceChange(int geofenceId, int transition, Location location,
|
||||
long timestamp, int monitoringType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback called to notify the success or failure of the add call.
|
||||
*
|
||||
* @param geofenceId The ID of the geofence.
|
||||
* @param status One of {@link GeofenceHardware#GEOFENCE_SUCCESS},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_ID_EXISTS},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_INVALID_TRANSITION},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_TOO_MANY_GEOFENCES},
|
||||
* {@link GeofenceHardware#GEOFENCE_FAILURE}
|
||||
*/
|
||||
public void onGeofenceAdd(int geofenceId, int status) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback called to notify the success or failure of the remove call.
|
||||
*
|
||||
* @param geofenceId The ID of the geofence.
|
||||
* @param status One of {@link GeofenceHardware#GEOFENCE_SUCCESS},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_ID_UNKNOWN},
|
||||
* {@link GeofenceHardware#GEOFENCE_FAILURE}
|
||||
*/
|
||||
public void onGeofenceRemove(int geofenceId, int status) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback called to notify the success or failure of the pause call.
|
||||
*
|
||||
* @param geofenceId The ID of the geofence.
|
||||
* @param status One of {@link GeofenceHardware#GEOFENCE_SUCCESS},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_ID_UNKNOWN},
|
||||
* {@link GeofenceHardware#GEOFENCE_FAILURE}
|
||||
*/
|
||||
public void onGeofencePause(int geofenceId, int status) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback called to notify the success or failure of the resume call.
|
||||
*
|
||||
* @param geofenceId The ID of the geofence.
|
||||
* @param status One of {@link GeofenceHardware#GEOFENCE_SUCCESS},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_ID_UNKNOWN},
|
||||
* {@link GeofenceHardware#GEOFENCE_ERROR_INVALID_TRANSITION},
|
||||
* {@link GeofenceHardware#GEOFENCE_FAILURE}
|
||||
*/
|
||||
public void onGeofenceResume(int geofenceId, int status) {
|
||||
}
|
||||
}
|
||||
599
core/java/android/hardware/location/GeofenceHardwareImpl.java
Normal file
599
core/java/android/hardware/location/GeofenceHardwareImpl.java
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.hardware.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.IGpsGeofenceHardware;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class manages the geofences which are handled by hardware.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class GeofenceHardwareImpl {
|
||||
private static final String TAG = "GeofenceHardwareImpl";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final Context mContext;
|
||||
private static GeofenceHardwareImpl sInstance;
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private SparseArray<IGeofenceHardwareCallback> mGeofences =
|
||||
new SparseArray<IGeofenceHardwareCallback>();
|
||||
private ArrayList<IGeofenceHardwareCallback>[] mCallbacks =
|
||||
new ArrayList[GeofenceHardware.NUM_MONITORS];
|
||||
|
||||
private IGpsGeofenceHardware mGpsService;
|
||||
|
||||
private int[] mSupportedMonitorTypes = new int[GeofenceHardware.NUM_MONITORS];
|
||||
|
||||
// mGeofenceHandler message types
|
||||
private static final int GEOFENCE_TRANSITION_CALLBACK = 1;
|
||||
private static final int ADD_GEOFENCE_CALLBACK = 2;
|
||||
private static final int REMOVE_GEOFENCE_CALLBACK = 3;
|
||||
private static final int PAUSE_GEOFENCE_CALLBACK = 4;
|
||||
private static final int RESUME_GEOFENCE_CALLBACK = 5;
|
||||
private static final int ADD_GEOFENCE = 6;
|
||||
private static final int REMOVE_GEOFENCE = 7;
|
||||
|
||||
// mCallbacksHandler message types
|
||||
private static final int GPS_GEOFENCE_STATUS = 1;
|
||||
private static final int CALLBACK_ADD = 2;
|
||||
private static final int CALLBACK_REMOVE = 3;
|
||||
|
||||
// The following constants need to match GpsLocationFlags enum in gps.h
|
||||
private static final int LOCATION_INVALID = 0;
|
||||
private static final int LOCATION_HAS_LAT_LONG = 1;
|
||||
private static final int LOCATION_HAS_ALTITUDE = 2;
|
||||
private static final int LOCATION_HAS_SPEED = 4;
|
||||
private static final int LOCATION_HAS_BEARING = 8;
|
||||
private static final int LOCATION_HAS_ACCURACY = 16;
|
||||
|
||||
// Resolution level constants used for permission checks.
|
||||
// These constants must be in increasing order of finer resolution.
|
||||
private static final int RESOLUTION_LEVEL_NONE = 1;
|
||||
private static final int RESOLUTION_LEVEL_COARSE = 2;
|
||||
private static final int RESOLUTION_LEVEL_FINE = 3;
|
||||
|
||||
// GPS Geofence errors. Should match gps.h constants.
|
||||
private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
|
||||
private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
|
||||
private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
|
||||
private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
|
||||
private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
|
||||
private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
|
||||
|
||||
|
||||
|
||||
public synchronized static GeofenceHardwareImpl getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new GeofenceHardwareImpl(context);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private GeofenceHardwareImpl(Context context) {
|
||||
mContext = context;
|
||||
// Init everything to unsupported.
|
||||
setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
|
||||
GeofenceHardware.MONITOR_UNSUPPORTED);
|
||||
|
||||
}
|
||||
|
||||
private void acquireWakeLock() {
|
||||
if (mWakeLock == null) {
|
||||
PowerManager powerManager =
|
||||
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||
}
|
||||
mWakeLock.acquire();
|
||||
}
|
||||
|
||||
private void releaseWakeLock() {
|
||||
if (mWakeLock.isHeld()) mWakeLock.release();
|
||||
}
|
||||
|
||||
private void updateGpsHardwareAvailability() {
|
||||
//Check which monitors are available.
|
||||
boolean gpsSupported;
|
||||
try {
|
||||
gpsSupported = mGpsService.isHardwareGeofenceSupported();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Remote Exception calling LocationManagerService");
|
||||
gpsSupported = false;
|
||||
}
|
||||
|
||||
if (gpsSupported) {
|
||||
// Its assumed currently available at startup.
|
||||
// native layer will update later.
|
||||
setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
|
||||
GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setGpsHardwareGeofence(IGpsGeofenceHardware service) {
|
||||
if (mGpsService == null) {
|
||||
mGpsService = service;
|
||||
updateGpsHardwareAvailability();
|
||||
} else if (service == null) {
|
||||
mGpsService = null;
|
||||
Log.w(TAG, "GPS Geofence Hardware service seems to have crashed");
|
||||
} else {
|
||||
Log.e(TAG, "Error: GpsService being set again.");
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getMonitoringTypesAndStatus() {
|
||||
synchronized (mSupportedMonitorTypes) {
|
||||
return mSupportedMonitorTypes;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addCircularFence(int geofenceId, double latitude, double longitude,
|
||||
double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes,
|
||||
int unknownTimer, int monitoringType, IGeofenceHardwareCallback callback) {
|
||||
// This API is not thread safe. Operations on the same geofence need to be serialized
|
||||
// by upper layers
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addCircularFence: GeofenceId: " + geofenceId + "Latitude: " + latitude +
|
||||
"Longitude: " + longitude + "Radius: " + radius + "LastTransition: "
|
||||
+ lastTransition + "MonitorTransition: " + monitorTransitions +
|
||||
"NotificationResponsiveness: " + notificationResponsivenes +
|
||||
"UnKnown Timer: " + unknownTimer + "MonitoringType: " + monitoringType);
|
||||
|
||||
}
|
||||
boolean result;
|
||||
Message m = mGeofenceHandler.obtainMessage(ADD_GEOFENCE, callback);
|
||||
m.arg1 = geofenceId;
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
|
||||
switch (monitoringType) {
|
||||
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
|
||||
if (mGpsService == null) return false;
|
||||
try {
|
||||
result = mGpsService.addCircularHardwareGeofence(geofenceId, latitude,
|
||||
longitude, radius, lastTransition, monitorTransitions,
|
||||
notificationResponsivenes, unknownTimer);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "AddGeofence: Remote Exception calling LocationManagerService");
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
}
|
||||
if (!result) {
|
||||
m = mGeofenceHandler.obtainMessage(REMOVE_GEOFENCE);
|
||||
m.arg1 = geofenceId;
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
if (DEBUG) Log.d(TAG, "addCircularFence: Result is: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean removeGeofence(int geofenceId, int monitoringType) {
|
||||
// This API is not thread safe. Operations on the same geofence need to be serialized
|
||||
// by upper layers
|
||||
if (DEBUG) Log.d(TAG, "Remove Geofence: GeofenceId: " + geofenceId);
|
||||
boolean result = false;
|
||||
switch (monitoringType) {
|
||||
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
|
||||
if (mGpsService == null) return false;
|
||||
try {
|
||||
result = mGpsService.removeHardwareGeofence(geofenceId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoveGeofence: Remote Exception calling LocationManagerService");
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "removeGeofence: Result is: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean pauseGeofence(int geofenceId, int monitoringType) {
|
||||
// This API is not thread safe. Operations on the same geofence need to be serialized
|
||||
// by upper layers
|
||||
if (DEBUG) Log.d(TAG, "Pause Geofence: GeofenceId: " + geofenceId);
|
||||
boolean result;
|
||||
switch (monitoringType) {
|
||||
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
|
||||
if (mGpsService == null) return false;
|
||||
try {
|
||||
result = mGpsService.pauseHardwareGeofence(geofenceId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "PauseGeofence: Remote Exception calling LocationManagerService");
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "pauseGeofence: Result is: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public boolean resumeGeofence(int geofenceId, int monitorTransition, int monitoringType) {
|
||||
// This API is not thread safe. Operations on the same geofence need to be serialized
|
||||
// by upper layers
|
||||
if (DEBUG) Log.d(TAG, "Resume Geofence: GeofenceId: " + geofenceId);
|
||||
boolean result;
|
||||
switch (monitoringType) {
|
||||
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
|
||||
if (mGpsService == null) return false;
|
||||
try {
|
||||
result = mGpsService.resumeHardwareGeofence(geofenceId, monitorTransition);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "ResumeGeofence: Remote Exception calling LocationManagerService");
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "resumeGeofence: Result is: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean registerForMonitorStateChangeCallback(int monitoringType,
|
||||
IGeofenceHardwareCallback callback) {
|
||||
Message m = mCallbacksHandler.obtainMessage(CALLBACK_ADD, callback);
|
||||
m.arg1 = monitoringType;
|
||||
mCallbacksHandler.sendMessage(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
|
||||
IGeofenceHardwareCallback callback) {
|
||||
Message m = mCallbacksHandler.obtainMessage(CALLBACK_REMOVE, callback);
|
||||
m.arg1 = monitoringType;
|
||||
mCallbacksHandler.sendMessage(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
private Location getLocation(int flags, double latitude,
|
||||
double longitude, double altitude, float speed, float bearing, float accuracy,
|
||||
long timestamp) {
|
||||
if (DEBUG) Log.d(TAG, "GetLocation: " + flags + ":" + latitude);
|
||||
Location location = new Location(LocationManager.GPS_PROVIDER);
|
||||
if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
|
||||
location.setLatitude(latitude);
|
||||
location.setLongitude(longitude);
|
||||
location.setTime(timestamp);
|
||||
// It would be nice to push the elapsed real-time timestamp
|
||||
// further down the stack, but this is still useful
|
||||
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
|
||||
}
|
||||
if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
|
||||
location.setAltitude(altitude);
|
||||
} else {
|
||||
location.removeAltitude();
|
||||
}
|
||||
if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
|
||||
location.setSpeed(speed);
|
||||
} else {
|
||||
location.removeSpeed();
|
||||
}
|
||||
if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
|
||||
location.setBearing(bearing);
|
||||
} else {
|
||||
location.removeBearing();
|
||||
}
|
||||
if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
|
||||
location.setAccuracy(accuracy);
|
||||
} else {
|
||||
location.removeAccuracy();
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* called from GpsLocationProvider to report geofence transition
|
||||
*/
|
||||
public void reportGpsGeofenceTransition(int geofenceId, int flags, double latitude,
|
||||
double longitude, double altitude, float speed, float bearing, float accuracy,
|
||||
long timestamp, int transition, long transitionTimestamp) {
|
||||
if (DEBUG) Log.d(TAG, "GeofenceTransition: Flags: " + flags + " Lat: " + latitude +
|
||||
" Long: " + longitude + " Altitude: " + altitude + " Speed: " + speed + " Bearing: " +
|
||||
bearing + " Accuracy: " + accuracy + " Timestamp: " + timestamp + " Transition: " +
|
||||
transition + " TransitionTimestamp: " + transitionTimestamp);
|
||||
Location location = getLocation(flags, latitude, longitude, altitude, speed, bearing,
|
||||
accuracy, timestamp);
|
||||
GeofenceTransition t = new GeofenceTransition(geofenceId, transition, timestamp, location);
|
||||
acquireWakeLock();
|
||||
Message m = mGeofenceHandler.obtainMessage(GEOFENCE_TRANSITION_CALLBACK, t);
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from GpsLocationProvider to report GPS status change.
|
||||
*/
|
||||
public void reportGpsGeofenceStatus(int status, int flags, double latitude,
|
||||
double longitude, double altitude, float speed, float bearing, float accuracy,
|
||||
long timestamp) {
|
||||
Location location = getLocation(flags, latitude, longitude, altitude, speed, bearing,
|
||||
accuracy, timestamp);
|
||||
boolean available = false;
|
||||
if (status == GeofenceHardware.GPS_GEOFENCE_AVAILABLE) available = true;
|
||||
|
||||
int val = (available ? GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE :
|
||||
GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE);
|
||||
setMonitorAvailability(GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, val);
|
||||
|
||||
acquireWakeLock();
|
||||
Message m = mCallbacksHandler.obtainMessage(GPS_GEOFENCE_STATUS, location);
|
||||
m.arg1 = val;
|
||||
mCallbacksHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from GpsLocationProvider add geofence callback.
|
||||
*/
|
||||
public void reportGpsGeofenceAddStatus(int geofenceId, int status) {
|
||||
if (DEBUG) Log.d(TAG, "Add Callback: GPS : Id: " + geofenceId + " Status: " + status);
|
||||
acquireWakeLock();
|
||||
Message m = mGeofenceHandler.obtainMessage(ADD_GEOFENCE_CALLBACK);
|
||||
m.arg1 = geofenceId;
|
||||
m.arg2 = getGeofenceStatus(status);
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from GpsLocationProvider remove geofence callback.
|
||||
*/
|
||||
public void reportGpsGeofenceRemoveStatus(int geofenceId, int status) {
|
||||
if (DEBUG) Log.d(TAG, "Remove Callback: GPS : Id: " + geofenceId + " Status: " + status);
|
||||
acquireWakeLock();
|
||||
Message m = mGeofenceHandler.obtainMessage(REMOVE_GEOFENCE_CALLBACK);
|
||||
m.arg1 = geofenceId;
|
||||
m.arg2 = getGeofenceStatus(status);
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from GpsLocationProvider pause geofence callback.
|
||||
*/
|
||||
public void reportGpsGeofencePauseStatus(int geofenceId, int status) {
|
||||
if (DEBUG) Log.d(TAG, "Pause Callback: GPS : Id: " + geofenceId + " Status: " + status);
|
||||
acquireWakeLock();
|
||||
Message m = mGeofenceHandler.obtainMessage(PAUSE_GEOFENCE_CALLBACK);
|
||||
m.arg1 = geofenceId;
|
||||
m.arg2 = getGeofenceStatus(status);
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from GpsLocationProvider resume geofence callback.
|
||||
*/
|
||||
public void reportGpsGeofenceResumeStatus(int geofenceId, int status) {
|
||||
if (DEBUG) Log.d(TAG, "Resume Callback: GPS : Id: " + geofenceId + " Status: " + status);
|
||||
acquireWakeLock();
|
||||
Message m = mGeofenceHandler.obtainMessage(RESUME_GEOFENCE_CALLBACK);
|
||||
m.arg1 = geofenceId;
|
||||
m.arg2 = getGeofenceStatus(status);
|
||||
mGeofenceHandler.sendMessage(m);
|
||||
}
|
||||
|
||||
// All operations on mGeofences
|
||||
private Handler mGeofenceHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
int geofenceId;
|
||||
int status;
|
||||
IGeofenceHardwareCallback callback;
|
||||
switch (msg.what) {
|
||||
case ADD_GEOFENCE:
|
||||
geofenceId = msg.arg1;
|
||||
callback = (IGeofenceHardwareCallback) msg.obj;
|
||||
mGeofences.put(geofenceId, callback);
|
||||
break;
|
||||
case REMOVE_GEOFENCE:
|
||||
geofenceId = msg.arg1;
|
||||
mGeofences.remove(geofenceId);
|
||||
break;
|
||||
case ADD_GEOFENCE_CALLBACK:
|
||||
geofenceId = msg.arg1;
|
||||
callback = mGeofences.get(geofenceId);
|
||||
if (callback == null) return;
|
||||
|
||||
try {
|
||||
callback.onGeofenceAdd(geofenceId, msg.arg2);
|
||||
} catch (RemoteException e) {Log.i(TAG, "Remote Exception:" + e);}
|
||||
releaseWakeLock();
|
||||
break;
|
||||
case REMOVE_GEOFENCE_CALLBACK:
|
||||
geofenceId = msg.arg1;
|
||||
callback = mGeofences.get(geofenceId);
|
||||
if (callback == null) return;
|
||||
|
||||
try {
|
||||
callback.onGeofenceRemove(geofenceId, msg.arg2);
|
||||
} catch (RemoteException e) {}
|
||||
mGeofences.remove(geofenceId);
|
||||
releaseWakeLock();
|
||||
break;
|
||||
|
||||
case PAUSE_GEOFENCE_CALLBACK:
|
||||
geofenceId = msg.arg1;
|
||||
callback = mGeofences.get(geofenceId);
|
||||
if (callback == null) return;
|
||||
|
||||
try {
|
||||
callback.onGeofencePause(geofenceId, msg.arg2);
|
||||
} catch (RemoteException e) {}
|
||||
releaseWakeLock();
|
||||
break;
|
||||
|
||||
case RESUME_GEOFENCE_CALLBACK:
|
||||
geofenceId = msg.arg1;
|
||||
callback = mGeofences.get(geofenceId);
|
||||
if (callback == null) return;
|
||||
|
||||
try {
|
||||
callback.onGeofenceResume(geofenceId, msg.arg2);
|
||||
} catch (RemoteException e) {}
|
||||
releaseWakeLock();
|
||||
break;
|
||||
|
||||
case GEOFENCE_TRANSITION_CALLBACK:
|
||||
GeofenceTransition geofenceTransition = (GeofenceTransition)(msg.obj);
|
||||
callback = mGeofences.get(geofenceTransition.mGeofenceId);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "GeofenceTransistionCallback: GPS : GeofenceId: " +
|
||||
geofenceTransition.mGeofenceId +
|
||||
"Transition: " + geofenceTransition.mTransition +
|
||||
"Location: " + geofenceTransition.mLocation + ":" + mGeofences);
|
||||
|
||||
try {
|
||||
callback.onGeofenceChange(
|
||||
geofenceTransition.mGeofenceId, geofenceTransition.mTransition,
|
||||
geofenceTransition.mLocation, geofenceTransition.mTimestamp,
|
||||
GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE);
|
||||
} catch (RemoteException e) {}
|
||||
releaseWakeLock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// All operations on mCallbacks
|
||||
private Handler mCallbacksHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
int monitoringType;
|
||||
ArrayList<IGeofenceHardwareCallback> callbackList;
|
||||
IGeofenceHardwareCallback callback;
|
||||
|
||||
switch (msg.what) {
|
||||
case GPS_GEOFENCE_STATUS:
|
||||
Location location = (Location) msg.obj;
|
||||
int val = msg.arg1;
|
||||
boolean available;
|
||||
available = (val == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE ?
|
||||
true : false);
|
||||
callbackList = mCallbacks[GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE];
|
||||
if (callbackList == null) return;
|
||||
|
||||
if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available);
|
||||
|
||||
for (IGeofenceHardwareCallback c: callbackList) {
|
||||
try {
|
||||
c.onMonitoringSystemChange(
|
||||
GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, available,
|
||||
location);
|
||||
} catch (RemoteException e) {}
|
||||
}
|
||||
releaseWakeLock();
|
||||
break;
|
||||
case CALLBACK_ADD:
|
||||
monitoringType = msg.arg1;
|
||||
callback = (IGeofenceHardwareCallback) msg.obj;
|
||||
callbackList = mCallbacks[monitoringType];
|
||||
if (callbackList == null) {
|
||||
callbackList = new ArrayList<IGeofenceHardwareCallback>();
|
||||
mCallbacks[monitoringType] = callbackList;
|
||||
}
|
||||
if (!callbackList.contains(callback)) callbackList.add(callback);
|
||||
break;
|
||||
case CALLBACK_REMOVE:
|
||||
monitoringType = msg.arg1;
|
||||
callback = (IGeofenceHardwareCallback) msg.obj;
|
||||
callbackList = mCallbacks[monitoringType];
|
||||
if (callbackList != null) {
|
||||
callbackList.remove(callback);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private class GeofenceTransition {
|
||||
private int mGeofenceId, mTransition;
|
||||
private long mTimestamp;
|
||||
private Location mLocation;
|
||||
|
||||
GeofenceTransition(int geofenceId, int transition, long timestamp, Location location) {
|
||||
mGeofenceId = geofenceId;
|
||||
mTransition = transition;
|
||||
mTimestamp = timestamp;
|
||||
mLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
private void setMonitorAvailability(int monitor, int val) {
|
||||
synchronized (mSupportedMonitorTypes) {
|
||||
mSupportedMonitorTypes[monitor] = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int getMonitoringResolutionLevel(int monitoringType) {
|
||||
switch (monitoringType) {
|
||||
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
|
||||
return RESOLUTION_LEVEL_FINE;
|
||||
}
|
||||
return RESOLUTION_LEVEL_NONE;
|
||||
}
|
||||
|
||||
int getAllowedResolutionLevel(int pid, int uid) {
|
||||
if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
pid, uid) == PackageManager.PERMISSION_GRANTED) {
|
||||
return RESOLUTION_LEVEL_FINE;
|
||||
} else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||
pid, uid) == PackageManager.PERMISSION_GRANTED) {
|
||||
return RESOLUTION_LEVEL_COARSE;
|
||||
} else {
|
||||
return RESOLUTION_LEVEL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
private int getGeofenceStatus(int status) {
|
||||
switch (status) {
|
||||
case GPS_GEOFENCE_OPERATION_SUCCESS:
|
||||
return GeofenceHardware.GEOFENCE_SUCCESS;
|
||||
case GPS_GEOFENCE_ERROR_GENERIC:
|
||||
return GeofenceHardware.GEOFENCE_FAILURE;
|
||||
case GPS_GEOFENCE_ERROR_ID_EXISTS:
|
||||
return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
|
||||
case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
|
||||
return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
|
||||
case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
|
||||
return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
|
||||
case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
|
||||
return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
134
core/java/android/hardware/location/GeofenceHardwareService.java
Normal file
134
core/java/android/hardware/location/GeofenceHardwareService.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.hardware.location;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.IGpsGeofenceHardware;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Service that handles hardware geofencing.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class GeofenceHardwareService extends Service {
|
||||
private GeofenceHardwareImpl mGeofenceHardwareImpl;
|
||||
private Context mContext;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
mContext = this;
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnbind(Intent intent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mGeofenceHardwareImpl = null;
|
||||
}
|
||||
|
||||
|
||||
private void checkPermission(int pid, int uid, int monitoringType) {
|
||||
if (mGeofenceHardwareImpl.getAllowedResolutionLevel(pid, uid) <
|
||||
mGeofenceHardwareImpl.getMonitoringResolutionLevel(monitoringType)) {
|
||||
throw new SecurityException("Insufficient permissions to access hardware geofence for"
|
||||
+ " type: " + monitoringType);
|
||||
}
|
||||
}
|
||||
|
||||
private IBinder mBinder = new IGeofenceHardware.Stub() {
|
||||
public void setGpsGeofenceHardware(IGpsGeofenceHardware service) {
|
||||
mGeofenceHardwareImpl.setGpsHardwareGeofence(service);
|
||||
}
|
||||
|
||||
public int[] getMonitoringTypesAndStatus() {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
|
||||
return mGeofenceHardwareImpl.getMonitoringTypesAndStatus();
|
||||
}
|
||||
|
||||
public boolean addCircularFence(int id, double lat, double longitude, double radius,
|
||||
int lastTransition, int monitorTransitions, int
|
||||
notificationResponsiveness, int unknownTimer, int monitoringType,
|
||||
IGeofenceHardwareCallback callback) {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
|
||||
return mGeofenceHardwareImpl.addCircularFence(id, lat, longitude, radius,
|
||||
lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer,
|
||||
monitoringType, callback);
|
||||
}
|
||||
|
||||
public boolean removeGeofence(int id, int monitoringType) {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
|
||||
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
|
||||
return mGeofenceHardwareImpl.removeGeofence(id, monitoringType);
|
||||
}
|
||||
|
||||
public boolean pauseGeofence(int id, int monitoringType) {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
|
||||
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
|
||||
return mGeofenceHardwareImpl.pauseGeofence(id, monitoringType);
|
||||
}
|
||||
|
||||
public boolean resumeGeofence(int id, int monitorTransitions, int monitoringType) {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
|
||||
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
|
||||
return mGeofenceHardwareImpl.resumeGeofence(id, monitorTransitions, monitoringType);
|
||||
}
|
||||
|
||||
public boolean registerForMonitorStateChangeCallback(int monitoringType,
|
||||
IGeofenceHardwareCallback callback) {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
|
||||
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
|
||||
return mGeofenceHardwareImpl.registerForMonitorStateChangeCallback(monitoringType,
|
||||
callback);
|
||||
}
|
||||
|
||||
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
|
||||
IGeofenceHardwareCallback callback) {
|
||||
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
|
||||
"Location Hardware permission not granted to access hardware geofence");
|
||||
|
||||
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
|
||||
return mGeofenceHardwareImpl.unregisterForMonitorStateChangeCallback(monitoringType,
|
||||
callback);
|
||||
}
|
||||
};
|
||||
}
|
||||
36
core/java/android/hardware/location/IGeofenceHardware.aidl
Normal file
36
core/java/android/hardware/location/IGeofenceHardware.aidl
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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/LICENS E-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.hardware.location;
|
||||
|
||||
import android.location.IGpsGeofenceHardware;
|
||||
import android.hardware.location.IGeofenceHardwareCallback;
|
||||
|
||||
/** @hide */
|
||||
interface IGeofenceHardware {
|
||||
void setGpsGeofenceHardware(in IGpsGeofenceHardware service);
|
||||
int[] getMonitoringTypesAndStatus();
|
||||
boolean addCircularFence(int id, double lat, double longitude, double radius,
|
||||
int lastTransition, int monitorTransitions, int notificationResponsiveness,
|
||||
int unknownTimer, int monitoringType, in IGeofenceHardwareCallback callback);
|
||||
boolean removeGeofence(int id, int monitoringType);
|
||||
boolean pauseGeofence(int id, int monitoringType);
|
||||
boolean resumeGeofence(int id, int monitorTransitions, int monitoringType);
|
||||
boolean registerForMonitorStateChangeCallback(int monitoringType,
|
||||
IGeofenceHardwareCallback callback);
|
||||
boolean unregisterForMonitorStateChangeCallback(int monitoringType,
|
||||
IGeofenceHardwareCallback callback);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.hardware.location;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
/** @hide */
|
||||
oneway interface IGeofenceHardwareCallback {
|
||||
void onMonitoringSystemChange(int monitoringType, boolean available, in Location location);
|
||||
void onGeofenceChange(int geofenceId, int transition, in Location location,
|
||||
long timestamp, int monitoringType);
|
||||
void onGeofenceAdd(int geofenceId, int status);
|
||||
void onGeofenceRemove(int geofenceId, int status);
|
||||
void onGeofencePause(int geofenceId, int status);
|
||||
void onGeofenceResume(int geofenceId, int status);
|
||||
}
|
||||
@@ -616,6 +616,14 @@
|
||||
android:label="@string/permlab_installLocationProvider"
|
||||
android:description="@string/permdesc_installLocationProvider" />
|
||||
|
||||
<!-- Allows an application to use location features in hardware,
|
||||
such as the geofencing api
|
||||
Protected by signature|system protection level -->
|
||||
<permission android:name="android.permission.LOCATION_HARDWARE"
|
||||
android:permissionGroup="android.permission-group.LOCATION"
|
||||
android:protectionLevel="signature|system" />
|
||||
<uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
|
||||
|
||||
<!-- ======================================= -->
|
||||
<!-- Permissions for accessing networks -->
|
||||
<!-- ======================================= -->
|
||||
@@ -2350,6 +2358,9 @@
|
||||
android:permission="android.permission.MASTER_CLEAR"
|
||||
android:exported="true" />
|
||||
|
||||
<service android:name="android.hardware.location.GeofenceHardwareService"
|
||||
android:permission="android.permission.LOCATION_HARDWARE"
|
||||
android:exported="false" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
28
location/java/android/location/IGeofenceProvider.aidl
Normal file
28
location/java/android/location/IGeofenceProvider.aidl
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.hardware.location.IGeofenceHardware;
|
||||
|
||||
/**
|
||||
* An interface for location providers implementing the Geofencing service
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IGeofenceProvider {
|
||||
void setGeofenceHardware(in IGeofenceHardware proxy);
|
||||
}
|
||||
33
location/java/android/location/IGpsGeofenceHardware.aidl
Normal file
33
location/java/android/location/IGpsGeofenceHardware.aidl
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2013, 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;
|
||||
|
||||
/**
|
||||
* GPS hardware geofence
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IGpsGeofenceHardware
|
||||
{
|
||||
boolean isHardwareGeofenceSupported();
|
||||
boolean addCircularHardwareGeofence(int geofenceId, double latitude, double
|
||||
longitude, double radius, int lastTransition, int monitorTransition,
|
||||
int notificationResponsiveness, int unknownTimer);
|
||||
boolean removeHardwareGeofence(int geofenceId);
|
||||
boolean pauseHardwareGeofence(int geofenceId);
|
||||
boolean resumeHardwareGeofence(int geofenceId, int monitorTransition);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.location.provider;
|
||||
|
||||
import android.hardware.location.GeofenceHardware;
|
||||
import android.hardware.location.IGeofenceHardware;
|
||||
import android.os.IBinder;
|
||||
|
||||
import android.location.IGeofenceProvider;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.Long;
|
||||
|
||||
/**
|
||||
* Base class for geofence providers implemented as unbundled services.
|
||||
*
|
||||
* <p>Geofence providers can be implemented as services and return the result of
|
||||
* {@link com.android.location.provider.GeofenceProvider#getBinder()} in its getBinder() method.
|
||||
*
|
||||
* <p>IMPORTANT: This class is effectively a public API for unbundled
|
||||
* applications, and must remain API stable. See README.txt in the root
|
||||
* of this package for more information.
|
||||
*/
|
||||
public abstract class GeofenceProvider {
|
||||
|
||||
private GeofenceHardware mGeofenceHardware;
|
||||
|
||||
private IGeofenceProvider.Stub mProvider = new IGeofenceProvider.Stub() {
|
||||
public void setGeofenceHardware(IGeofenceHardware hardwareProxy) {
|
||||
mGeofenceHardware = new GeofenceHardware(hardwareProxy);
|
||||
onGeofenceHardwareChange(mGeofenceHardware);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the Binder interface for the geofence provider.
|
||||
* This is intended to be used for the onBind() method of
|
||||
* a service that implements a geofence service.
|
||||
*
|
||||
* @return the IBinder instance for the provider
|
||||
*/
|
||||
public IBinder getBinder() {
|
||||
return mProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when GeofenceHardware object becomes available.
|
||||
*
|
||||
* @param geofenceHardware Geofence Hardware object. This can be null
|
||||
* when for some reason the service connection gets disconnected.
|
||||
*/
|
||||
public abstract void onGeofenceHardwareChange(GeofenceHardware geofenceHardware);
|
||||
}
|
||||
@@ -54,19 +54,17 @@ import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.WorkSource;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
import com.android.internal.location.ProviderRequest;
|
||||
import com.android.server.location.GeocoderProxy;
|
||||
import com.android.server.location.GeofenceProxy;
|
||||
import com.android.server.location.GeofenceManager;
|
||||
import com.android.server.location.GpsLocationProvider;
|
||||
import com.android.server.location.LocationBlacklist;
|
||||
@@ -338,11 +336,11 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
addProviderLocked(passiveProvider);
|
||||
mEnabledProviders.add(passiveProvider.getName());
|
||||
mPassiveProvider = passiveProvider;
|
||||
// Create a gps location provider
|
||||
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
|
||||
mLocationHandler.getLooper());
|
||||
|
||||
if (GpsLocationProvider.isSupported()) {
|
||||
// Create a gps location provider
|
||||
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
|
||||
mLocationHandler.getLooper());
|
||||
mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
|
||||
mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
|
||||
addProviderLocked(gpsProvider);
|
||||
@@ -406,6 +404,14 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
if (mGeocodeProvider == null) {
|
||||
Slog.e(TAG, "no geocoder provider found");
|
||||
}
|
||||
|
||||
// bind to geofence provider
|
||||
GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, providerPackageNames,
|
||||
mLocationHandler, gpsProvider.getGpsGeofenceProxy());
|
||||
if (provider == null) {
|
||||
Slog.e(TAG, "no geofence provider found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
154
services/java/com/android/server/location/GeofenceProxy.java
Normal file
154
services/java/com/android/server/location/GeofenceProxy.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.server.location;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.hardware.location.GeofenceHardwareService;
|
||||
import android.hardware.location.IGeofenceHardware;
|
||||
import android.location.IGeofenceProvider;
|
||||
import android.location.IGpsGeofenceHardware;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import com.android.server.ServiceWatcher;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final class GeofenceProxy {
|
||||
private static final String TAG = "GeofenceProxy";
|
||||
private static final String SERVICE_ACTION =
|
||||
"com.android.location.service.GeofenceProvider";
|
||||
private ServiceWatcher mServiceWatcher;
|
||||
private Context mContext;
|
||||
private IGeofenceHardware mGeofenceHardware;
|
||||
private IGpsGeofenceHardware mGpsGeofenceHardware;
|
||||
|
||||
private static final int GEOFENCE_PROVIDER_CONNECTED = 1;
|
||||
private static final int GEOFENCE_HARDWARE_CONNECTED = 2;
|
||||
private static final int GEOFENCE_HARDWARE_DISCONNECTED = 3;
|
||||
private static final int GEOFENCE_GPS_HARDWARE_CONNECTED = 4;
|
||||
private static final int GEOFENCE_GPS_HARDWARE_DISCONNECTED = 5;
|
||||
|
||||
private Runnable mRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mHandler.sendEmptyMessage(GEOFENCE_PROVIDER_CONNECTED);
|
||||
}
|
||||
};
|
||||
|
||||
public static GeofenceProxy createAndBind(Context context,
|
||||
List<String> initialPackageNames, Handler handler, IGpsGeofenceHardware gpsGeofence) {
|
||||
GeofenceProxy proxy = new GeofenceProxy(context, initialPackageNames, handler, gpsGeofence);
|
||||
if (proxy.bindGeofenceProvider()) {
|
||||
return proxy;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private GeofenceProxy(Context context, List<String> initialPackageName, Handler handler,
|
||||
IGpsGeofenceHardware gpsGeofence) {
|
||||
mContext = context;
|
||||
mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, initialPackageName,
|
||||
mRunnable, handler);
|
||||
mGpsGeofenceHardware = gpsGeofence;
|
||||
bindHardwareGeofence();
|
||||
}
|
||||
|
||||
private boolean bindGeofenceProvider() {
|
||||
return mServiceWatcher.start();
|
||||
}
|
||||
|
||||
private IGeofenceProvider getGeofenceProviderService() {
|
||||
return IGeofenceProvider.Stub.asInterface(mServiceWatcher.getBinder());
|
||||
}
|
||||
|
||||
private void bindHardwareGeofence() {
|
||||
mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
|
||||
mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER);
|
||||
}
|
||||
|
||||
private ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mGeofenceHardware = IGeofenceHardware.Stub.asInterface(service);
|
||||
mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_CONNECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mGeofenceHardware = null;
|
||||
mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_DISCONNECTED);
|
||||
}
|
||||
};
|
||||
|
||||
private void setGeofenceHardwareInProvider() {
|
||||
try {
|
||||
getGeofenceProviderService().setGeofenceHardware(mGeofenceHardware);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Remote Exception: setGeofenceHardwareInProvider: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setGpsGeofence() {
|
||||
try {
|
||||
mGeofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error while connecting to GeofenceHardwareService");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This needs to be reworked, when more services get added,
|
||||
// Might need a state machine or add a framework utility class,
|
||||
private Handler mHandler = new Handler() {
|
||||
private boolean mGeofenceHardwareConnected = false;
|
||||
private boolean mGeofenceProviderConnected = false;
|
||||
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case GEOFENCE_PROVIDER_CONNECTED:
|
||||
mGeofenceProviderConnected = true;
|
||||
if (mGeofenceHardwareConnected) {
|
||||
setGeofenceHardwareInProvider();
|
||||
}
|
||||
break;
|
||||
case GEOFENCE_HARDWARE_CONNECTED:
|
||||
setGpsGeofence();
|
||||
mGeofenceHardwareConnected = true;
|
||||
if (mGeofenceProviderConnected) {
|
||||
setGeofenceHardwareInProvider();
|
||||
}
|
||||
break;
|
||||
case GEOFENCE_HARDWARE_DISCONNECTED:
|
||||
mGeofenceHardwareConnected = false;
|
||||
setGeofenceHardwareInProvider();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -24,7 +24,10 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.Cursor;
|
||||
import android.hardware.location.GeofenceHardwareImpl;
|
||||
import android.hardware.location.IGeofenceHardware;
|
||||
import android.location.Criteria;
|
||||
import android.location.IGpsGeofenceHardware;
|
||||
import android.location.IGpsStatusListener;
|
||||
import android.location.IGpsStatusProvider;
|
||||
import android.location.ILocationManager;
|
||||
@@ -314,6 +317,8 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
// only modified on handler thread
|
||||
private WorkSource mClientSource = new WorkSource();
|
||||
|
||||
private GeofenceHardwareImpl mGeofenceHardwareImpl;
|
||||
|
||||
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
|
||||
@Override
|
||||
public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
|
||||
@@ -367,6 +372,10 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
return mGpsStatusProvider;
|
||||
}
|
||||
|
||||
public IGpsGeofenceHardware getGpsGeofenceProxy() {
|
||||
return mGpsGeofenceBinder;
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
@@ -918,6 +927,31 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
return result;
|
||||
}
|
||||
|
||||
private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
|
||||
public boolean isHardwareGeofenceSupported() {
|
||||
return native_is_geofence_supported();
|
||||
}
|
||||
|
||||
public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
|
||||
double longitude, double radius, int lastTransition, int monitorTransitions,
|
||||
int notificationResponsiveness, int unknownTimer) {
|
||||
return native_add_geofence(geofenceId, latitude, longitude, radius,
|
||||
lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
|
||||
}
|
||||
|
||||
public boolean removeHardwareGeofence(int geofenceId) {
|
||||
return native_remove_geofence(geofenceId);
|
||||
}
|
||||
|
||||
public boolean pauseHardwareGeofence(int geofenceId) {
|
||||
return native_pause_geofence(geofenceId);
|
||||
}
|
||||
|
||||
public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
|
||||
return native_resume_geofence(geofenceId, monitorTransition);
|
||||
}
|
||||
};
|
||||
|
||||
private boolean deleteAidingData(Bundle extras) {
|
||||
int flags;
|
||||
|
||||
@@ -1017,6 +1051,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
return ((mEngineCapabilities & capability) != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* called from native code to update our position.
|
||||
*/
|
||||
@@ -1320,6 +1355,73 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from native to report GPS Geofence transition
|
||||
* All geofence callbacks are called on the same thread
|
||||
*/
|
||||
private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
|
||||
double longitude, double altitude, float speed, float bearing, float accuracy,
|
||||
long timestamp, int transition, long transitionTimestamp) {
|
||||
if (mGeofenceHardwareImpl == null) {
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
mGeofenceHardwareImpl.reportGpsGeofenceTransition(geofenceId, flags, latitude, longitude,
|
||||
altitude, speed, bearing, accuracy, timestamp, transition, transitionTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code to report GPS status change.
|
||||
*/
|
||||
private void reportGeofenceStatus(int status, int flags, double latitude,
|
||||
double longitude, double altitude, float speed, float bearing, float accuracy,
|
||||
long timestamp) {
|
||||
if (mGeofenceHardwareImpl == null) {
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
mGeofenceHardwareImpl.reportGpsGeofenceStatus(status, flags, latitude, longitude, altitude,
|
||||
speed, bearing, accuracy, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code - Geofence Add callback
|
||||
*/
|
||||
private void reportGeofenceAddStatus(int geofenceId, int status) {
|
||||
if (mGeofenceHardwareImpl == null) {
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
mGeofenceHardwareImpl.reportGpsGeofenceAddStatus(geofenceId, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code - Geofence Remove callback
|
||||
*/
|
||||
private void reportGeofenceRemoveStatus(int geofenceId, int status) {
|
||||
if (mGeofenceHardwareImpl == null) {
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
mGeofenceHardwareImpl.reportGpsGeofenceRemoveStatus(geofenceId, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code - Geofence Pause callback
|
||||
*/
|
||||
private void reportGeofencePauseStatus(int geofenceId, int status) {
|
||||
if (mGeofenceHardwareImpl == null) {
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
mGeofenceHardwareImpl.reportGpsGeofencePauseStatus(geofenceId, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code - Geofence Resume callback
|
||||
*/
|
||||
private void reportGeofenceResumeStatus(int geofenceId, int status) {
|
||||
if (mGeofenceHardwareImpl == null) {
|
||||
mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
|
||||
}
|
||||
mGeofenceHardwareImpl.reportGpsGeofenceResumeStatus(geofenceId, status);
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
// NI Client support
|
||||
//=============================================================
|
||||
@@ -1650,4 +1752,13 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
|
||||
private native void native_update_network_state(boolean connected, int type,
|
||||
boolean roaming, boolean available, String extraInfo, String defaultAPN);
|
||||
|
||||
// Hardware Geofence support.
|
||||
private static native boolean native_is_geofence_supported();
|
||||
private static native boolean native_add_geofence(int geofenceId, double latitude,
|
||||
double longitude, double radius, int lastTransition,int monitorTransitions,
|
||||
int notificationResponsivenes, int unknownTimer);
|
||||
private static native boolean native_remove_geofence(int geofenceId);
|
||||
private static native boolean native_resume_geofence(int geofenceId, int transitions);
|
||||
private static native boolean native_pause_geofence(int geofenceId);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,12 @@ static jmethodID method_reportNiNotification;
|
||||
static jmethodID method_requestRefLocation;
|
||||
static jmethodID method_requestSetID;
|
||||
static jmethodID method_requestUtcTime;
|
||||
static jmethodID method_reportGeofenceTransition;
|
||||
static jmethodID method_reportGeofenceStatus;
|
||||
static jmethodID method_reportGeofenceAddStatus;
|
||||
static jmethodID method_reportGeofenceRemoveStatus;
|
||||
static jmethodID method_reportGeofencePauseStatus;
|
||||
static jmethodID method_reportGeofenceResumeStatus;
|
||||
|
||||
static const GpsInterface* sGpsInterface = NULL;
|
||||
static const GpsXtraInterface* sGpsXtraInterface = NULL;
|
||||
@@ -50,6 +56,7 @@ static const AGpsInterface* sAGpsInterface = NULL;
|
||||
static const GpsNiInterface* sGpsNiInterface = NULL;
|
||||
static const GpsDebugInterface* sGpsDebugInterface = NULL;
|
||||
static const AGpsRilInterface* sAGpsRilInterface = NULL;
|
||||
static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
|
||||
|
||||
// temporary storage for GPS callbacks
|
||||
static GpsSvStatus sGpsSvStatus;
|
||||
@@ -107,7 +114,7 @@ static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
|
||||
|
||||
static void set_capabilities_callback(uint32_t capabilities)
|
||||
{
|
||||
ALOGD("set_capabilities_callback: %ld\n", capabilities);
|
||||
ALOGD("set_capabilities_callback: %du\n", capabilities);
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
@@ -233,6 +240,97 @@ AGpsRilCallbacks sAGpsRilCallbacks = {
|
||||
create_thread_callback,
|
||||
};
|
||||
|
||||
static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
|
||||
int32_t transition, GpsUtcTime timestamp)
|
||||
{
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
|
||||
location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
|
||||
(jdouble)location->altitude,
|
||||
(jfloat)location->speed, (jfloat)location->bearing,
|
||||
(jfloat)location->accuracy, (jlong)location->timestamp,
|
||||
transition, timestamp);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
};
|
||||
|
||||
static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
|
||||
{
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jint flags = 0;
|
||||
jdouble latitude = 0;
|
||||
jdouble longitude = 0;
|
||||
jdouble altitude = 0;
|
||||
jfloat speed = 0;
|
||||
jfloat bearing = 0;
|
||||
jfloat accuracy = 0;
|
||||
jlong timestamp = 0;
|
||||
if (location != NULL) {
|
||||
flags = location->flags;
|
||||
latitude = location->latitude;
|
||||
longitude = location->longitude;
|
||||
altitude = location->altitude;
|
||||
speed = location->speed;
|
||||
bearing = location->bearing;
|
||||
accuracy = location->accuracy;
|
||||
timestamp = location->timestamp;
|
||||
}
|
||||
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
|
||||
flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
};
|
||||
|
||||
static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
|
||||
{
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
|
||||
ALOGE("Error in geofence_add_callback: %d\n", status);
|
||||
}
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
};
|
||||
|
||||
static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
|
||||
{
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
|
||||
ALOGE("Error in geofence_remove_callback: %d\n", status);
|
||||
}
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
};
|
||||
|
||||
static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
|
||||
{
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
|
||||
ALOGE("Error in geofence_resume_callback: %d\n", status);
|
||||
}
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
};
|
||||
|
||||
static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
|
||||
{
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
|
||||
ALOGE("Error in geofence_pause_callback: %d\n", status);
|
||||
}
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
};
|
||||
|
||||
GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
|
||||
gps_geofence_transition_callback,
|
||||
gps_geofence_status_callback,
|
||||
gps_geofence_add_callback,
|
||||
gps_geofence_remove_callback,
|
||||
gps_geofence_pause_callback,
|
||||
gps_geofence_resume_callback,
|
||||
create_thread_callback,
|
||||
};
|
||||
|
||||
static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
|
||||
int err;
|
||||
hw_module_t* module;
|
||||
@@ -249,6 +347,18 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
|
||||
method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
|
||||
method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
|
||||
method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
|
||||
method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
|
||||
"(IIDDDFFFJIJ)V");
|
||||
method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
|
||||
"(IIDDDFFFJ)V");
|
||||
method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
|
||||
"(II)V");
|
||||
method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
|
||||
"(II)V");
|
||||
method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
|
||||
"(II)V");
|
||||
method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
|
||||
"(II)V");
|
||||
|
||||
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
|
||||
if (err == 0) {
|
||||
@@ -270,6 +380,8 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
|
||||
(const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
|
||||
sAGpsRilInterface =
|
||||
(const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
|
||||
sGpsGeofencingInterface =
|
||||
(const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +399,7 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o
|
||||
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
|
||||
return false;
|
||||
|
||||
// if XTRA initialization fails we will disable it by sGpsXtraInterface to null,
|
||||
// if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
|
||||
// but continue to allow the rest of the GPS interface to work.
|
||||
if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
|
||||
sGpsXtraInterface = NULL;
|
||||
@@ -297,6 +409,8 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o
|
||||
sGpsNiInterface->init(&sGpsNiCallbacks);
|
||||
if (sAGpsRilInterface)
|
||||
sAGpsRilInterface->init(&sAGpsRilCallbacks);
|
||||
if (sGpsGeofencingInterface)
|
||||
sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -565,6 +679,62 @@ static void android_location_GpsLocationProvider_update_network_state(JNIEnv* en
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean android_location_GpsLocationProvider_is_geofence_supported(JNIEnv* env,
|
||||
jobject obj) {
|
||||
if (sGpsGeofencingInterface != NULL) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* env, jobject obj,
|
||||
jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
|
||||
jint last_transition, jint monitor_transition, jint notification_responsiveness,
|
||||
jint unknown_timer) {
|
||||
if (sGpsGeofencingInterface != NULL) {
|
||||
sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
|
||||
radius, last_transition, monitor_transition, notification_responsiveness,
|
||||
unknown_timer);
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
ALOGE("Geofence interface not available");
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* env, jobject obj,
|
||||
jint geofence_id) {
|
||||
if (sGpsGeofencingInterface != NULL) {
|
||||
sGpsGeofencingInterface->remove_geofence_area(geofence_id);
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
ALOGE("Geofence interface not available");
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* env, jobject obj,
|
||||
jint geofence_id) {
|
||||
if (sGpsGeofencingInterface != NULL) {
|
||||
sGpsGeofencingInterface->pause_geofence(geofence_id);
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
ALOGE("Geofence interface not available");
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* env, jobject obj,
|
||||
jint geofence_id, jint monitor_transition) {
|
||||
if (sGpsGeofencingInterface != NULL) {
|
||||
sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
ALOGE("Geofence interface not available");
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static JNINativeMethod sMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
|
||||
@@ -591,6 +761,11 @@ static JNINativeMethod sMethods[] = {
|
||||
{"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},
|
||||
{"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},
|
||||
{"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },
|
||||
{"native_is_geofence_supported", "()Z", (void*) android_location_GpsLocationProvider_is_geofence_supported},
|
||||
{"native_add_geofence", "(IDDDIIII)Z", (void *)android_location_GpsLocationProvider_add_geofence},
|
||||
{"native_remove_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_remove_geofence},
|
||||
{"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence},
|
||||
{"native_resume_geofence", "(II)Z", (void *)android_location_GpsLocationProvider_resume_geofence}
|
||||
};
|
||||
|
||||
int register_android_server_location_GpsLocationProvider(JNIEnv* env)
|
||||
|
||||
Reference in New Issue
Block a user