content: /*
   * 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);
      }
  }
  