Merge "Refactor GnssNavigationMessageProvider" into pi-dev
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 03046b6..64750b0 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -827,26 +827,6 @@
mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
@Override
- protected boolean isAvailableInPlatform() {
- return native_is_navigation_message_supported();
- }
-
- @Override
- protected int registerWithService() {
- boolean result = native_start_navigation_message_collection();
- if (result) {
- return RemoteListenerHelper.RESULT_SUCCESS;
- } else {
- return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
- }
- }
-
- @Override
- protected void unregisterFromService() {
- native_stop_navigation_message_collection();
- }
-
- @Override
protected boolean isGpsEnabled() {
return isEnabled();
}
@@ -2760,13 +2740,6 @@
private native void native_update_network_state(boolean connected, int type,
boolean roaming, boolean available, String extraInfo, String defaultAPN);
- // Gps Navigation message support.
- private static native boolean native_is_navigation_message_supported();
-
- private native boolean native_start_navigation_message_collection();
-
- private native boolean native_stop_navigation_message_collection();
-
// GNSS Configuration
private static native boolean native_set_supl_version(int version);
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index df3c49b..1b4fd18 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -22,6 +22,8 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* An base implementation for GPS navigation messages provider.
* It abstracts out the responsibility of handling listeners, while still allowing technology
@@ -32,9 +34,53 @@
public abstract class GnssNavigationMessageProvider
extends RemoteListenerHelper<IGnssNavigationMessageListener> {
private static final String TAG = "GnssNavigationMessageProvider";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final GnssNavigationMessageProviderNative mNative;
+ private boolean mCollectionStarted;
protected GnssNavigationMessageProvider(Handler handler) {
+ this(handler, new GnssNavigationMessageProviderNative());
+ }
+
+ @VisibleForTesting
+ GnssNavigationMessageProvider(Handler handler, GnssNavigationMessageProviderNative aNative) {
super(handler, TAG);
+ mNative = aNative;
+ }
+
+ // TODO(b/37460011): Use this with death recovery logic.
+ void resumeIfStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "resumeIfStarted");
+ }
+ if (mCollectionStarted) {
+ mNative.startNavigationMessageCollection();
+ }
+ }
+
+ @Override
+ protected boolean isAvailableInPlatform() {
+ return mNative.isNavigationMessageSupported();
+ }
+
+ @Override
+ protected int registerWithService() {
+ boolean result = mNative.startNavigationMessageCollection();
+ if (result) {
+ mCollectionStarted = true;
+ return RemoteListenerHelper.RESULT_SUCCESS;
+ } else {
+ return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
+ }
+ }
+
+ @Override
+ protected void unregisterFromService() {
+ boolean stopped = mNative.stopNavigationMessageCollection();
+ if (stopped) {
+ mCollectionStarted = false;
+ }
}
public void onNavigationMessageAvailable(final GnssNavigationMessage event) {
@@ -96,4 +142,25 @@
listener.onStatusChanged(mStatus);
}
}
+
+ @VisibleForTesting
+ static class GnssNavigationMessageProviderNative {
+ public boolean isNavigationMessageSupported() {
+ return native_is_navigation_message_supported();
+ }
+
+ public boolean startNavigationMessageCollection() {
+ return native_start_navigation_message_collection();
+ }
+
+ public boolean stopNavigationMessageCollection() {
+ return native_stop_navigation_message_collection();
+ }
+ }
+
+ private static native boolean native_is_navigation_message_supported();
+
+ private static native boolean native_start_navigation_message_collection();
+
+ private static native boolean native_stop_navigation_message_collection();
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index b3b37d6..a3a7e1e 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1854,7 +1854,7 @@
return boolToJbool(result.isOk());
}
-static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
+static jboolean android_location_GnssNavigationMessageProvider_is_navigation_message_supported(
JNIEnv* env,
jclass clazz) {
if (gnssNavigationMessageIface != nullptr) {
@@ -1863,7 +1863,7 @@
return JNI_FALSE;
}
-static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
+static jboolean android_location_GnssNavigationMessageProvider_start_navigation_message_collection(
JNIEnv* env,
jobject obj) {
if (gnssNavigationMessageIface == nullptr) {
@@ -1884,7 +1884,7 @@
return JNI_TRUE;
}
-static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
+static jboolean android_location_GnssNavigationMessageProvider_stop_navigation_message_collection(
JNIEnv* env,
jobject obj) {
if (gnssNavigationMessageIface == nullptr) {
@@ -2178,18 +2178,6 @@
{"native_update_network_state",
"(ZIZZLjava/lang/String;Ljava/lang/String;)V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
- {"native_is_navigation_message_supported",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssLocationProvider_is_navigation_message_supported)},
- {"native_start_navigation_message_collection",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssLocationProvider_start_navigation_message_collection)},
- {"native_stop_navigation_message_collection",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssLocationProvider_stop_navigation_message_collection)},
{"native_set_supl_es",
"(I)Z",
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
@@ -2273,6 +2261,22 @@
android_location_GnssMeasurementsProvider_stop_measurement_collection)},
};
+static const JNINativeMethod sNavigationMessageMethods[] = {
+ /* name, signature, funcPtr */
+ {"native_is_navigation_message_supported",
+ "()Z",
+ reinterpret_cast<void *>(
+ android_location_GnssNavigationMessageProvider_is_navigation_message_supported)},
+ {"native_start_navigation_message_collection",
+ "()Z",
+ reinterpret_cast<void *>(
+ android_location_GnssNavigationMessageProvider_start_navigation_message_collection)},
+ {"native_stop_navigation_message_collection",
+ "()Z",
+ reinterpret_cast<void *>(
+ android_location_GnssNavigationMessageProvider_stop_navigation_message_collection)},
+};
+
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
jniRegisterNativeMethods(
env,
@@ -2289,6 +2293,11 @@
"com/android/server/location/GnssMeasurementsProvider",
sMeasurementMethods,
NELEM(sMeasurementMethods));
+ jniRegisterNativeMethods(
+ env,
+ "com/android/server/location/GnssNavigationMessageProvider",
+ sNavigationMessageMethods,
+ NELEM(sNavigationMessageMethods));
return jniRegisterNativeMethods(
env,
"com/android/server/location/GnssLocationProvider",
diff --git a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
new file mode 100644
index 0000000..8d3de3c
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
@@ -0,0 +1,89 @@
+package com.android.server.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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.annotation.Config;
+
+/**
+ * Unit tests for {@link GnssNavigationMessageProvider}.
+ */
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+ manifest = Config.NONE,
+ sdk = 27
+)
+@SystemLoaderPackages({"com.android.server.location"})
+@Presubmit
+public class GnssNavigationMessageProviderTest {
+ @Mock
+ private GnssNavigationMessageProvider.GnssNavigationMessageProviderNative mMockNative;
+ private GnssNavigationMessageProvider mTestProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mMockNative.startNavigationMessageCollection()).thenReturn(true);
+ when(mMockNative.stopNavigationMessageCollection()).thenReturn(true);
+
+ mTestProvider = new GnssNavigationMessageProvider(new Handler(Looper.myLooper()),
+ mMockNative) {
+ @Override
+ public boolean isGpsEnabled() {
+ return true;
+ }
+ };
+ }
+
+ @Test
+ public void register_nativeStarted() {
+ mTestProvider.registerWithService();
+ verify(mMockNative).startNavigationMessageCollection();
+ }
+
+ @Test
+ public void unregister_nativeStopped() {
+ mTestProvider.registerWithService();
+ mTestProvider.unregisterFromService();
+ verify(mMockNative).stopNavigationMessageCollection();
+ }
+
+ @Test
+ public void isSupported_nativeIsSupported() {
+ when(mMockNative.isNavigationMessageSupported()).thenReturn(true);
+ assertThat(mTestProvider.isAvailableInPlatform()).isTrue();
+
+ when(mMockNative.isNavigationMessageSupported()).thenReturn(false);
+ assertThat(mTestProvider.isAvailableInPlatform()).isFalse();
+ }
+
+ @Test
+ public void register_resume_started() {
+ mTestProvider.registerWithService();
+ mTestProvider.resumeIfStarted();
+ verify(mMockNative, times(2)).startNavigationMessageCollection();
+ }
+
+ @Test
+ public void unregister_resume_notStarted() {
+ mTestProvider.registerWithService();
+ mTestProvider.unregisterFromService();
+ mTestProvider.resumeIfStarted();
+ verify(mMockNative, times(1)).startNavigationMessageCollection();
+ }
+}