1 package com.android.server.location; 2 3 import android.location.IGpsGeofenceHardware; 4 import android.util.Log; 5 import android.util.SparseArray; 6 7 import com.android.internal.annotations.GuardedBy; 8 import com.android.internal.annotations.VisibleForTesting; 9 10 /** 11 * Manages GNSS Geofence operations. 12 */ 13 class GnssGeofenceProvider extends IGpsGeofenceHardware.Stub { 14 15 private static final String TAG = "GnssGeofenceProvider"; 16 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 17 18 /** Holds the parameters of a geofence. */ 19 private static class GeofenceEntry { 20 public int geofenceId; 21 public double latitude; 22 public double longitude; 23 public double radius; 24 public int lastTransition; 25 public int monitorTransitions; 26 public int notificationResponsiveness; 27 public int unknownTimer; 28 public boolean paused; 29 } 30 31 private final Object mLock = new Object(); 32 @GuardedBy("mLock") 33 private final GnssGeofenceProviderNative mNative; 34 @GuardedBy("mLock") 35 private final SparseArray<GeofenceEntry> mGeofenceEntries = new SparseArray<>(); 36 GnssGeofenceProvider()37 GnssGeofenceProvider() { 38 this(new GnssGeofenceProviderNative()); 39 } 40 41 @VisibleForTesting GnssGeofenceProvider(GnssGeofenceProviderNative gnssGeofenceProviderNative)42 GnssGeofenceProvider(GnssGeofenceProviderNative gnssGeofenceProviderNative) { 43 mNative = gnssGeofenceProviderNative; 44 } 45 resumeIfStarted()46 void resumeIfStarted() { 47 if (DEBUG) { 48 Log.d(TAG, "resumeIfStarted"); 49 } 50 synchronized (mLock) { 51 for (int i = 0; i < mGeofenceEntries.size(); i++) { 52 GeofenceEntry entry = mGeofenceEntries.valueAt(i); 53 boolean added = mNative.addGeofence(entry.geofenceId, entry.latitude, 54 entry.longitude, 55 entry.radius, 56 entry.lastTransition, entry.monitorTransitions, 57 entry.notificationResponsiveness, entry.unknownTimer); 58 if (added && entry.paused) { 59 mNative.pauseGeofence(entry.geofenceId); 60 } 61 } 62 } 63 } 64 65 @Override isHardwareGeofenceSupported()66 public boolean isHardwareGeofenceSupported() { 67 synchronized (mLock) { 68 return mNative.isGeofenceSupported(); 69 } 70 } 71 72 @Override addCircularHardwareGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer)73 public boolean addCircularHardwareGeofence(int geofenceId, double latitude, 74 double longitude, double radius, int lastTransition, int monitorTransitions, 75 int notificationResponsiveness, int unknownTimer) { 76 synchronized (mLock) { 77 boolean added = mNative.addGeofence(geofenceId, latitude, longitude, radius, 78 lastTransition, monitorTransitions, notificationResponsiveness, 79 unknownTimer); 80 if (added) { 81 GeofenceEntry entry = new GeofenceEntry(); 82 entry.geofenceId = geofenceId; 83 entry.latitude = latitude; 84 entry.longitude = longitude; 85 entry.radius = radius; 86 entry.lastTransition = lastTransition; 87 entry.monitorTransitions = monitorTransitions; 88 entry.notificationResponsiveness = notificationResponsiveness; 89 entry.unknownTimer = unknownTimer; 90 mGeofenceEntries.put(geofenceId, entry); 91 } 92 return added; 93 } 94 } 95 96 @Override removeHardwareGeofence(int geofenceId)97 public boolean removeHardwareGeofence(int geofenceId) { 98 synchronized (mLock) { 99 boolean removed = mNative.removeGeofence(geofenceId); 100 if (removed) { 101 mGeofenceEntries.remove(geofenceId); 102 } 103 return removed; 104 } 105 } 106 107 @Override pauseHardwareGeofence(int geofenceId)108 public boolean pauseHardwareGeofence(int geofenceId) { 109 synchronized (mLock) { 110 boolean paused = mNative.pauseGeofence(geofenceId); 111 if (paused) { 112 GeofenceEntry entry = mGeofenceEntries.get(geofenceId); 113 if (entry != null) { 114 entry.paused = true; 115 } 116 } 117 return paused; 118 } 119 } 120 121 @Override resumeHardwareGeofence(int geofenceId, int monitorTransitions)122 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransitions) { 123 synchronized (mLock) { 124 boolean resumed = mNative.resumeGeofence(geofenceId, monitorTransitions); 125 if (resumed) { 126 GeofenceEntry entry = mGeofenceEntries.get(geofenceId); 127 if (entry != null) { 128 entry.paused = false; 129 entry.monitorTransitions = monitorTransitions; 130 } 131 } 132 return resumed; 133 } 134 } 135 136 @VisibleForTesting 137 static class GnssGeofenceProviderNative { isGeofenceSupported()138 public boolean isGeofenceSupported() { 139 return native_is_geofence_supported(); 140 } 141 addGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer)142 public boolean addGeofence(int geofenceId, double latitude, double longitude, double radius, 143 int lastTransition, int monitorTransitions, int notificationResponsiveness, 144 int unknownTimer) { 145 return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition, 146 monitorTransitions, notificationResponsiveness, unknownTimer); 147 } 148 removeGeofence(int geofenceId)149 public boolean removeGeofence(int geofenceId) { 150 return native_remove_geofence(geofenceId); 151 } 152 resumeGeofence(int geofenceId, int transitions)153 public boolean resumeGeofence(int geofenceId, int transitions) { 154 return native_resume_geofence(geofenceId, transitions); 155 } 156 pauseGeofence(int geofenceId)157 public boolean pauseGeofence(int geofenceId) { 158 return native_pause_geofence(geofenceId); 159 } 160 } 161 native_is_geofence_supported()162 private static native boolean native_is_geofence_supported(); 163 native_add_geofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsivenes, int unknownTimer)164 private static native boolean native_add_geofence(int geofenceId, double latitude, 165 double longitude, double radius, int lastTransition, int monitorTransitions, 166 int notificationResponsivenes, int unknownTimer); 167 native_remove_geofence(int geofenceId)168 private static native boolean native_remove_geofence(int geofenceId); 169 native_resume_geofence(int geofenceId, int transitions)170 private static native boolean native_resume_geofence(int geofenceId, int transitions); 171 native_pause_geofence(int geofenceId)172 private static native boolean native_pause_geofence(int geofenceId); 173 } 174