Loading services/core/java/com/android/server/location/GnssGeofenceProvider.java 0 → 100644 +188 −0 Original line number Diff line number Diff line package com.android.server.location; import android.location.IGpsGeofenceHardware; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Manages GNSS Geofence operations. */ class GnssGeofenceProvider extends IGpsGeofenceHardware.Stub { private static final String TAG = "GnssGeofenceProvider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); /** Holds the parameters of a geofence. */ private static class GeofenceEntry { public int geofenceId; public double latitude; public double longitude; public double radius; public int lastTransition; public int monitorTransitions; public int notificationResponsiveness; public int unknownTimer; public boolean paused; } private final GnssGeofenceProviderNative mNative; private final SparseArray<GeofenceEntry> mGeofenceEntries = new SparseArray<>(); private final Handler mHandler; GnssGeofenceProvider(Looper looper) { this(looper, new GnssGeofenceProviderNative()); } @VisibleForTesting GnssGeofenceProvider(Looper looper, GnssGeofenceProviderNative gnssGeofenceProviderNative) { mHandler = new Handler(looper); mNative = gnssGeofenceProviderNative; } // TODO(b/37460011): use this method in HAL death recovery. void resumeIfStarted() { if (DEBUG) { Log.d(TAG, "resumeIfStarted"); } mHandler.post(() -> { for (int i = 0; i < mGeofenceEntries.size(); i++) { GeofenceEntry entry = mGeofenceEntries.valueAt(i); boolean added = mNative.addGeofence(entry.geofenceId, entry.latitude, entry.longitude, entry.radius, entry.lastTransition, entry.monitorTransitions, entry.notificationResponsiveness, entry.unknownTimer); if (added && entry.paused) { mNative.pauseGeofence(entry.geofenceId); } } }); } private boolean runOnHandlerThread(Callable<Boolean> callable) { FutureTask<Boolean> futureTask = new FutureTask<>(callable); mHandler.post(futureTask); try { return futureTask.get(); } catch (InterruptedException | ExecutionException e) { Log.e(TAG, "Failed running callable.", e); } return false; } @Override public boolean isHardwareGeofenceSupported() { return runOnHandlerThread(mNative::isGeofenceSupported); } @Override public boolean addCircularHardwareGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer) { return runOnHandlerThread(() -> { boolean added = mNative.addGeofence(geofenceId, latitude, longitude, radius, lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); if (added) { GeofenceEntry entry = new GeofenceEntry(); entry.geofenceId = geofenceId; entry.latitude = latitude; entry.longitude = longitude; entry.radius = radius; entry.lastTransition = lastTransition; entry.monitorTransitions = monitorTransitions; entry.notificationResponsiveness = notificationResponsiveness; entry.unknownTimer = unknownTimer; mGeofenceEntries.put(geofenceId, entry); } return added; }); } @Override public boolean removeHardwareGeofence(int geofenceId) { return runOnHandlerThread(() -> { boolean removed = mNative.removeGeofence(geofenceId); if (removed) { mGeofenceEntries.remove(geofenceId); } return removed; }); } @Override public boolean pauseHardwareGeofence(int geofenceId) { return runOnHandlerThread(() -> { boolean paused = mNative.pauseGeofence(geofenceId); if (paused) { GeofenceEntry entry = mGeofenceEntries.get(geofenceId); if (entry != null) { entry.paused = true; } } return paused; }); } @Override public boolean resumeHardwareGeofence(int geofenceId, int monitorTransitions) { return runOnHandlerThread(() -> { boolean resumed = mNative.resumeGeofence(geofenceId, monitorTransitions); if (resumed) { GeofenceEntry entry = mGeofenceEntries.get(geofenceId); if (entry != null) { entry.paused = false; entry.monitorTransitions = monitorTransitions; } } return resumed; }); } @VisibleForTesting static class GnssGeofenceProviderNative { public boolean isGeofenceSupported() { return native_is_geofence_supported(); } public boolean addGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer) { return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); } public boolean removeGeofence(int geofenceId) { return native_remove_geofence(geofenceId); } public boolean resumeGeofence(int geofenceId, int transitions) { return native_resume_geofence(geofenceId, transitions); } public boolean pauseGeofence(int geofenceId) { return native_pause_geofence(geofenceId); } } private static native boolean native_is_geofence_supported(); private static native boolean native_add_geofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsivenes, int unknownTimer); private static native boolean native_remove_geofence(int geofenceId); private static native boolean native_resume_geofence(int geofenceId, int transitions); private static native boolean native_pause_geofence(int geofenceId); } services/core/java/com/android/server/location/GnssLocationProvider.java +3 −39 Original line number Diff line number Diff line Loading @@ -419,6 +419,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt private final LocationChangeListener mFusedLocationListener = new FusedLocationListener(); private final NtpTimeHelper mNtpTimeHelper; private final GnssBatchingProvider mGnssBatchingProvider; private final GnssGeofenceProvider mGnssGeofenceProvider; // Handler for processing events private Handler mHandler; Loading Loading @@ -493,7 +494,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt } public IGpsGeofenceHardware getGpsGeofenceProxy() { return mGpsGeofenceBinder; return mGnssGeofenceProvider; } public GnssMeasurementsProvider getGnssMeasurementsProvider() { Loading Loading @@ -887,6 +888,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt looper, this); mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist); mGnssBatchingProvider = new GnssBatchingProvider(); mGnssGeofenceProvider = new GnssGeofenceProvider(looper); } /** Loading Loading @@ -1501,31 +1503,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt } } private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() { public boolean isHardwareGeofenceSupported() { return native_is_geofence_supported(); } public boolean addCircularHardwareGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer) { return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); } public boolean removeHardwareGeofence(int geofenceId) { return native_remove_geofence(geofenceId); } public boolean pauseHardwareGeofence(int geofenceId) { return native_pause_geofence(geofenceId); } public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) { return native_resume_geofence(geofenceId, monitorTransition); } }; private boolean deleteAidingData(Bundle extras) { int flags; Loading Loading @@ -2813,19 +2790,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt private native void native_update_network_state(boolean connected, int type, boolean roaming, boolean available, String extraInfo, String defaultAPN); // Hardware Geofence support. private static native boolean native_is_geofence_supported(); private static native boolean native_add_geofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsivenes, int unknownTimer); private static native boolean native_remove_geofence(int geofenceId); private static native boolean native_resume_geofence(int geofenceId, int transitions); private static native boolean native_pause_geofence(int geofenceId); // Gps Hal measurements support. private static native boolean native_is_measurement_supported(); Loading services/core/jni/com_android_server_location_GnssLocationProvider.cpp +28 −19 Original line number Diff line number Diff line Loading @@ -1745,12 +1745,12 @@ static void android_location_GnssLocationProvider_update_network_state(JNIEnv* e } } static jboolean android_location_GnssLocationProvider_is_geofence_supported( static jboolean android_location_GnssGeofenceProvider_is_geofence_supported( JNIEnv* /* env */, jobject /* obj */) { return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE; } static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_add_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId, jdouble latitude, jdouble longitude, jdouble radius, jint last_transition, jint monitor_transition, jint notification_responsiveness, jint unknown_timer) { Loading @@ -1766,7 +1766,7 @@ static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* en return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_remove_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId) { if (gnssGeofencingIface != nullptr) { auto result = gnssGeofencingIface->removeGeofence(geofenceId); Loading @@ -1777,7 +1777,7 @@ static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_pause_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId) { if (gnssGeofencingIface != nullptr) { auto result = gnssGeofencingIface->pauseGeofence(geofenceId); Loading @@ -1788,7 +1788,7 @@ static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_resume_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId, jint monitor_transition) { if (gnssGeofencingIface != nullptr) { auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition); Loading Loading @@ -2178,20 +2178,6 @@ static const JNINativeMethod sMethods[] = { {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)}, {"native_is_geofence_supported", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_is_geofence_supported)}, {"native_add_geofence", "(IDDDIIII)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_add_geofence)}, {"native_remove_geofence", "(I)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_remove_geofence)}, {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_pause_geofence)}, {"native_resume_geofence", "(II)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_resume_geofence)}, {"native_is_measurement_supported", "()Z", reinterpret_cast<void *>( Loading Loading @@ -2265,12 +2251,35 @@ static const JNINativeMethod sMethodsBatching[] = { reinterpret_cast<void *>(android_location_GnssBatchingProvider_cleanup_batching)}, }; static const JNINativeMethod sGeofenceMethods[] = { /* name, signature, funcPtr */ {"native_is_geofence_supported", "()Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_is_geofence_supported)}, {"native_add_geofence", "(IDDDIIII)Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_add_geofence)}, {"native_remove_geofence", "(I)Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_remove_geofence)}, {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>( android_location_GnssGeofenceProvider_pause_geofence)}, {"native_resume_geofence", "(II)Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_resume_geofence)}, }; int register_android_server_location_GnssLocationProvider(JNIEnv* env) { jniRegisterNativeMethods( env, "com/android/server/location/GnssBatchingProvider", sMethodsBatching, NELEM(sMethodsBatching)); jniRegisterNativeMethods( env, "com/android/server/location/GnssGeofenceProvider", sGeofenceMethods, NELEM(sGeofenceMethods)); return jniRegisterNativeMethods( env, "com/android/server/location/GnssLocationProvider", Loading services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java 0 → 100644 +121 −0 Original line number Diff line number Diff line package com.android.server.location; import static org.mockito.Matchers.anyDouble; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.Looper; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; /** * Unit tests for {@link GnssGeofenceProvider}. */ @RunWith(FrameworkRobolectricTestRunner.class) @Config( manifest = Config.NONE, sdk = 27 ) @SystemLoaderPackages({"com.android.server.location"}) @Presubmit public class GnssGeofenceProviderTest { private static final int GEOFENCE_ID = 12345; private static final double LATITUDE = 10.0; private static final double LONGITUDE = 20.0; private static final double RADIUS = 5.0; private static final int LAST_TRANSITION = 0; private static final int MONITOR_TRANSITIONS = 0; private static final int NOTIFICATION_RESPONSIVENESS = 0; private static final int UNKNOWN_TIMER = 0; @Mock private GnssGeofenceProvider.GnssGeofenceProviderNative mMockNative; private GnssGeofenceProvider mTestProvider; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mMockNative.addGeofence(anyInt(), anyDouble(), anyDouble(), anyDouble(), anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(true); when(mMockNative.pauseGeofence(anyInt())).thenReturn(true); when(mMockNative.removeGeofence(anyInt())).thenReturn(true); when(mMockNative.resumeGeofence(anyInt(), anyInt())).thenReturn(true); mTestProvider = new GnssGeofenceProvider(Looper.myLooper(), mMockNative); mTestProvider.addCircularHardwareGeofence(GEOFENCE_ID, LATITUDE, LONGITUDE, RADIUS, LAST_TRANSITION, MONITOR_TRANSITIONS, NOTIFICATION_RESPONSIVENESS, UNKNOWN_TIMER); } @Test public void addGeofence_nativeAdded() { verify(mMockNative).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); } @Test public void pauseGeofence_nativePaused() { mTestProvider.pauseHardwareGeofence(GEOFENCE_ID); verify(mMockNative).pauseGeofence(eq(GEOFENCE_ID)); } @Test public void removeGeofence_nativeRemoved() { mTestProvider.removeHardwareGeofence(GEOFENCE_ID); verify(mMockNative).removeGeofence(eq(GEOFENCE_ID)); } @Test public void resumeGeofence_nativeResumed() { mTestProvider.pauseHardwareGeofence(GEOFENCE_ID); mTestProvider.resumeHardwareGeofence(GEOFENCE_ID, MONITOR_TRANSITIONS); verify(mMockNative).resumeGeofence(eq(GEOFENCE_ID), eq(MONITOR_TRANSITIONS)); } @Test public void addGeofence_restart_added() throws RemoteException { mTestProvider.resumeIfStarted(); verify(mMockNative, times(2)).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); } @Test public void removeGeofence_restart_notAdded() throws RemoteException { mTestProvider.removeHardwareGeofence(GEOFENCE_ID); mTestProvider.resumeIfStarted(); verify(mMockNative, times(1)).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); } @Test public void pauseGeofence_restart_paused() throws RemoteException { mTestProvider.pauseHardwareGeofence(GEOFENCE_ID); mTestProvider.resumeIfStarted(); verify(mMockNative, times(2)).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); verify(mMockNative, times(2)).pauseGeofence(eq(GEOFENCE_ID)); } } Loading
services/core/java/com/android/server/location/GnssGeofenceProvider.java 0 → 100644 +188 −0 Original line number Diff line number Diff line package com.android.server.location; import android.location.IGpsGeofenceHardware; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Manages GNSS Geofence operations. */ class GnssGeofenceProvider extends IGpsGeofenceHardware.Stub { private static final String TAG = "GnssGeofenceProvider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); /** Holds the parameters of a geofence. */ private static class GeofenceEntry { public int geofenceId; public double latitude; public double longitude; public double radius; public int lastTransition; public int monitorTransitions; public int notificationResponsiveness; public int unknownTimer; public boolean paused; } private final GnssGeofenceProviderNative mNative; private final SparseArray<GeofenceEntry> mGeofenceEntries = new SparseArray<>(); private final Handler mHandler; GnssGeofenceProvider(Looper looper) { this(looper, new GnssGeofenceProviderNative()); } @VisibleForTesting GnssGeofenceProvider(Looper looper, GnssGeofenceProviderNative gnssGeofenceProviderNative) { mHandler = new Handler(looper); mNative = gnssGeofenceProviderNative; } // TODO(b/37460011): use this method in HAL death recovery. void resumeIfStarted() { if (DEBUG) { Log.d(TAG, "resumeIfStarted"); } mHandler.post(() -> { for (int i = 0; i < mGeofenceEntries.size(); i++) { GeofenceEntry entry = mGeofenceEntries.valueAt(i); boolean added = mNative.addGeofence(entry.geofenceId, entry.latitude, entry.longitude, entry.radius, entry.lastTransition, entry.monitorTransitions, entry.notificationResponsiveness, entry.unknownTimer); if (added && entry.paused) { mNative.pauseGeofence(entry.geofenceId); } } }); } private boolean runOnHandlerThread(Callable<Boolean> callable) { FutureTask<Boolean> futureTask = new FutureTask<>(callable); mHandler.post(futureTask); try { return futureTask.get(); } catch (InterruptedException | ExecutionException e) { Log.e(TAG, "Failed running callable.", e); } return false; } @Override public boolean isHardwareGeofenceSupported() { return runOnHandlerThread(mNative::isGeofenceSupported); } @Override public boolean addCircularHardwareGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer) { return runOnHandlerThread(() -> { boolean added = mNative.addGeofence(geofenceId, latitude, longitude, radius, lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); if (added) { GeofenceEntry entry = new GeofenceEntry(); entry.geofenceId = geofenceId; entry.latitude = latitude; entry.longitude = longitude; entry.radius = radius; entry.lastTransition = lastTransition; entry.monitorTransitions = monitorTransitions; entry.notificationResponsiveness = notificationResponsiveness; entry.unknownTimer = unknownTimer; mGeofenceEntries.put(geofenceId, entry); } return added; }); } @Override public boolean removeHardwareGeofence(int geofenceId) { return runOnHandlerThread(() -> { boolean removed = mNative.removeGeofence(geofenceId); if (removed) { mGeofenceEntries.remove(geofenceId); } return removed; }); } @Override public boolean pauseHardwareGeofence(int geofenceId) { return runOnHandlerThread(() -> { boolean paused = mNative.pauseGeofence(geofenceId); if (paused) { GeofenceEntry entry = mGeofenceEntries.get(geofenceId); if (entry != null) { entry.paused = true; } } return paused; }); } @Override public boolean resumeHardwareGeofence(int geofenceId, int monitorTransitions) { return runOnHandlerThread(() -> { boolean resumed = mNative.resumeGeofence(geofenceId, monitorTransitions); if (resumed) { GeofenceEntry entry = mGeofenceEntries.get(geofenceId); if (entry != null) { entry.paused = false; entry.monitorTransitions = monitorTransitions; } } return resumed; }); } @VisibleForTesting static class GnssGeofenceProviderNative { public boolean isGeofenceSupported() { return native_is_geofence_supported(); } public boolean addGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer) { return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); } public boolean removeGeofence(int geofenceId) { return native_remove_geofence(geofenceId); } public boolean resumeGeofence(int geofenceId, int transitions) { return native_resume_geofence(geofenceId, transitions); } public boolean pauseGeofence(int geofenceId) { return native_pause_geofence(geofenceId); } } private static native boolean native_is_geofence_supported(); private static native boolean native_add_geofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsivenes, int unknownTimer); private static native boolean native_remove_geofence(int geofenceId); private static native boolean native_resume_geofence(int geofenceId, int transitions); private static native boolean native_pause_geofence(int geofenceId); }
services/core/java/com/android/server/location/GnssLocationProvider.java +3 −39 Original line number Diff line number Diff line Loading @@ -419,6 +419,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt private final LocationChangeListener mFusedLocationListener = new FusedLocationListener(); private final NtpTimeHelper mNtpTimeHelper; private final GnssBatchingProvider mGnssBatchingProvider; private final GnssGeofenceProvider mGnssGeofenceProvider; // Handler for processing events private Handler mHandler; Loading Loading @@ -493,7 +494,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt } public IGpsGeofenceHardware getGpsGeofenceProxy() { return mGpsGeofenceBinder; return mGnssGeofenceProvider; } public GnssMeasurementsProvider getGnssMeasurementsProvider() { Loading Loading @@ -887,6 +888,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt looper, this); mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist); mGnssBatchingProvider = new GnssBatchingProvider(); mGnssGeofenceProvider = new GnssGeofenceProvider(looper); } /** Loading Loading @@ -1501,31 +1503,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt } } private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() { public boolean isHardwareGeofenceSupported() { return native_is_geofence_supported(); } public boolean addCircularHardwareGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer) { return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); } public boolean removeHardwareGeofence(int geofenceId) { return native_remove_geofence(geofenceId); } public boolean pauseHardwareGeofence(int geofenceId) { return native_pause_geofence(geofenceId); } public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) { return native_resume_geofence(geofenceId, monitorTransition); } }; private boolean deleteAidingData(Bundle extras) { int flags; Loading Loading @@ -2813,19 +2790,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt private native void native_update_network_state(boolean connected, int type, boolean roaming, boolean available, String extraInfo, String defaultAPN); // Hardware Geofence support. private static native boolean native_is_geofence_supported(); private static native boolean native_add_geofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsivenes, int unknownTimer); private static native boolean native_remove_geofence(int geofenceId); private static native boolean native_resume_geofence(int geofenceId, int transitions); private static native boolean native_pause_geofence(int geofenceId); // Gps Hal measurements support. private static native boolean native_is_measurement_supported(); Loading
services/core/jni/com_android_server_location_GnssLocationProvider.cpp +28 −19 Original line number Diff line number Diff line Loading @@ -1745,12 +1745,12 @@ static void android_location_GnssLocationProvider_update_network_state(JNIEnv* e } } static jboolean android_location_GnssLocationProvider_is_geofence_supported( static jboolean android_location_GnssGeofenceProvider_is_geofence_supported( JNIEnv* /* env */, jobject /* obj */) { return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE; } static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_add_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId, jdouble latitude, jdouble longitude, jdouble radius, jint last_transition, jint monitor_transition, jint notification_responsiveness, jint unknown_timer) { Loading @@ -1766,7 +1766,7 @@ static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* en return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_remove_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId) { if (gnssGeofencingIface != nullptr) { auto result = gnssGeofencingIface->removeGeofence(geofenceId); Loading @@ -1777,7 +1777,7 @@ static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_pause_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId) { if (gnssGeofencingIface != nullptr) { auto result = gnssGeofencingIface->pauseGeofence(geofenceId); Loading @@ -1788,7 +1788,7 @@ static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */, static jboolean android_location_GnssGeofenceProvider_resume_geofence(JNIEnv* /* env */, jobject /* obj */, jint geofenceId, jint monitor_transition) { if (gnssGeofencingIface != nullptr) { auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition); Loading Loading @@ -2178,20 +2178,6 @@ static const JNINativeMethod sMethods[] = { {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)}, {"native_is_geofence_supported", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_is_geofence_supported)}, {"native_add_geofence", "(IDDDIIII)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_add_geofence)}, {"native_remove_geofence", "(I)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_remove_geofence)}, {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_pause_geofence)}, {"native_resume_geofence", "(II)Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_resume_geofence)}, {"native_is_measurement_supported", "()Z", reinterpret_cast<void *>( Loading Loading @@ -2265,12 +2251,35 @@ static const JNINativeMethod sMethodsBatching[] = { reinterpret_cast<void *>(android_location_GnssBatchingProvider_cleanup_batching)}, }; static const JNINativeMethod sGeofenceMethods[] = { /* name, signature, funcPtr */ {"native_is_geofence_supported", "()Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_is_geofence_supported)}, {"native_add_geofence", "(IDDDIIII)Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_add_geofence)}, {"native_remove_geofence", "(I)Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_remove_geofence)}, {"native_pause_geofence", "(I)Z", reinterpret_cast<void *>( android_location_GnssGeofenceProvider_pause_geofence)}, {"native_resume_geofence", "(II)Z", reinterpret_cast<void *>(android_location_GnssGeofenceProvider_resume_geofence)}, }; int register_android_server_location_GnssLocationProvider(JNIEnv* env) { jniRegisterNativeMethods( env, "com/android/server/location/GnssBatchingProvider", sMethodsBatching, NELEM(sMethodsBatching)); jniRegisterNativeMethods( env, "com/android/server/location/GnssGeofenceProvider", sGeofenceMethods, NELEM(sGeofenceMethods)); return jniRegisterNativeMethods( env, "com/android/server/location/GnssLocationProvider", Loading
services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java 0 → 100644 +121 −0 Original line number Diff line number Diff line package com.android.server.location; import static org.mockito.Matchers.anyDouble; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.Looper; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; /** * Unit tests for {@link GnssGeofenceProvider}. */ @RunWith(FrameworkRobolectricTestRunner.class) @Config( manifest = Config.NONE, sdk = 27 ) @SystemLoaderPackages({"com.android.server.location"}) @Presubmit public class GnssGeofenceProviderTest { private static final int GEOFENCE_ID = 12345; private static final double LATITUDE = 10.0; private static final double LONGITUDE = 20.0; private static final double RADIUS = 5.0; private static final int LAST_TRANSITION = 0; private static final int MONITOR_TRANSITIONS = 0; private static final int NOTIFICATION_RESPONSIVENESS = 0; private static final int UNKNOWN_TIMER = 0; @Mock private GnssGeofenceProvider.GnssGeofenceProviderNative mMockNative; private GnssGeofenceProvider mTestProvider; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mMockNative.addGeofence(anyInt(), anyDouble(), anyDouble(), anyDouble(), anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(true); when(mMockNative.pauseGeofence(anyInt())).thenReturn(true); when(mMockNative.removeGeofence(anyInt())).thenReturn(true); when(mMockNative.resumeGeofence(anyInt(), anyInt())).thenReturn(true); mTestProvider = new GnssGeofenceProvider(Looper.myLooper(), mMockNative); mTestProvider.addCircularHardwareGeofence(GEOFENCE_ID, LATITUDE, LONGITUDE, RADIUS, LAST_TRANSITION, MONITOR_TRANSITIONS, NOTIFICATION_RESPONSIVENESS, UNKNOWN_TIMER); } @Test public void addGeofence_nativeAdded() { verify(mMockNative).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); } @Test public void pauseGeofence_nativePaused() { mTestProvider.pauseHardwareGeofence(GEOFENCE_ID); verify(mMockNative).pauseGeofence(eq(GEOFENCE_ID)); } @Test public void removeGeofence_nativeRemoved() { mTestProvider.removeHardwareGeofence(GEOFENCE_ID); verify(mMockNative).removeGeofence(eq(GEOFENCE_ID)); } @Test public void resumeGeofence_nativeResumed() { mTestProvider.pauseHardwareGeofence(GEOFENCE_ID); mTestProvider.resumeHardwareGeofence(GEOFENCE_ID, MONITOR_TRANSITIONS); verify(mMockNative).resumeGeofence(eq(GEOFENCE_ID), eq(MONITOR_TRANSITIONS)); } @Test public void addGeofence_restart_added() throws RemoteException { mTestProvider.resumeIfStarted(); verify(mMockNative, times(2)).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); } @Test public void removeGeofence_restart_notAdded() throws RemoteException { mTestProvider.removeHardwareGeofence(GEOFENCE_ID); mTestProvider.resumeIfStarted(); verify(mMockNative, times(1)).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); } @Test public void pauseGeofence_restart_paused() throws RemoteException { mTestProvider.pauseHardwareGeofence(GEOFENCE_ID); mTestProvider.resumeIfStarted(); verify(mMockNative, times(2)).addGeofence(eq(GEOFENCE_ID), eq(LATITUDE), eq(LONGITUDE), eq(RADIUS), eq(LAST_TRANSITION), eq(MONITOR_TRANSITIONS), eq(NOTIFICATION_RESPONSIVENESS), eq(UNKNOWN_TIMER)); verify(mMockNative, times(2)).pauseGeofence(eq(GEOFENCE_ID)); } }