/*
* Copyright (C) 2012 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.app.PendingIntent;
import android.location.Geofence;
import android.location.Location;
/**
* Represents state associated with a geofence
*/
public class GeofenceState {
public final static int FLAG_ENTER = 0x01;
public final static int FLAG_EXIT = 0x02;
private static final int STATE_UNKNOWN = 0;
private static final int STATE_INSIDE = 1;
private static final int STATE_OUTSIDE = 2;
public final Geofence mFence;
private final Location mLocation;
public final long mExpireAt;
public final int mAllowedResolutionLevel;
public final int mUid;
public final String mPackageName;
public final PendingIntent mIntent;
int mState; // current state
double mDistanceToCenter; // current distance to center of fence
public GeofenceState(Geofence fence, long expireAt,
int allowedResolutionLevel, int uid, String packageName, PendingIntent intent) {
mState = STATE_UNKNOWN;
mDistanceToCenter = Double.MAX_VALUE;
mFence = fence;
mExpireAt = expireAt;
mAllowedResolutionLevel = allowedResolutionLevel;
mUid = uid;
mPackageName = packageName;
mIntent = intent;
mLocation = new Location("");
mLocation.setLatitude(fence.getLatitude());
mLocation.setLongitude(fence.getLongitude());
}
/**
* Process a new location.
* @return FLAG_ENTER or FLAG_EXIT if the fence was crossed, 0 otherwise
*/
public int processLocation(Location location) {
mDistanceToCenter = mLocation.distanceTo(location);
int prevState = mState;
//TODO: inside/outside detection could be made more rigorous
boolean inside = mDistanceToCenter <= Math.max(mFence.getRadius(), location.getAccuracy());
if (inside) {
mState = STATE_INSIDE;
if (prevState != STATE_INSIDE) {
return FLAG_ENTER; // return enter if previously exited or unknown
}
} else {
mState = STATE_OUTSIDE;
if (prevState == STATE_INSIDE) {
return FLAG_EXIT; // return exit only if previously entered
}
}
return 0;
}
/**
* Gets the distance from the current location to the fence's boundary.
* @return The distance or {@link Double#MAX_VALUE} if unknown.
*/
public double getDistanceToBoundary() {
if (Double.compare(mDistanceToCenter, Double.MAX_VALUE) == 0) {
return Double.MAX_VALUE;
} else {
return Math.abs(mFence.getRadius() - mDistanceToCenter);
}
}
@Override
public String toString() {
String state;
switch (mState) {
case STATE_INSIDE:
state = "IN";
break;
case STATE_OUTSIDE:
state = "OUT";
break;
default:
state = "?";
}
return String.format("%s d=%.0f %s", mFence.toString(), mDistanceToCenter, state);
}
}