1e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly/*
2e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * Copyright (C) 2012 The Android Open Source Project
3e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly *
4e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * you may not use this file except in compliance with the License.
6e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * You may obtain a copy of the License at
7e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly *
8e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly *
10e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * Unless required by applicable law or agreed to in writing, software
11e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * See the License for the specific language governing permissions and
14e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly * limitations under the License.
15e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly */
16e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
17e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
18e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pellypackage com.android.server.location;
19e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.app.PendingIntent;
216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.Geofence;
22e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pellyimport android.location.Location;
23e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
24e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly/**
256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Represents state associated with a geofence
26e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly */
276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellypublic class GeofenceState {
28e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    public final static int FLAG_ENTER = 0x01;
29e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    public final static int FLAG_EXIT = 0x02;
30e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int STATE_UNKNOWN = 0;
326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int STATE_INSIDE = 1;
336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int STATE_OUTSIDE = 2;
34e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public final Geofence mFence;
366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Location mLocation;
376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public final long mExpireAt;
385e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    public final int mAllowedResolutionLevel;
395e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    public final int mUid;
406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public final String mPackageName;
416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public final PendingIntent mIntent;
42e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
43e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    int mState;  // current state
444cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease    double mDistanceToCenter;  // current distance to center of fence
45e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
464cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease    public GeofenceState(Geofence fence, long expireAt,
475e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            int allowedResolutionLevel, int uid, String packageName, PendingIntent intent) {
48e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        mState = STATE_UNKNOWN;
494cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        mDistanceToCenter = Double.MAX_VALUE;
50e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mFence = fence;
526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mExpireAt = expireAt;
535e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mAllowedResolutionLevel = allowedResolutionLevel;
545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mUid = uid;
556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mPackageName = packageName;
566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mIntent = intent;
57e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
58e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        mLocation = new Location("");
596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocation.setLatitude(fence.getLatitude());
606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocation.setLongitude(fence.getLongitude());
61e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
62e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
63e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    /**
64e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly     * Process a new location.
65e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly     * @return FLAG_ENTER or FLAG_EXIT if the fence was crossed, 0 otherwise
66e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly     */
67e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    public int processLocation(Location location) {
684cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        mDistanceToCenter = mLocation.distanceTo(location);
69e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
70e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        int prevState = mState;
71e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        //TODO: inside/outside detection could be made more rigorous
724cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        boolean inside = mDistanceToCenter <= Math.max(mFence.getRadius(), location.getAccuracy());
73e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (inside) {
74e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            mState = STATE_INSIDE;
754cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease            if (prevState != STATE_INSIDE) {
764cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease                return FLAG_ENTER; // return enter if previously exited or unknown
774cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease            }
78e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        } else {
79e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            mState = STATE_OUTSIDE;
804cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease            if (prevState == STATE_INSIDE) {
814cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease                return FLAG_EXIT; // return exit only if previously entered
824cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease            }
83e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
84e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        return 0;
85e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
86e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
874cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease    /**
884cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease     * Gets the distance from the current location to the fence's boundary.
894cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease     * @return The distance or {@link Double#MAX_VALUE} if unknown.
904cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease     */
914cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease    public double getDistanceToBoundary() {
924cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        if (Double.compare(mDistanceToCenter, Double.MAX_VALUE) == 0) {
934cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease            return Double.MAX_VALUE;
944cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        } else {
954cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease            return Math.abs(mFence.getRadius() - mDistanceToCenter);
964cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        }
97e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
98e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
99e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
100e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    public String toString() {
101e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        String state;
102e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        switch (mState) {
103e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            case STATE_INSIDE:
104e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                state = "IN";
105e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                break;
106e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            case STATE_OUTSIDE:
107e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                state = "OUT";
108e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                break;
109e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            default:
110e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                state = "?";
111e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
1124cd0a50b26eeb68517d03bc0cafc18e98bfc1fecVictoria Lease        return String.format("%s d=%.0f %s", mFence.toString(), mDistanceToCenter, state);
113e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
114e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly}
115