1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.location; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 /** 24 * Represents a geographical boundary, also known as a geofence. 25 * 26 * <p>Currently only circular geofences are supported and they do not support altitude changes. 27 * 28 * @hide 29 */ 30 public final class Geofence implements Parcelable { 31 /** @hide */ 32 public static final int TYPE_HORIZONTAL_CIRCLE = 1; 33 34 private final int mType; 35 private final double mLatitude; 36 private final double mLongitude; 37 private final float mRadius; 38 39 /** 40 * Create a circular geofence (on a flat, horizontal plane). 41 * 42 * @param latitude latitude in degrees, between -90 and +90 inclusive 43 * @param longitude longitude in degrees, between -180 and +180 inclusive 44 * @param radius radius in meters 45 * @return a new geofence 46 * @throws IllegalArgumentException if any parameters are out of range 47 */ createCircle(double latitude, double longitude, float radius)48 public static Geofence createCircle(double latitude, double longitude, float radius) { 49 return new Geofence(latitude, longitude, radius); 50 } 51 Geofence(double latitude, double longitude, float radius)52 private Geofence(double latitude, double longitude, float radius) { 53 checkRadius(radius); 54 checkLatLong(latitude, longitude); 55 mType = TYPE_HORIZONTAL_CIRCLE; 56 mLatitude = latitude; 57 mLongitude = longitude; 58 mRadius = radius; 59 } 60 61 /** @hide */ getType()62 public int getType() { 63 return mType; 64 } 65 66 /** @hide */ getLatitude()67 public double getLatitude() { 68 return mLatitude; 69 } 70 71 /** @hide */ getLongitude()72 public double getLongitude() { 73 return mLongitude; 74 } 75 76 /** @hide */ getRadius()77 public float getRadius() { 78 return mRadius; 79 } 80 checkRadius(float radius)81 private static void checkRadius(float radius) { 82 if (radius <= 0) { 83 throw new IllegalArgumentException("invalid radius: " + radius); 84 } 85 } 86 checkLatLong(double latitude, double longitude)87 private static void checkLatLong(double latitude, double longitude) { 88 if (latitude > 90.0 || latitude < -90.0) { 89 throw new IllegalArgumentException("invalid latitude: " + latitude); 90 } 91 if (longitude > 180.0 || longitude < -180.0) { 92 throw new IllegalArgumentException("invalid longitude: " + longitude); 93 } 94 } 95 checkType(int type)96 private static void checkType(int type) { 97 if (type != TYPE_HORIZONTAL_CIRCLE) { 98 throw new IllegalArgumentException("invalid type: " + type); 99 } 100 } 101 102 @UnsupportedAppUsage 103 public static final @android.annotation.NonNull Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() { 104 @Override 105 public Geofence createFromParcel(Parcel in) { 106 int type = in.readInt(); 107 double latitude = in.readDouble(); 108 double longitude = in.readDouble(); 109 float radius = in.readFloat(); 110 checkType(type); 111 return Geofence.createCircle(latitude, longitude, radius); 112 } 113 @Override 114 public Geofence[] newArray(int size) { 115 return new Geofence[size]; 116 } 117 }; 118 119 @Override describeContents()120 public int describeContents() { 121 return 0; 122 } 123 124 @Override writeToParcel(Parcel parcel, int flags)125 public void writeToParcel(Parcel parcel, int flags) { 126 parcel.writeInt(mType); 127 parcel.writeDouble(mLatitude); 128 parcel.writeDouble(mLongitude); 129 parcel.writeFloat(mRadius); 130 } 131 typeToString(int type)132 private static String typeToString(int type) { 133 switch (type) { 134 case TYPE_HORIZONTAL_CIRCLE: 135 return "CIRCLE"; 136 default: 137 checkType(type); 138 return null; 139 } 140 } 141 142 @Override toString()143 public String toString() { 144 return String.format("Geofence[%s %.6f, %.6f %.0fm]", 145 typeToString(mType), mLatitude, mLongitude, mRadius); 146 } 147 148 @Override hashCode()149 public int hashCode() { 150 final int prime = 31; 151 int result = 1; 152 long temp; 153 temp = Double.doubleToLongBits(mLatitude); 154 result = prime * result + (int) (temp ^ (temp >>> 32)); 155 temp = Double.doubleToLongBits(mLongitude); 156 result = prime * result + (int) (temp ^ (temp >>> 32)); 157 result = prime * result + Float.floatToIntBits(mRadius); 158 result = prime * result + mType; 159 return result; 160 } 161 162 /** 163 * Two geofences are equal if they have identical properties. 164 */ 165 @Override equals(Object obj)166 public boolean equals(Object obj) { 167 if (this == obj) 168 return true; 169 if (obj == null) 170 return false; 171 if (!(obj instanceof Geofence)) 172 return false; 173 Geofence other = (Geofence) obj; 174 if (mRadius != other.mRadius) 175 return false; 176 if (mLatitude != other.mLatitude) 177 return false; 178 if (mLongitude != other.mLongitude) 179 return false; 180 if (mType != other.mType) 181 return false; 182 return true; 183 } 184 } 185