Refactor GnssBatchingProvider
Bug: 77974758 Fixes: 77974758 Test: m -j ROBOTEST_FILTER=GnssBatchingProviderTest RunFrameworksServicesRoboTests Change-Id: I907265358abdd5486dc1040c7d7bf912942bcb1d
This commit is contained in:
@@ -86,6 +86,7 @@ import com.android.server.location.ActivityRecognitionProxy;
|
||||
import com.android.server.location.GeocoderProxy;
|
||||
import com.android.server.location.GeofenceManager;
|
||||
import com.android.server.location.GeofenceProxy;
|
||||
import com.android.server.location.GnssBatchingProvider;
|
||||
import com.android.server.location.GnssLocationProvider;
|
||||
import com.android.server.location.GnssMeasurementsProvider;
|
||||
import com.android.server.location.GnssNavigationMessageProvider;
|
||||
@@ -244,7 +245,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
|
||||
private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
|
||||
|
||||
private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
|
||||
private GnssBatchingProvider mGnssBatchingProvider;
|
||||
private IBatchedLocationCallback mGnssBatchingCallback;
|
||||
private LinkedCallback mGnssBatchingDeathCallback;
|
||||
private boolean mGnssBatchingInProgress = false;
|
||||
@@ -1173,7 +1174,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
"Location Hardware permission not granted to access hardware batching");
|
||||
|
||||
if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
|
||||
return mGnssBatchingProvider.getSize();
|
||||
return mGnssBatchingProvider.getBatchSize();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.android.server.location;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Manages GNSS Batching operations.
|
||||
*
|
||||
* <p>This class is not thread safe (It's client's responsibility to make sure calls happen on
|
||||
* the same thread).
|
||||
*/
|
||||
public class GnssBatchingProvider {
|
||||
|
||||
private static final String TAG = "GnssBatchingProvider";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final GnssBatchingProviderNative mNative;
|
||||
private boolean mEnabled;
|
||||
private boolean mStarted;
|
||||
private long mPeriodNanos;
|
||||
private boolean mWakeOnFifoFull;
|
||||
|
||||
GnssBatchingProvider() {
|
||||
this(new GnssBatchingProviderNative());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
GnssBatchingProvider(GnssBatchingProviderNative gnssBatchingProviderNative) {
|
||||
mNative = gnssBatchingProviderNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GNSS batching size
|
||||
*/
|
||||
public int getBatchSize() {
|
||||
return mNative.getBatchSize();
|
||||
}
|
||||
|
||||
/** Enable GNSS batching. */
|
||||
public void enable() {
|
||||
mEnabled = mNative.initBatching();
|
||||
if (!mEnabled) {
|
||||
Log.e(TAG, "Failed to initialize GNSS batching");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the hardware batching operation
|
||||
*/
|
||||
public boolean start(long periodNanos, boolean wakeOnFifoFull) {
|
||||
if (!mEnabled) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (periodNanos <= 0) {
|
||||
Log.e(TAG, "Invalid periodNanos " + periodNanos +
|
||||
" in batching request, not started");
|
||||
return false;
|
||||
}
|
||||
mStarted = mNative.startBatch(periodNanos, wakeOnFifoFull);
|
||||
if (mStarted) {
|
||||
mPeriodNanos = periodNanos;
|
||||
mWakeOnFifoFull = wakeOnFifoFull;
|
||||
}
|
||||
return mStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a flush of existing locations from the hardware batching
|
||||
*/
|
||||
public void flush() {
|
||||
if (!mStarted) {
|
||||
Log.w(TAG, "Cannot flush since GNSS batching has not started.");
|
||||
return;
|
||||
}
|
||||
mNative.flushBatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the batching operation
|
||||
*/
|
||||
public boolean stop() {
|
||||
boolean stopped = mNative.stopBatch();
|
||||
if (stopped) {
|
||||
mStarted = false;
|
||||
}
|
||||
return stopped;
|
||||
}
|
||||
|
||||
/** Disable GNSS batching. */
|
||||
public void disable() {
|
||||
stop();
|
||||
mNative.cleanupBatching();
|
||||
mEnabled = false;
|
||||
}
|
||||
|
||||
// TODO(b/37460011): Use this with death recovery logic.
|
||||
void resumeIfStarted() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "resumeIfStarted");
|
||||
}
|
||||
if (mStarted) {
|
||||
mNative.startBatch(mPeriodNanos, mWakeOnFifoFull);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class GnssBatchingProviderNative {
|
||||
public int getBatchSize() {
|
||||
return native_get_batch_size();
|
||||
}
|
||||
|
||||
public boolean startBatch(long periodNanos, boolean wakeOnFifoFull) {
|
||||
return native_start_batch(periodNanos, wakeOnFifoFull);
|
||||
}
|
||||
|
||||
public void flushBatch() {
|
||||
native_flush_batch();
|
||||
}
|
||||
|
||||
public boolean stopBatch() {
|
||||
return native_stop_batch();
|
||||
}
|
||||
|
||||
public boolean initBatching() {
|
||||
return native_init_batching();
|
||||
}
|
||||
|
||||
public void cleanupBatching() {
|
||||
native_cleanup_batching();
|
||||
}
|
||||
}
|
||||
|
||||
private static native int native_get_batch_size();
|
||||
|
||||
private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
|
||||
|
||||
private static native void native_flush_batch();
|
||||
|
||||
private static native boolean native_stop_batch();
|
||||
|
||||
private static native boolean native_init_batching();
|
||||
|
||||
private static native void native_cleanup_batching();
|
||||
}
|
||||
@@ -420,6 +420,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
|
||||
private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
|
||||
private final NtpTimeHelper mNtpTimeHelper;
|
||||
private final GnssBatchingProvider mGnssBatchingProvider;
|
||||
|
||||
// Handler for processing events
|
||||
private Handler mHandler;
|
||||
@@ -887,6 +888,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
|
||||
looper, this);
|
||||
mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
|
||||
mGnssBatchingProvider = new GnssBatchingProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1273,7 +1275,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
|
||||
mGnssMeasurementsProvider.onGpsEnabledChanged();
|
||||
mGnssNavigationMessageProvider.onGpsEnabledChanged();
|
||||
enableBatching();
|
||||
mGnssBatchingProvider.enable();
|
||||
} else {
|
||||
synchronized (mLock) {
|
||||
mEnabled = false;
|
||||
@@ -1305,7 +1307,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
mAlarmManager.cancel(mWakeupIntent);
|
||||
mAlarmManager.cancel(mTimeoutIntent);
|
||||
|
||||
disableBatching();
|
||||
mGnssBatchingProvider.disable();
|
||||
// do this before releasing wakelock
|
||||
native_cleanup();
|
||||
|
||||
@@ -2007,58 +2009,11 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
};
|
||||
}
|
||||
|
||||
public interface GnssBatchingProvider {
|
||||
/**
|
||||
* Returns the GNSS batching size
|
||||
*/
|
||||
int getSize();
|
||||
|
||||
/**
|
||||
* Starts the hardware batching operation
|
||||
*/
|
||||
boolean start(long periodNanos, boolean wakeOnFifoFull);
|
||||
|
||||
/**
|
||||
* Forces a flush of existing locations from the hardware batching
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Stops the batching operation
|
||||
*/
|
||||
boolean stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public GnssBatchingProvider getGnssBatchingProvider() {
|
||||
return new GnssBatchingProvider() {
|
||||
@Override
|
||||
public int getSize() {
|
||||
return native_get_batch_size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start(long periodNanos, boolean wakeOnFifoFull) {
|
||||
if (periodNanos <= 0) {
|
||||
Log.e(TAG, "Invalid periodNanos " + periodNanos +
|
||||
"in batching request, not started");
|
||||
return false;
|
||||
}
|
||||
return native_start_batch(periodNanos, wakeOnFifoFull);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
native_flush_batch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return native_stop_batch();
|
||||
}
|
||||
};
|
||||
return mGnssBatchingProvider;
|
||||
}
|
||||
|
||||
public interface GnssMetricsProvider {
|
||||
@@ -2080,23 +2035,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Batching if enabled
|
||||
*/
|
||||
private void enableBatching() {
|
||||
if (!native_init_batching()) {
|
||||
Log.e(TAG, "Failed to initialize GNSS batching");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable batching
|
||||
*/
|
||||
private void disableBatching() {
|
||||
native_stop_batch();
|
||||
native_cleanup_batching();
|
||||
}
|
||||
|
||||
/**
|
||||
* called from native code - GNSS location batch callback
|
||||
*/
|
||||
@@ -2918,19 +2856,5 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
|
||||
|
||||
private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds);
|
||||
|
||||
// GNSS Batching
|
||||
private static native int native_get_batch_size();
|
||||
|
||||
private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
|
||||
|
||||
private static native void native_flush_batch();
|
||||
|
||||
private static native boolean native_stop_batch();
|
||||
|
||||
private static native boolean native_init_batching();
|
||||
|
||||
private static native void native_cleanup_batching();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2050,7 +2050,7 @@ static jboolean android_location_GnssLocationProvider_set_satellite_blacklist(
|
||||
}
|
||||
|
||||
|
||||
static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) {
|
||||
static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return 0; // batching not supported, size = 0
|
||||
}
|
||||
@@ -2062,7 +2062,7 @@ static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jclass) {
|
||||
static jboolean android_location_GnssBatchingProvider_init_batching(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return JNI_FALSE; // batching not supported
|
||||
}
|
||||
@@ -2071,14 +2071,14 @@ static jboolean android_location_GnssLocationProvider_init_batching(JNIEnv*, jcl
|
||||
return static_cast<jboolean>(gnssBatchingIface->init(gnssBatchingCbIface));
|
||||
}
|
||||
|
||||
static void android_location_GnssLocationProvider_cleanup_batching(JNIEnv*, jclass) {
|
||||
static void android_location_GnssBatchingProvider_cleanup_batching(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return; // batching not supported
|
||||
}
|
||||
gnssBatchingIface->cleanup();
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclass,
|
||||
static jboolean android_location_GnssBatchingProvider_start_batch(JNIEnv*, jclass,
|
||||
jlong periodNanos, jboolean wakeOnFifoFull) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return JNI_FALSE; // batching not supported
|
||||
@@ -2095,7 +2095,7 @@ static jboolean android_location_GnssLocationProvider_start_batch(JNIEnv*, jclas
|
||||
return static_cast<jboolean>(gnssBatchingIface->start(options));
|
||||
}
|
||||
|
||||
static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
|
||||
static void android_location_GnssBatchingProvider_flush_batch(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return; // batching not supported
|
||||
}
|
||||
@@ -2103,7 +2103,7 @@ static void android_location_GnssLocationProvider_flush_batch(JNIEnv*, jclass) {
|
||||
gnssBatchingIface->flush();
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_stop_batch(JNIEnv*, jclass) {
|
||||
static jboolean android_location_GnssBatchingProvider_stop_batch(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return JNI_FALSE; // batching not supported
|
||||
}
|
||||
@@ -2241,30 +2241,36 @@ static const JNINativeMethod sMethods[] = {
|
||||
{"native_set_satellite_blacklist",
|
||||
"([I[I)Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_satellite_blacklist)},
|
||||
};
|
||||
|
||||
static const JNINativeMethod sMethodsBatching[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"native_get_batch_size",
|
||||
"()I",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)},
|
||||
{"native_init_batching",
|
||||
"()Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_get_batch_size)},
|
||||
{"native_start_batch",
|
||||
"(JZ)Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_start_batch)},
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_start_batch)},
|
||||
{"native_flush_batch",
|
||||
"()V",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_flush_batch)},
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_flush_batch)},
|
||||
{"native_stop_batch",
|
||||
"()Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_stop_batch)},
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_stop_batch)},
|
||||
{"native_init_batching",
|
||||
"()Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_init_batching)},
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_init_batching)},
|
||||
{"native_cleanup_batching",
|
||||
"()V",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_cleanup_batching)},
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_cleanup_batching)},
|
||||
};
|
||||
|
||||
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
|
||||
jniRegisterNativeMethods(
|
||||
env,
|
||||
"com/android/server/location/GnssBatchingProvider",
|
||||
sMethodsBatching,
|
||||
NELEM(sMethodsBatching));
|
||||
return jniRegisterNativeMethods(
|
||||
env,
|
||||
"com/android/server/location/GnssLocationProvider",
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.android.server.location;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyLong;
|
||||
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.platform.test.annotations.Presubmit;
|
||||
|
||||
import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
|
||||
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 GnssBatchingProvider}.
|
||||
*/
|
||||
@RunWith(FrameworkRobolectricTestRunner.class)
|
||||
@Config(
|
||||
manifest = Config.NONE,
|
||||
shadows = {
|
||||
},
|
||||
sdk = 27
|
||||
)
|
||||
@SystemLoaderPackages({"com.android.server.location"})
|
||||
@Presubmit
|
||||
public class GnssBatchingProviderTest {
|
||||
|
||||
private static final long PERIOD_NANOS = (long) 1e9;
|
||||
private static final boolean WAKE_ON_FIFO_FULL = true;
|
||||
private static final int BATCH_SIZE = 3;
|
||||
@Mock
|
||||
private GnssBatchingProviderNative mMockNative;
|
||||
private GnssBatchingProvider mTestProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mMockNative.initBatching()).thenReturn(true);
|
||||
when(mMockNative.startBatch(anyLong(), anyBoolean())).thenReturn(true);
|
||||
when(mMockNative.stopBatch()).thenReturn(true);
|
||||
when(mMockNative.getBatchSize()).thenReturn(BATCH_SIZE);
|
||||
mTestProvider = new GnssBatchingProvider(mMockNative);
|
||||
mTestProvider.enable();
|
||||
mTestProvider.start(PERIOD_NANOS, WAKE_ON_FIFO_FULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start_nativeStarted() {
|
||||
verify(mMockNative).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stop_nativeStopped() {
|
||||
mTestProvider.stop();
|
||||
verify(mMockNative).stopBatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flush_nativeFlushed() {
|
||||
mTestProvider.flush();
|
||||
verify(mMockNative).flushBatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBatchSize_nativeGetBatchSize() {
|
||||
assertThat(mTestProvider.getBatchSize()).isEqualTo(BATCH_SIZE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void started_resume_started() {
|
||||
mTestProvider.resumeIfStarted();
|
||||
verify(mMockNative, times(2)).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopped_resume_notStarted() {
|
||||
mTestProvider.stop();
|
||||
mTestProvider.resumeIfStarted();
|
||||
verify(mMockNative, times(1)).startBatch(eq(PERIOD_NANOS), eq(WAKE_ON_FIFO_FULL));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user