1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 package org.mozilla.mozstumbler.service.stumblerthread.scanners;
6 
7 import android.location.Location;
8 import android.util.Log;
9 import org.mozilla.mozstumbler.service.AppGlobals;
10 import org.mozilla.mozstumbler.service.Prefs;
11 
12 public final class LocationBlockList {
13     private static final String LOG_TAG = AppGlobals.makeLogTag(LocationBlockList.class.getSimpleName());
14     private static final double MAX_ALTITUDE = 8848;      // Mount Everest's altitude in meters
15     private static final double MIN_ALTITUDE = -418;      // Dead Sea's altitude in meters
16     private static final float MAX_SPEED = 340.29f;   // Mach 1 in meters/second
17     private static final float MIN_ACCURACY = 500;       // meter radius
18     private static final long MIN_TIMESTAMP = 946684801; // 2000-01-01 00:00:01
19     private static final double GEOFENCE_RADIUS = 0.01;      // .01 degrees is approximately 1km
20     private static final long MILLISECONDS_PER_DAY = 86400000;
21 
22     private Location mBlockedLocation;
23     private boolean mGeofencingEnabled;
24     private boolean mIsGeofenced = false;
25 
LocationBlockList()26     public LocationBlockList() {
27         updateBlocks();
28     }
29 
updateBlocks()30     public void updateBlocks()    {
31         Prefs prefs = Prefs.getInstanceWithoutContext();
32         if (prefs == null) {
33             return;
34         }
35         mBlockedLocation = prefs.getGeofenceLocation();
36         mGeofencingEnabled = prefs.getGeofenceEnabled();
37     }
38 
contains(Location location)39     public boolean contains(Location location) {
40         final float inaccuracy = location.getAccuracy();
41         final double altitude = location.getAltitude();
42         final float bearing = location.getBearing();
43         final double latitude = location.getLatitude();
44         final double longitude = location.getLongitude();
45         final float speed = location.getSpeed();
46         final long timestamp = location.getTime();
47         final long tomorrow = System.currentTimeMillis() + MILLISECONDS_PER_DAY;
48 
49         boolean block = false;
50         mIsGeofenced = false;
51 
52         if (latitude == 0 && longitude == 0) {
53             block = true;
54             Log.w(LOG_TAG, "Bogus latitude,longitude: 0,0");
55         } else {
56             if (latitude < -90 || latitude > 90) {
57                 block = true;
58                 Log.w(LOG_TAG, "Bogus latitude: " + latitude);
59             }
60 
61             if (longitude < -180 || longitude > 180) {
62                 block = true;
63                 Log.w(LOG_TAG, "Bogus longitude: " + longitude);
64             }
65         }
66 
67         if (location.hasAccuracy() && (inaccuracy < 0 || inaccuracy > MIN_ACCURACY)) {
68             block = true;
69             Log.w(LOG_TAG, "Insufficient accuracy: " + inaccuracy + " meters");
70         }
71 
72         if (location.hasAltitude() && (altitude < MIN_ALTITUDE || altitude > MAX_ALTITUDE)) {
73             block = true;
74             Log.w(LOG_TAG, "Bogus altitude: " + altitude + " meters");
75         }
76 
77         if (location.hasBearing() && (bearing < 0 || bearing > 360)) {
78             block = true;
79             Log.w(LOG_TAG, "Bogus bearing: " + bearing + " degrees");
80         }
81 
82         if (location.hasSpeed() && (speed < 0 || speed > MAX_SPEED)) {
83             block = true;
84             Log.w(LOG_TAG, "Bogus speed: " + speed + " meters/second");
85         }
86 
87         if (timestamp < MIN_TIMESTAMP || timestamp > tomorrow) {
88             block = true;
89             Log.w(LOG_TAG, "Bogus timestamp: " + timestamp);
90         }
91 
92         if (mGeofencingEnabled &&
93             Math.abs(location.getLatitude() - mBlockedLocation.getLatitude()) < GEOFENCE_RADIUS &&
94             Math.abs(location.getLongitude() - mBlockedLocation.getLongitude()) < GEOFENCE_RADIUS) {
95             block = true;
96             mIsGeofenced = true;
97         }
98 
99         return block;
100     }
101 
isGeofenced()102     public boolean isGeofenced() {
103         return mIsGeofenced;
104     }
105 }
106