am f4fdceb1: am b46316dd: am 823ac05c: Add support for sources in Geofencing APIs.

* commit 'f4fdceb117ebdc41c2937da86a751936c0f8c21a':
  Add support for sources in Geofencing APIs.
This commit is contained in:
destradaa
2014-07-30 23:51:17 +00:00
committed by Android Git Automerger
13 changed files with 368 additions and 94 deletions

View File

@@ -16,6 +16,7 @@
package android.hardware.location;
import android.location.Location;
import android.os.Build;
import android.os.RemoteException;
import java.lang.ref.WeakReference;
@@ -60,19 +61,19 @@ public final class GeofenceHardware {
public static final int MONITORING_TYPE_FUSED_HARDWARE = 1;
/**
* Constant to indiciate that the monitoring system is currently
* Constant to indicate 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
* Constant to indicate 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
* Constant to indicate that the monitoring system is unsupported
* for hardware geofence monitoring.
*/
public static final int MONITOR_UNSUPPORTED = 2;
@@ -129,6 +130,33 @@ public final class GeofenceHardware {
*/
public static final int GEOFENCE_ERROR_INSUFFICIENT_MEMORY = 6;
// the following values must match the definitions in fused_location.h
/**
* The constant used to indicate that the monitoring system supports GNSS.
*/
public static final int SOURCE_TECHNOLOGY_GNSS = (1<<0);
/**
* The constant used to indicate that the monitoring system supports WiFi.
*/
public static final int SOURCE_TECHNOLOGY_WIFI = (1<<1);
/**
* The constant used to indicate that the monitoring system supports Sensors.
*/
public static final int SOURCE_TECHNOLOGY_SENSORS = (1<<2);
/**
* The constant used to indicate that the monitoring system supports Cell.
*/
public static final int SOURCE_TECHNOLOGY_CELL = (1<<3);
/**
* The constant used to indicate that the monitoring system supports Bluetooth.
*/
public static final int SOURCE_TECHNOLOGY_BLUETOOTH = (1<<4);
private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>
mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>();
private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
@@ -238,13 +266,9 @@ public final class GeofenceHardware {
geofenceRequest, GeofenceHardwareCallback callback) {
try {
if (geofenceRequest.getType() == GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
return mService.addCircularFence(geofenceId, monitoringType,
geofenceRequest.getLatitude(),
geofenceRequest.getLongitude(), geofenceRequest.getRadius(),
geofenceRequest.getLastTransition(),
geofenceRequest.getMonitorTransitions(),
geofenceRequest.getNotificationResponsiveness(),
geofenceRequest.getUnknownTimer(),
return mService.addCircularFence(
monitoringType,
new GeofenceHardwareRequestParcelable(geofenceId, geofenceRequest),
getCallbackWrapper(callback));
} else {
throw new IllegalArgumentException("Geofence Request type not supported");
@@ -452,10 +476,21 @@ public final class GeofenceHardware {
mCallback = new WeakReference<GeofenceHardwareMonitorCallback>(c);
}
public void onMonitoringSystemChange(int monitoringType, boolean available,
Location location) {
public void onMonitoringSystemChange(GeofenceHardwareMonitorEvent event) {
GeofenceHardwareMonitorCallback c = mCallback.get();
if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
if (c == null) return;
// report the legacy event first, so older clients are not broken
c.onMonitoringSystemChange(
event.getMonitoringType(),
event.getMonitoringStatus() == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE,
event.getLocation());
// and only call the updated callback on on L and above, this complies with the
// documentation of GeofenceHardwareMonitorCallback
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
c.onMonitoringSystemChange(event);
}
}
}

View File

@@ -210,18 +210,20 @@ public final class GeofenceHardwareImpl {
}
}
public boolean addCircularFence(int geofenceId, int monitoringType, double latitude,
double longitude, double radius, int lastTransition,int monitorTransitions,
int notificationResponsivenes, int unknownTimer, IGeofenceHardwareCallback callback) {
public boolean addCircularFence(
int monitoringType,
GeofenceHardwareRequestParcelable request,
IGeofenceHardwareCallback callback) {
int geofenceId = request.getId();
// 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);
String message = String.format(
"addCircularFence: monitoringType=%d, %s",
monitoringType,
request);
Log.d(TAG, message);
}
boolean result;
@@ -237,9 +239,15 @@ public final class GeofenceHardwareImpl {
case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE:
if (mGpsService == null) return false;
try {
result = mGpsService.addCircularHardwareGeofence(geofenceId, latitude,
longitude, radius, lastTransition, monitorTransitions,
notificationResponsivenes, unknownTimer);
result = mGpsService.addCircularHardwareGeofence(
request.getId(),
request.getLatitude(),
request.getLongitude(),
request.getRadius(),
request.getLastTransition(),
request.getMonitorTransitions(),
request.getNotificationResponsiveness(),
request.getUnknownTimer());
} catch (RemoteException e) {
Log.e(TAG, "AddGeofence: Remote Exception calling LocationManagerService");
result = false;
@@ -249,20 +257,9 @@ public final class GeofenceHardwareImpl {
if(mFusedService == null) {
return false;
}
GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence(
latitude,
longitude,
radius);
request.setUnknownTimer(unknownTimer);
request.setNotificationResponsiveness(notificationResponsivenes);
request.setMonitorTransitions(monitorTransitions);
request.setLastTransition(lastTransition);
GeofenceHardwareRequestParcelable parcelableRequest =
new GeofenceHardwareRequestParcelable(geofenceId, request);
try {
mFusedService.addGeofences(
new GeofenceHardwareRequestParcelable[] { parcelableRequest });
new GeofenceHardwareRequestParcelable[] { request });
result = true;
} catch(RemoteException e) {
Log.e(TAG, "AddGeofence: RemoteException calling LocationManagerService");
@@ -471,12 +468,14 @@ public final class GeofenceHardwareImpl {
int monitoringStatus,
Location location,
int source) {
// TODO: use the source if needed in the future
setMonitorAvailability(monitoringType, monitoringStatus);
acquireWakeLock();
Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, location);
message.arg1 = monitoringStatus;
message.arg2 = monitoringType;
GeofenceHardwareMonitorEvent event = new GeofenceHardwareMonitorEvent(
monitoringType,
monitoringStatus,
source,
location);
Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, event);
message.sendToTarget();
}
@@ -644,20 +643,17 @@ public final class GeofenceHardwareImpl {
switch (msg.what) {
case GEOFENCE_STATUS:
Location location = (Location) msg.obj;
int val = msg.arg1;
monitoringType = msg.arg2;
boolean available;
available = (val == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE ?
true : false);
callbackList = mCallbacks[monitoringType];
GeofenceHardwareMonitorEvent event = (GeofenceHardwareMonitorEvent) msg.obj;
callbackList = mCallbacks[event.getMonitoringType()];
if (callbackList != null) {
if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available);
if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: " + event);
for (IGeofenceHardwareMonitorCallback c: callbackList) {
for (IGeofenceHardwareMonitorCallback c : callbackList) {
try {
c.onMonitoringSystemChange(monitoringType, available, location);
} catch (RemoteException e) {}
c.onMonitoringSystemChange(event);
} catch (RemoteException e) {
Log.d(TAG, "Error reporting onMonitoringSystemChange.", e);
}
}
}
releaseWakeLock();

View File

@@ -19,19 +19,39 @@ package android.hardware.location;
import android.location.Location;
/**
* The callback class associated with the status change of hardware montiors
* The callback class associated with the status change of hardware monitors
* in {@link GeofenceHardware}
*/
public abstract class GeofenceHardwareMonitorCallback {
/**
* The callback called when the state of a monitoring system changes.
* {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a
* monitoring system
* monitoring system.
*
* @deprecated use {@link #onMonitoringSystemChange(GeofenceHardwareMonitorEvent)} instead.
* NOTE: this API is will remain to be called on Android API 21 and above for backwards
* compatibility. But clients must stop implementing it when updating their code.
*
* @param monitoringType The type of the monitoring system.
* @param available Indicates whether the system is currenty available or not.
* @param available Indicates whether the system is currently available or not.
* @param location The last known location according to the monitoring system.
*/
@Deprecated
public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) {
}
/**
* The callback called when the sate of a monitoring system changes.
* {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a monitoring system.
* {@link GeofenceHardware#MONITOR_CURRENTLY_AVAILABLE} is an example of a monitoring status.
* {@link GeofenceHardware#SOURCE_TECHNOLOGY_GNSS} is an example of a source.
*
* This callback must be used instead of
* {@link #onMonitoringSystemChange(int, boolean, android.location.Location)}.
*
* NOTE: this API is only called on Android API 21 and above.
*
* @param event An object representing the monitoring system change event.
*/
public void onMonitoringSystemChange(GeofenceHardwareMonitorEvent event) {}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2014 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;
parcelable GeofenceHardwareMonitorEvent;

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2014 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;
import android.os.Parcel;
import android.os.Parcelable;
/**
* A class that represents an event for each change in the state of a monitoring system.
*/
public class GeofenceHardwareMonitorEvent implements Parcelable {
private final int mMonitoringType;
private final int mMonitoringStatus;
private final int mSourceTechnologies;
private final Location mLocation;
public GeofenceHardwareMonitorEvent(
int monitoringType,
int monitoringStatus,
int sourceTechnologies,
Location location) {
mMonitoringType = monitoringType;
mMonitoringStatus = monitoringStatus;
mSourceTechnologies = sourceTechnologies;
mLocation = location;
}
/**
* Returns the type of the monitoring system that has a change on its state.
*/
public int getMonitoringType() {
return mMonitoringType;
}
/**
* Returns the new status associated with the monitoring system.
*/
public int getMonitoringStatus() {
return mMonitoringStatus;
}
/**
* Returns the source technologies that the status is associated to.
*/
public int getSourceTechnologies() {
return mSourceTechnologies;
}
/**
* Returns the last known location according to the monitoring system.
*/
public Location getLocation() {
return mLocation;
}
public static final Creator<GeofenceHardwareMonitorEvent> CREATOR =
new Creator<GeofenceHardwareMonitorEvent>() {
@Override
public GeofenceHardwareMonitorEvent createFromParcel(Parcel source) {
ClassLoader classLoader = GeofenceHardwareMonitorEvent.class.getClassLoader();
int monitoringType = source.readInt();
int monitoringStatus = source.readInt();
int sourceTechnologies = source.readInt();
Location location = source.readParcelable(classLoader);
return new GeofenceHardwareMonitorEvent(
monitoringType,
monitoringStatus,
sourceTechnologies,
location);
}
@Override
public GeofenceHardwareMonitorEvent[] newArray(int size) {
return new GeofenceHardwareMonitorEvent[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mMonitoringType);
parcel.writeInt(mMonitoringStatus);
parcel.writeInt(mSourceTechnologies);
parcel.writeParcelable(mLocation, flags);
}
@Override
public String toString() {
return String.format(
"GeofenceHardwareMonitorEvent: type=%d, status=%d, sources=%d, location=%s",
mMonitoringType,
mMonitoringStatus,
mSourceTechnologies,
mLocation);
}
}

View File

@@ -33,6 +33,7 @@ public final class GeofenceHardwareRequest {
private int mMonitorTransitions = GeofenceHardware.GEOFENCE_UNCERTAIN |
GeofenceHardware.GEOFENCE_ENTERED | GeofenceHardware.GEOFENCE_EXITED;
private int mNotificationResponsiveness = 5000; // 5 secs
private int mSourceTechnologies = GeofenceHardware.SOURCE_TECHNOLOGY_GNSS;
private void setCircularGeofence(double latitude, double longitude, double radius) {
mLatitude = latitude;
@@ -101,6 +102,28 @@ public final class GeofenceHardwareRequest {
mNotificationResponsiveness = notificationResponsiveness;
}
/**
* Set the source technologies to use while tracking the geofence.
* The value is the bit-wise of one or several source fields defined in
* {@link GeofenceHardware}.
*
* @param sourceTechnologies The set of source technologies to use.
*/
public void setSourceTechnologies(int sourceTechnologies) {
int sourceTechnologiesAll = GeofenceHardware.SOURCE_TECHNOLOGY_GNSS
| GeofenceHardware.SOURCE_TECHNOLOGY_WIFI
| GeofenceHardware.SOURCE_TECHNOLOGY_SENSORS
| GeofenceHardware.SOURCE_TECHNOLOGY_CELL
| GeofenceHardware.SOURCE_TECHNOLOGY_BLUETOOTH;
int sanitizedSourceTechnologies = (sourceTechnologies & sourceTechnologiesAll);
if (sanitizedSourceTechnologies == 0) {
throw new IllegalArgumentException("At least one valid source technology must be set.");
}
mSourceTechnologies = sanitizedSourceTechnologies;
}
/**
* Returns the latitude of this geofence.
*/
@@ -150,6 +173,13 @@ public final class GeofenceHardwareRequest {
return mLastTransition;
}
/**
* Returns the source technologies to track this geofence.
*/
public int getSourceTechnologies() {
return mSourceTechnologies;
}
int getType() {
return mType;
}

View File

@@ -97,10 +97,44 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
return mRequest.getType();
}
/**
* Returns the source technologies to track this geofence.
*/
int getSourceTechnologies() {
return mRequest.getSourceTechnologies();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("id=");
builder.append(mId);
builder.append(", type=");
builder.append(mRequest.getType());
builder.append(", latitude=");
builder.append(mRequest.getLatitude());
builder.append(", longitude=");
builder.append(mRequest.getLongitude());
builder.append(", radius=");
builder.append(mRequest.getRadius());
builder.append(", lastTransition=");
builder.append(mRequest.getLastTransition());
builder.append(", unknownTimer=");
builder.append(mRequest.getUnknownTimer());
builder.append(", monitorTransitions=");
builder.append(mRequest.getMonitorTransitions());
builder.append(", notificationResponsiveness=");
builder.append(mRequest.getNotificationResponsiveness());
builder.append(", sourceTechnologies=");
builder.append(mRequest.getSourceTechnologies());
return builder.toString();
}
/**
* Method definitions to support Parcelable operations.
*/
public static final Parcelable.Creator<GeofenceHardwareRequestParcelable> CREATOR =
public static final Parcelable.Creator<GeofenceHardwareRequestParcelable> CREATOR =
new Parcelable.Creator<GeofenceHardwareRequestParcelable>() {
@Override
public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) {
@@ -120,7 +154,8 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
request.setMonitorTransitions(parcel.readInt());
request.setUnknownTimer(parcel.readInt());
request.setNotificationResponsiveness(parcel.readInt());
request.setSourceTechnologies(parcel.readInt());
int id = parcel.readInt();
return new GeofenceHardwareRequestParcelable(id, request);
}
@@ -146,6 +181,7 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
parcel.writeInt(getMonitorTransitions());
parcel.writeInt(getUnknownTimer());
parcel.writeInt(getNotificationResponsiveness());
parcel.writeInt(getSourceTechnologies());
parcel.writeInt(getId());
}
}

View File

@@ -86,15 +86,14 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.getStatusOfMonitoringType(monitoringType);
}
public boolean addCircularFence(int id, int monitoringType, double lat, double longitude,
double radius, int lastTransition, int monitorTransitions, int
notificationResponsiveness, int unknownTimer, IGeofenceHardwareCallback callback) {
public boolean addCircularFence(
int monitoringType,
GeofenceHardwareRequestParcelable request,
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, monitoringType, lat, longitude,
radius, lastTransition, monitorTransitions, notificationResponsiveness,
unknownTimer, callback);
return mGeofenceHardwareImpl.addCircularFence(monitoringType, request, callback);
}
public boolean removeGeofence(int id, int monitoringType) {

View File

@@ -18,6 +18,7 @@ package android.hardware.location;
import android.location.IFusedGeofenceHardware;
import android.location.IGpsGeofenceHardware;
import android.hardware.location.GeofenceHardwareRequestParcelable;
import android.hardware.location.IGeofenceHardwareCallback;
import android.hardware.location.IGeofenceHardwareMonitorCallback;
@@ -27,9 +28,10 @@ interface IGeofenceHardware {
void setFusedGeofenceHardware(in IFusedGeofenceHardware service);
int[] getMonitoringTypes();
int getStatusOfMonitoringType(int monitoringType);
boolean addCircularFence(int id, int monitoringType, double lat, double longitude,
double radius, int lastTransition, int monitorTransitions,
int notificationResponsiveness, int unknownTimer,in IGeofenceHardwareCallback callback);
boolean addCircularFence(
int monitoringType,
in GeofenceHardwareRequestParcelable request,
in IGeofenceHardwareCallback callback);
boolean removeGeofence(int id, int monitoringType);
boolean pauseGeofence(int id, int monitoringType);
boolean resumeGeofence(int id, int monitoringType, int monitorTransitions);

View File

@@ -16,9 +16,10 @@
package android.hardware.location;
import android.hardware.location.GeofenceHardwareMonitorEvent;
import android.location.Location;
/** @hide */
oneway interface IGeofenceHardwareMonitorCallback {
void onMonitoringSystemChange(int monitoringType, boolean available, in Location location);
void onMonitoringSystemChange(in GeofenceHardwareMonitorEvent event);
}