16fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly/* 26fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Copyright (C) 2012 The Android Open Source Project 36fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * 46fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 56fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * you may not use this file except in compliance with the License. 66fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * You may obtain a copy of the License at 76fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * 86fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 96fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * 106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * Unless required by applicable law or agreed to in writing, software 116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * See the License for the specific language governing permissions and 146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * limitations under the License. 156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly */ 166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellypackage android.location; 186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.Parcel; 206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.Parcelable; 216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly/** 234e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly * Represents a geographical boundary, also known as a geofence. 244e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly * 258761e143c987fc48d854818988cde44700c9f602Scott Main * <p>Currently only circular geofences are supported and they do not support altitude changes. 267ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu * 277ab7f538924371a9dd4be7a27a6ae3b4c04b301cLaurent Tu * @hide 286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly */ 296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellypublic final class Geofence implements Parcelable { 306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** @hide */ 316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public static final int TYPE_HORIZONTAL_CIRCLE = 1; 326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final int mType; 346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final double mLatitude; 356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final double mLongitude; 366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private final float mRadius; 376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** 398761e143c987fc48d854818988cde44700c9f602Scott Main * Create a circular geofence (on a flat, horizontal plane). 404e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly * 413dffb8cb691ccd3187cec193223d53b32339ed8bVictoria Lease * @param latitude latitude in degrees, between -90 and +90 inclusive 423dffb8cb691ccd3187cec193223d53b32339ed8bVictoria Lease * @param longitude longitude in degrees, between -180 and +180 inclusive 436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * @param radius radius in meters 446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * @return a new geofence 456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly * @throws IllegalArgumentException if any parameters are out of range 466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly */ 476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public static Geofence createCircle(double latitude, double longitude, float radius) { 486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return new Geofence(latitude, longitude, radius); 496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private Geofence(double latitude, double longitude, float radius) { 526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly checkRadius(radius); 536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly checkLatLong(latitude, longitude); 546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mType = TYPE_HORIZONTAL_CIRCLE; 556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mLatitude = latitude; 566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mLongitude = longitude; 576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly mRadius = radius; 586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** @hide */ 616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public int getType() { 626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return mType; 636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** @hide */ 666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public double getLatitude() { 676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return mLatitude; 686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** @hide */ 716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public double getLongitude() { 726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return mLongitude; 736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly /** @hide */ 766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public float getRadius() { 776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return mRadius; 786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static void checkRadius(float radius) { 816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (radius <= 0) { 826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly throw new IllegalArgumentException("invalid radius: " + radius); 836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static void checkLatLong(double latitude, double longitude) { 876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (latitude > 90.0 || latitude < -90.0) { 886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly throw new IllegalArgumentException("invalid latitude: " + latitude); 896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (longitude > 180.0 || longitude < -180.0) { 916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly throw new IllegalArgumentException("invalid longitude: " + longitude); 926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static void checkType(int type) { 966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (type != TYPE_HORIZONTAL_CIRCLE) { 976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly throw new IllegalArgumentException("invalid type: " + type); 986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public static final Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() { 1026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public Geofence createFromParcel(Parcel in) { 1046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly int type = in.readInt(); 1056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly double latitude = in.readDouble(); 1066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly double longitude = in.readDouble(); 1076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly float radius = in.readFloat(); 1086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly checkType(type); 1096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return Geofence.createCircle(latitude, longitude, radius); 1106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public Geofence[] newArray(int size) { 1136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return new Geofence[size]; 1146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly }; 1166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public int describeContents() { 1196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return 0; 1206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public void writeToParcel(Parcel parcel, int flags) { 1246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly parcel.writeInt(mType); 1256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly parcel.writeDouble(mLatitude); 1266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly parcel.writeDouble(mLongitude); 1276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly parcel.writeFloat(mRadius); 1286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly private static String typeToString(int type) { 1316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly switch (type) { 1326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly case TYPE_HORIZONTAL_CIRCLE: 1336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return "CIRCLE"; 1346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly default: 1356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly checkType(type); 1366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return null; 1376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public String toString() { 1426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return String.format("Geofence[%s %.6f, %.6f %.0fm]", 1436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly typeToString(mType), mLatitude, mLongitude, mRadius); 1446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public int hashCode() { 1486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly final int prime = 31; 1496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly int result = 1; 1506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly long temp; 1516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly temp = Double.doubleToLongBits(mLatitude); 1526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly result = prime * result + (int) (temp ^ (temp >>> 32)); 1536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly temp = Double.doubleToLongBits(mLongitude); 1546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly result = prime * result + (int) (temp ^ (temp >>> 32)); 1556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly result = prime * result + Float.floatToIntBits(mRadius); 1566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly result = prime * result + mType; 1576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return result; 1586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly 1604e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly /** 1614e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly * Two geofences are equal if they have identical properties. 1624e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly */ 1636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly @Override 1646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly public boolean equals(Object obj) { 1656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (this == obj) 1666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return true; 1676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (obj == null) 1686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return false; 1696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (!(obj instanceof Geofence)) 1706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return false; 1716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly Geofence other = (Geofence) obj; 1726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (mRadius != other.mRadius) 1736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return false; 1746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (mLatitude != other.mLatitude) 1756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return false; 1766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (mLongitude != other.mLongitude) 1776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return false; 1786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly if (mType != other.mType) 1796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return false; 1806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly return true; 1816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly } 1826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly} 183