Loading services/core/java/com/android/server/location/GnssLocationProvider.java +2 −39 Original line number Diff line number Diff line Loading @@ -818,37 +818,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt } }; mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) { @Override public boolean isAvailableInPlatform() { return native_is_measurement_supported(); } @Override protected int registerWithService() { int devOptions = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0); int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING , 0); boolean result = false; if (devOptions == 1 /* Developer Mode enabled */ && fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */) { result = native_start_measurement_collection(true /* enableFullTracking */); } else { result = native_start_measurement_collection(false /* enableFullTracking */); } if (result) { return RemoteListenerHelper.RESULT_SUCCESS; } else { return RemoteListenerHelper.RESULT_INTERNAL_ERROR; } } @Override protected void unregisterFromService() { native_stop_measurement_collection(); } mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) { @Override protected boolean isGpsEnabled() { return isEnabled(); Loading Loading @@ -2790,13 +2760,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); // Gps Hal measurements support. private static native boolean native_is_measurement_supported(); private native boolean native_start_measurement_collection(boolean enableFullTracking); private native boolean native_stop_measurement_collection(); // Gps Navigation message support. private static native boolean native_is_navigation_message_supported(); Loading services/core/java/com/android/server/location/GnssMeasurementsProvider.java +85 −9 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package com.android.server.location; import android.content.Context; import android.location.GnssMeasurementsEvent; import android.location.IGnssMeasurementsListener; import android.os.Handler; import android.os.RemoteException; import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; /** * An base implementation for GPS measurements provider. * It abstracts out the responsibility of handling listeners, while still allowing technology Loading @@ -29,22 +33,73 @@ import android.util.Log; * * @hide */ public abstract class GnssMeasurementsProvider extends RemoteListenerHelper<IGnssMeasurementsListener> { public abstract class GnssMeasurementsProvider extends RemoteListenerHelper<IGnssMeasurementsListener> { private static final String TAG = "GnssMeasurementsProvider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Context mContext; private final GnssMeasurementProviderNative mNative; private boolean mIsCollectionStarted; private boolean mEnableFullTracking; protected GnssMeasurementsProvider(Context context, Handler handler) { this(context, handler, new GnssMeasurementProviderNative()); } protected GnssMeasurementsProvider(Handler handler) { @VisibleForTesting GnssMeasurementsProvider(Context context, Handler handler, GnssMeasurementProviderNative aNative) { super(handler, TAG); mContext = context; mNative = aNative; } // TODO(b/37460011): Use this with death recovery logic. void resumeIfStarted() { if (DEBUG) { Log.d(TAG, "resumeIfStarted"); } if (mIsCollectionStarted) { mNative.startMeasurementCollection(mEnableFullTracking); } } public void onMeasurementsAvailable(final GnssMeasurementsEvent event) { ListenerOperation<IGnssMeasurementsListener> operation = new ListenerOperation<IGnssMeasurementsListener>() { @Override public void execute(IGnssMeasurementsListener listener) throws RemoteException { listener.onGnssMeasurementsReceived(event); public boolean isAvailableInPlatform() { return mNative.isMeasurementSupported(); } @Override protected int registerWithService() { int devOptions = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0); int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, 0); boolean enableFullTracking = (devOptions == 1 /* Developer Mode enabled */) && (fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */); boolean result = mNative.startMeasurementCollection(enableFullTracking); if (result) { mIsCollectionStarted = true; mEnableFullTracking = enableFullTracking; return RemoteListenerHelper.RESULT_SUCCESS; } else { return RemoteListenerHelper.RESULT_INTERNAL_ERROR; } }; } @Override protected void unregisterFromService() { boolean stopped = mNative.stopMeasurementCollection(); if (stopped) { mIsCollectionStarted = false; } } public void onMeasurementsAvailable(final GnssMeasurementsEvent event) { ListenerOperation<IGnssMeasurementsListener> operation = listener -> listener.onGnssMeasurementsReceived(event); foreach(operation); } Loading Loading @@ -98,4 +153,25 @@ public abstract class GnssMeasurementsProvider listener.onStatusChanged(mStatus); } } @VisibleForTesting static class GnssMeasurementProviderNative { public boolean isMeasurementSupported() { return native_is_measurement_supported(); } public boolean startMeasurementCollection(boolean enableFullTracking) { return native_start_measurement_collection(enableFullTracking); } public boolean stopMeasurementCollection() { return native_stop_measurement_collection(); } } private static native boolean native_is_measurement_supported(); private static native boolean native_start_measurement_collection(boolean enableFullTracking); private static native boolean native_stop_measurement_collection(); } services/core/jni/com_android_server_location_GnssLocationProvider.cpp +24 −15 Original line number Diff line number Diff line Loading @@ -1799,7 +1799,7 @@ static jboolean android_location_GnssGeofenceProvider_resume_geofence(JNIEnv* /* return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_is_measurement_supported( static jboolean android_location_GnssMeasurementsProvider_is_measurement_supported( JNIEnv* env, jclass clazz) { if (gnssMeasurementIface != nullptr) { return JNI_TRUE; Loading @@ -1808,7 +1808,7 @@ static jboolean android_location_GnssLocationProvider_is_measurement_supported( return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_start_measurement_collection( static jboolean android_location_GnssMeasurementsProvider_start_measurement_collection( JNIEnv* /* env */, jobject /* obj */, jboolean enableFullTracking) { Loading Loading @@ -1842,7 +1842,7 @@ static jboolean android_location_GnssLocationProvider_start_measurement_collecti return JNI_TRUE; } static jboolean android_location_GnssLocationProvider_stop_measurement_collection( static jboolean android_location_GnssMeasurementsProvider_stop_measurement_collection( JNIEnv* env, jobject obj) { if (gnssMeasurementIface == nullptr) { Loading Loading @@ -2178,18 +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_measurement_supported", "()Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_is_measurement_supported)}, {"native_start_measurement_collection", "(Z)Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_start_measurement_collection)}, {"native_stop_measurement_collection", "()Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_stop_measurement_collection)}, {"native_is_navigation_message_supported", "()Z", reinterpret_cast<void *>( Loading Loading @@ -2269,6 +2257,22 @@ static const JNINativeMethod sGeofenceMethods[] = { reinterpret_cast<void *>(android_location_GnssGeofenceProvider_resume_geofence)}, }; static const JNINativeMethod sMeasurementMethods[] = { /* name, signature, funcPtr */ {"native_is_measurement_supported", "()Z", reinterpret_cast<void *>( android_location_GnssMeasurementsProvider_is_measurement_supported)}, {"native_start_measurement_collection", "(Z)Z", reinterpret_cast<void *>( android_location_GnssMeasurementsProvider_start_measurement_collection)}, {"native_stop_measurement_collection", "()Z", reinterpret_cast<void *>( android_location_GnssMeasurementsProvider_stop_measurement_collection)}, }; int register_android_server_location_GnssLocationProvider(JNIEnv* env) { jniRegisterNativeMethods( env, Loading @@ -2280,6 +2284,11 @@ int register_android_server_location_GnssLocationProvider(JNIEnv* env) { "com/android/server/location/GnssGeofenceProvider", sGeofenceMethods, NELEM(sGeofenceMethods)); jniRegisterNativeMethods( env, "com/android/server/location/GnssMeasurementsProvider", sMeasurementMethods, NELEM(sMeasurementMethods)); return jniRegisterNativeMethods( env, "com/android/server/location/GnssLocationProvider", Loading services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java 0 → 100644 +90 −0 Original line number Diff line number Diff line package com.android.server.location; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.Handler; import android.os.Looper; 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.RuntimeEnvironment; import org.robolectric.annotation.Config; /** * Unit tests for {@link GnssMeasurementsProvider}. */ @RunWith(FrameworkRobolectricTestRunner.class) @Config( manifest = Config.NONE, sdk = 27 ) @SystemLoaderPackages({"com.android.server.location"}) @Presubmit public class GnssMeasurementsProviderTest { @Mock private GnssMeasurementsProvider.GnssMeasurementProviderNative mMockNative; private GnssMeasurementsProvider mTestProvider; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mMockNative.startMeasurementCollection(anyBoolean())).thenReturn(true); when(mMockNative.stopMeasurementCollection()).thenReturn(true); mTestProvider = new GnssMeasurementsProvider(RuntimeEnvironment.application, new Handler(Looper.myLooper()), mMockNative) { @Override public boolean isGpsEnabled() { return true; } }; } @Test public void register_nativeStarted() { mTestProvider.registerWithService(); verify(mMockNative).startMeasurementCollection(anyBoolean()); } @Test public void unregister_nativeStopped() { mTestProvider.registerWithService(); mTestProvider.unregisterFromService(); verify(mMockNative).stopMeasurementCollection(); } @Test public void isSupported_nativeIsSupported() { when(mMockNative.isMeasurementSupported()).thenReturn(true); assertThat(mTestProvider.isAvailableInPlatform()).isTrue(); when(mMockNative.isMeasurementSupported()).thenReturn(false); assertThat(mTestProvider.isAvailableInPlatform()).isFalse(); } @Test public void register_resume_started() { mTestProvider.registerWithService(); mTestProvider.resumeIfStarted(); verify(mMockNative, times(2)).startMeasurementCollection(anyBoolean()); } @Test public void unregister_resume_notStarted() { mTestProvider.registerWithService(); mTestProvider.unregisterFromService(); mTestProvider.resumeIfStarted(); verify(mMockNative, times(1)).startMeasurementCollection(anyBoolean()); } } Loading
services/core/java/com/android/server/location/GnssLocationProvider.java +2 −39 Original line number Diff line number Diff line Loading @@ -818,37 +818,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt } }; mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) { @Override public boolean isAvailableInPlatform() { return native_is_measurement_supported(); } @Override protected int registerWithService() { int devOptions = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0); int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING , 0); boolean result = false; if (devOptions == 1 /* Developer Mode enabled */ && fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */) { result = native_start_measurement_collection(true /* enableFullTracking */); } else { result = native_start_measurement_collection(false /* enableFullTracking */); } if (result) { return RemoteListenerHelper.RESULT_SUCCESS; } else { return RemoteListenerHelper.RESULT_INTERNAL_ERROR; } } @Override protected void unregisterFromService() { native_stop_measurement_collection(); } mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) { @Override protected boolean isGpsEnabled() { return isEnabled(); Loading Loading @@ -2790,13 +2760,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); // Gps Hal measurements support. private static native boolean native_is_measurement_supported(); private native boolean native_start_measurement_collection(boolean enableFullTracking); private native boolean native_stop_measurement_collection(); // Gps Navigation message support. private static native boolean native_is_navigation_message_supported(); Loading
services/core/java/com/android/server/location/GnssMeasurementsProvider.java +85 −9 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package com.android.server.location; import android.content.Context; import android.location.GnssMeasurementsEvent; import android.location.IGnssMeasurementsListener; import android.os.Handler; import android.os.RemoteException; import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; /** * An base implementation for GPS measurements provider. * It abstracts out the responsibility of handling listeners, while still allowing technology Loading @@ -29,22 +33,73 @@ import android.util.Log; * * @hide */ public abstract class GnssMeasurementsProvider extends RemoteListenerHelper<IGnssMeasurementsListener> { public abstract class GnssMeasurementsProvider extends RemoteListenerHelper<IGnssMeasurementsListener> { private static final String TAG = "GnssMeasurementsProvider"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Context mContext; private final GnssMeasurementProviderNative mNative; private boolean mIsCollectionStarted; private boolean mEnableFullTracking; protected GnssMeasurementsProvider(Context context, Handler handler) { this(context, handler, new GnssMeasurementProviderNative()); } protected GnssMeasurementsProvider(Handler handler) { @VisibleForTesting GnssMeasurementsProvider(Context context, Handler handler, GnssMeasurementProviderNative aNative) { super(handler, TAG); mContext = context; mNative = aNative; } // TODO(b/37460011): Use this with death recovery logic. void resumeIfStarted() { if (DEBUG) { Log.d(TAG, "resumeIfStarted"); } if (mIsCollectionStarted) { mNative.startMeasurementCollection(mEnableFullTracking); } } public void onMeasurementsAvailable(final GnssMeasurementsEvent event) { ListenerOperation<IGnssMeasurementsListener> operation = new ListenerOperation<IGnssMeasurementsListener>() { @Override public void execute(IGnssMeasurementsListener listener) throws RemoteException { listener.onGnssMeasurementsReceived(event); public boolean isAvailableInPlatform() { return mNative.isMeasurementSupported(); } @Override protected int registerWithService() { int devOptions = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0); int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, 0); boolean enableFullTracking = (devOptions == 1 /* Developer Mode enabled */) && (fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */); boolean result = mNative.startMeasurementCollection(enableFullTracking); if (result) { mIsCollectionStarted = true; mEnableFullTracking = enableFullTracking; return RemoteListenerHelper.RESULT_SUCCESS; } else { return RemoteListenerHelper.RESULT_INTERNAL_ERROR; } }; } @Override protected void unregisterFromService() { boolean stopped = mNative.stopMeasurementCollection(); if (stopped) { mIsCollectionStarted = false; } } public void onMeasurementsAvailable(final GnssMeasurementsEvent event) { ListenerOperation<IGnssMeasurementsListener> operation = listener -> listener.onGnssMeasurementsReceived(event); foreach(operation); } Loading Loading @@ -98,4 +153,25 @@ public abstract class GnssMeasurementsProvider listener.onStatusChanged(mStatus); } } @VisibleForTesting static class GnssMeasurementProviderNative { public boolean isMeasurementSupported() { return native_is_measurement_supported(); } public boolean startMeasurementCollection(boolean enableFullTracking) { return native_start_measurement_collection(enableFullTracking); } public boolean stopMeasurementCollection() { return native_stop_measurement_collection(); } } private static native boolean native_is_measurement_supported(); private static native boolean native_start_measurement_collection(boolean enableFullTracking); private static native boolean native_stop_measurement_collection(); }
services/core/jni/com_android_server_location_GnssLocationProvider.cpp +24 −15 Original line number Diff line number Diff line Loading @@ -1799,7 +1799,7 @@ static jboolean android_location_GnssGeofenceProvider_resume_geofence(JNIEnv* /* return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_is_measurement_supported( static jboolean android_location_GnssMeasurementsProvider_is_measurement_supported( JNIEnv* env, jclass clazz) { if (gnssMeasurementIface != nullptr) { return JNI_TRUE; Loading @@ -1808,7 +1808,7 @@ static jboolean android_location_GnssLocationProvider_is_measurement_supported( return JNI_FALSE; } static jboolean android_location_GnssLocationProvider_start_measurement_collection( static jboolean android_location_GnssMeasurementsProvider_start_measurement_collection( JNIEnv* /* env */, jobject /* obj */, jboolean enableFullTracking) { Loading Loading @@ -1842,7 +1842,7 @@ static jboolean android_location_GnssLocationProvider_start_measurement_collecti return JNI_TRUE; } static jboolean android_location_GnssLocationProvider_stop_measurement_collection( static jboolean android_location_GnssMeasurementsProvider_stop_measurement_collection( JNIEnv* env, jobject obj) { if (gnssMeasurementIface == nullptr) { Loading Loading @@ -2178,18 +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_measurement_supported", "()Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_is_measurement_supported)}, {"native_start_measurement_collection", "(Z)Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_start_measurement_collection)}, {"native_stop_measurement_collection", "()Z", reinterpret_cast<void *>( android_location_GnssLocationProvider_stop_measurement_collection)}, {"native_is_navigation_message_supported", "()Z", reinterpret_cast<void *>( Loading Loading @@ -2269,6 +2257,22 @@ static const JNINativeMethod sGeofenceMethods[] = { reinterpret_cast<void *>(android_location_GnssGeofenceProvider_resume_geofence)}, }; static const JNINativeMethod sMeasurementMethods[] = { /* name, signature, funcPtr */ {"native_is_measurement_supported", "()Z", reinterpret_cast<void *>( android_location_GnssMeasurementsProvider_is_measurement_supported)}, {"native_start_measurement_collection", "(Z)Z", reinterpret_cast<void *>( android_location_GnssMeasurementsProvider_start_measurement_collection)}, {"native_stop_measurement_collection", "()Z", reinterpret_cast<void *>( android_location_GnssMeasurementsProvider_stop_measurement_collection)}, }; int register_android_server_location_GnssLocationProvider(JNIEnv* env) { jniRegisterNativeMethods( env, Loading @@ -2280,6 +2284,11 @@ int register_android_server_location_GnssLocationProvider(JNIEnv* env) { "com/android/server/location/GnssGeofenceProvider", sGeofenceMethods, NELEM(sGeofenceMethods)); jniRegisterNativeMethods( env, "com/android/server/location/GnssMeasurementsProvider", sMeasurementMethods, NELEM(sMeasurementMethods)); return jniRegisterNativeMethods( env, "com/android/server/location/GnssLocationProvider", Loading
services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java 0 → 100644 +90 −0 Original line number Diff line number Diff line package com.android.server.location; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.Handler; import android.os.Looper; 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.RuntimeEnvironment; import org.robolectric.annotation.Config; /** * Unit tests for {@link GnssMeasurementsProvider}. */ @RunWith(FrameworkRobolectricTestRunner.class) @Config( manifest = Config.NONE, sdk = 27 ) @SystemLoaderPackages({"com.android.server.location"}) @Presubmit public class GnssMeasurementsProviderTest { @Mock private GnssMeasurementsProvider.GnssMeasurementProviderNative mMockNative; private GnssMeasurementsProvider mTestProvider; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mMockNative.startMeasurementCollection(anyBoolean())).thenReturn(true); when(mMockNative.stopMeasurementCollection()).thenReturn(true); mTestProvider = new GnssMeasurementsProvider(RuntimeEnvironment.application, new Handler(Looper.myLooper()), mMockNative) { @Override public boolean isGpsEnabled() { return true; } }; } @Test public void register_nativeStarted() { mTestProvider.registerWithService(); verify(mMockNative).startMeasurementCollection(anyBoolean()); } @Test public void unregister_nativeStopped() { mTestProvider.registerWithService(); mTestProvider.unregisterFromService(); verify(mMockNative).stopMeasurementCollection(); } @Test public void isSupported_nativeIsSupported() { when(mMockNative.isMeasurementSupported()).thenReturn(true); assertThat(mTestProvider.isAvailableInPlatform()).isTrue(); when(mMockNative.isMeasurementSupported()).thenReturn(false); assertThat(mTestProvider.isAvailableInPlatform()).isFalse(); } @Test public void register_resume_started() { mTestProvider.registerWithService(); mTestProvider.resumeIfStarted(); verify(mMockNative, times(2)).startMeasurementCollection(anyBoolean()); } @Test public void unregister_resume_notStarted() { mTestProvider.registerWithService(); mTestProvider.unregisterFromService(); mTestProvider.resumeIfStarted(); verify(mMockNative, times(1)).startMeasurementCollection(anyBoolean()); } }