Merge "Implements GNSS satellite blacklist" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b1bcab2210
@@ -12541,6 +12541,19 @@ public final class Settings {
|
||||
*/
|
||||
public static final String SWAP_ENABLED = "swap_enabled";
|
||||
|
||||
/**
|
||||
* Blacklist of GNSS satellites.
|
||||
*
|
||||
* This is a list of integers separated by commas to represent pairs of (constellation,
|
||||
* svid). Thus, the number of integers should be even.
|
||||
*
|
||||
* E.g.: "3,0,5,24" denotes (constellation=3, svid=0) and (constellation=5, svid=24) are
|
||||
* blacklisted. Note that svid=0 denotes all svids in the
|
||||
* constellation are blacklisted.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String GNSS_SATELLITE_BLACKLIST = "gnss_satellite_blacklist";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -451,6 +451,7 @@ message GlobalSettingsProto {
|
||||
// If set to 1, {@link Secure#LOCATION_MODE} will be set to {@link
|
||||
// Secure#LOCATION_MODE_OFF} temporarily for all users.
|
||||
optional SettingProto global_kill_switch = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
optional SettingProto gnss_satellite_blacklist = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
}
|
||||
optional Location location = 69;
|
||||
|
||||
|
||||
@@ -239,6 +239,7 @@ public class SettingsBackupTest {
|
||||
Settings.Global.GLOBAL_HTTP_PROXY_HOST,
|
||||
Settings.Global.GLOBAL_HTTP_PROXY_PAC,
|
||||
Settings.Global.GLOBAL_HTTP_PROXY_PORT,
|
||||
Settings.Global.GNSS_SATELLITE_BLACKLIST,
|
||||
Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
|
||||
Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
|
||||
Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
|
||||
|
||||
@@ -742,6 +742,9 @@ class SettingsProtoDumpUtil {
|
||||
dumpSetting(s, p,
|
||||
Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
|
||||
GlobalSettingsProto.Location.GLOBAL_KILL_SWITCH);
|
||||
dumpSetting(s, p,
|
||||
Settings.Global.GNSS_SATELLITE_BLACKLIST,
|
||||
GlobalSettingsProto.Location.GNSS_SATELLITE_BLACKLIST);
|
||||
p.end(locationToken);
|
||||
|
||||
final long lpmToken = p.start(GlobalSettingsProto.LOW_POWER_MODE);
|
||||
|
||||
@@ -83,7 +83,11 @@ import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
import com.android.internal.location.ProviderRequest;
|
||||
import com.android.internal.location.gnssmetrics.GnssMetrics;
|
||||
import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
|
||||
import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
@@ -99,14 +103,13 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
/**
|
||||
* A GNSS implementation of LocationProvider used by LocationManager.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class GnssLocationProvider implements LocationProviderInterface, InjectNtpTimeCallback {
|
||||
public class GnssLocationProvider implements LocationProviderInterface, InjectNtpTimeCallback,
|
||||
GnssSatelliteBlacklistCallback {
|
||||
|
||||
private static final String TAG = "GnssLocationProvider";
|
||||
|
||||
@@ -308,7 +311,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
}
|
||||
}
|
||||
|
||||
private Object mLock = new Object();
|
||||
private final Object mLock = new Object();
|
||||
|
||||
// current status
|
||||
private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
|
||||
@@ -411,6 +414,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
private final ILocationManager mILocationManager;
|
||||
private final LocationExtras mLocationExtras = new LocationExtras();
|
||||
private final GnssStatusListenerHelper mListenerHelper;
|
||||
private final GnssSatelliteBlacklistHelper mGnssSatelliteBlacklistHelper;
|
||||
private final GnssMeasurementsProvider mGnssMeasurementsProvider;
|
||||
private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
|
||||
private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
|
||||
@@ -577,6 +581,16 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements {@link GnssSatelliteBlacklistCallback#onUpdateSatelliteBlacklist}.
|
||||
*/
|
||||
@Override
|
||||
public void onUpdateSatelliteBlacklist(int[] constellations, int[] svids) {
|
||||
mHandler.post(()->{
|
||||
native_set_satellite_blacklist(constellations, svids);
|
||||
});
|
||||
}
|
||||
|
||||
private void subscriptionOrSimChanged(Context context) {
|
||||
if (DEBUG) Log.d(TAG, "received SIM related action: ");
|
||||
TelephonyManager phone = (TelephonyManager)
|
||||
@@ -869,7 +883,10 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
|
||||
};
|
||||
mGnssMetrics = new GnssMetrics(mBatteryStats);
|
||||
|
||||
mNtpTimeHelper = new NtpTimeHelper(mContext, Looper.myLooper(), this);
|
||||
mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this);
|
||||
mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
|
||||
looper, this);
|
||||
mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2900,6 +2917,8 @@ 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();
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.android.server.location;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Detects blacklist change and updates the blacklist.
|
||||
*/
|
||||
class GnssSatelliteBlacklistHelper {
|
||||
|
||||
private static final String TAG = "GnssBlacklistHelper";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final String BLACKLIST_DELIMITER = ",";
|
||||
|
||||
private final Context mContext;
|
||||
private final GnssSatelliteBlacklistCallback mCallback;
|
||||
|
||||
interface GnssSatelliteBlacklistCallback {
|
||||
void onUpdateSatelliteBlacklist(int[] constellations, int[] svids);
|
||||
}
|
||||
|
||||
GnssSatelliteBlacklistHelper(Context context, Looper looper,
|
||||
GnssSatelliteBlacklistCallback callback) {
|
||||
mContext = context;
|
||||
mCallback = callback;
|
||||
ContentObserver contentObserver = new ContentObserver(new Handler(looper)) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
updateSatelliteBlacklist();
|
||||
}
|
||||
};
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Global.getUriFor(
|
||||
Settings.Global.GNSS_SATELLITE_BLACKLIST),
|
||||
true,
|
||||
contentObserver, UserHandle.USER_ALL);
|
||||
}
|
||||
|
||||
void updateSatelliteBlacklist() {
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
String blacklist = Settings.Global.getString(
|
||||
resolver,
|
||||
Settings.Global.GNSS_SATELLITE_BLACKLIST);
|
||||
if (blacklist == null) {
|
||||
blacklist = "";
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("Update GNSS satellite blacklist: %s", blacklist));
|
||||
}
|
||||
|
||||
List<Integer> blacklistValues;
|
||||
try {
|
||||
blacklistValues = parseSatelliteBlacklist(blacklist);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Exception thrown when parsing blacklist string.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blacklistValues.size() % 2 != 0) {
|
||||
Log.e(TAG, "blacklist string has odd number of values."
|
||||
+ "Aborting updateSatelliteBlacklist");
|
||||
return;
|
||||
}
|
||||
|
||||
int length = blacklistValues.size() / 2;
|
||||
int[] constellations = new int[length];
|
||||
int[] svids = new int[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
constellations[i] = blacklistValues.get(i * 2);
|
||||
svids[i] = blacklistValues.get(i * 2 + 1);
|
||||
}
|
||||
mCallback.onUpdateSatelliteBlacklist(constellations, svids);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static List<Integer> parseSatelliteBlacklist(String blacklist) throws NumberFormatException {
|
||||
String[] strings = blacklist.split(BLACKLIST_DELIMITER);
|
||||
List<Integer> parsed = new ArrayList<>(strings.length);
|
||||
for (String string : strings) {
|
||||
string = string.trim();
|
||||
if (!"".equals(string)) {
|
||||
int value = Integer.parseInt(string);
|
||||
if (value < 0) {
|
||||
throw new NumberFormatException("Negative value is invalid.");
|
||||
}
|
||||
parsed.add(value);
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,7 @@ using android::hardware::Return;
|
||||
using android::hardware::Void;
|
||||
using android::hardware::hidl_vec;
|
||||
using android::hardware::hidl_death_recipient;
|
||||
using android::hardware::gnss::V1_0::GnssConstellationType;
|
||||
using android::hardware::gnss::V1_0::GnssLocation;
|
||||
using android::hardware::gnss::V1_0::GnssLocationFlags;
|
||||
|
||||
@@ -91,7 +92,6 @@ using android::hardware::gnss::V1_0::IAGnssRil;
|
||||
using android::hardware::gnss::V1_0::IAGnssRilCallback;
|
||||
using android::hardware::gnss::V1_0::IGnssBatching;
|
||||
using android::hardware::gnss::V1_0::IGnssBatchingCallback;
|
||||
using android::hardware::gnss::V1_0::IGnssConfiguration;
|
||||
using android::hardware::gnss::V1_0::IGnssDebug;
|
||||
using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
|
||||
using android::hardware::gnss::V1_0::IGnssGeofencing;
|
||||
@@ -108,6 +108,8 @@ using android::hidl::base::V1_0::IBase;
|
||||
|
||||
using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss;
|
||||
using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss;
|
||||
using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
|
||||
using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
|
||||
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
|
||||
using IGnssMeasurementCallback_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
|
||||
@@ -137,7 +139,8 @@ sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
|
||||
sp<IAGnss> agnssIface = nullptr;
|
||||
sp<IGnssBatching> gnssBatchingIface = nullptr;
|
||||
sp<IGnssDebug> gnssDebugIface = nullptr;
|
||||
sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
|
||||
sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr;
|
||||
sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr;
|
||||
sp<IGnssNi> gnssNiIface = nullptr;
|
||||
sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
|
||||
sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
|
||||
@@ -1098,13 +1101,11 @@ struct GnssBatchingCallback : public IGnssBatchingCallback {
|
||||
* Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback
|
||||
* follow.
|
||||
*/
|
||||
Return<void> gnssLocationBatchCb(
|
||||
const ::android::hardware::hidl_vec<GnssLocation> & locations)
|
||||
Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation> & locations)
|
||||
override;
|
||||
};
|
||||
|
||||
Return<void> GnssBatchingCallback::gnssLocationBatchCb(
|
||||
const ::android::hardware::hidl_vec<GnssLocation> & locations) {
|
||||
Return<void> GnssBatchingCallback::gnssLocationBatchCb(const hidl_vec<GnssLocation> & locations) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
|
||||
jobjectArray jLocations = env->NewObjectArray(locations.size(),
|
||||
@@ -1257,11 +1258,21 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass
|
||||
gnssNiIface = gnssNi;
|
||||
}
|
||||
|
||||
auto gnssConfiguration = gnssHal->getExtensionGnssConfiguration();
|
||||
if (!gnssConfiguration.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssConfiguration");
|
||||
if (gnssHal_V1_1 != nullptr) {
|
||||
auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
|
||||
if (!gnssConfiguration.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssConfiguration");
|
||||
} else {
|
||||
gnssConfigurationIface_V1_1 = gnssConfiguration;
|
||||
gnssConfigurationIface = gnssConfigurationIface_V1_1;
|
||||
}
|
||||
} else {
|
||||
gnssConfigurationIface = gnssConfiguration;
|
||||
auto gnssConfiguration_V1_0 = gnssHal->getExtensionGnssConfiguration();
|
||||
if (!gnssConfiguration_V1_0.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssConfiguration");
|
||||
} else {
|
||||
gnssConfigurationIface = gnssConfiguration_V1_0;
|
||||
}
|
||||
}
|
||||
|
||||
auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
|
||||
@@ -1997,6 +2008,48 @@ static jboolean android_location_GnssLocationProvider_set_gnss_pos_protocol_sele
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssLocationProvider_set_satellite_blacklist(
|
||||
JNIEnv* env, jobject, jintArray constellations, jintArray sv_ids) {
|
||||
if (gnssConfigurationIface_V1_1 == nullptr) {
|
||||
ALOGI("No GNSS Satellite Blacklist interface available");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
jint *constellation_array = env->GetIntArrayElements(constellations, 0);
|
||||
if (NULL == constellation_array) {
|
||||
ALOGI("GetIntArrayElements returns NULL.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
jsize length = env->GetArrayLength(constellations);
|
||||
|
||||
jint *sv_id_array = env->GetIntArrayElements(sv_ids, 0);
|
||||
if (NULL == sv_id_array) {
|
||||
ALOGI("GetIntArrayElements returns NULL.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (length != env->GetArrayLength(sv_ids)) {
|
||||
ALOGI("Lengths of constellations and sv_ids are inconsistent.");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
hidl_vec<IGnssConfiguration_V1_1::BlacklistedSource> sources;
|
||||
sources.resize(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
sources[i].constellation = static_cast<GnssConstellationType>(constellation_array[i]);
|
||||
sources[i].svid = sv_id_array[i];
|
||||
}
|
||||
|
||||
auto result = gnssConfigurationIface_V1_1->setBlacklist(sources);
|
||||
if (result.isOk()) {
|
||||
return result;
|
||||
} else {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) {
|
||||
if (gnssBatchingIface == nullptr) {
|
||||
return 0; // batching not supported, size = 0
|
||||
@@ -2185,6 +2238,9 @@ static const JNINativeMethod sMethods[] = {
|
||||
{"native_set_emergency_supl_pdn",
|
||||
"(I)Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
|
||||
{"native_set_satellite_blacklist",
|
||||
"([I[I)Z",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_satellite_blacklist)},
|
||||
{"native_get_batch_size",
|
||||
"()I",
|
||||
reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)},
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.android.server.location;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.provider.Settings;
|
||||
|
||||
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.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GnssSatelliteBlacklistHelper}.
|
||||
*/
|
||||
@RunWith(FrameworkRobolectricTestRunner.class)
|
||||
@Config(
|
||||
manifest = Config.NONE,
|
||||
shadows = {
|
||||
},
|
||||
sdk = 27
|
||||
)
|
||||
@SystemLoaderPackages({"com.android.server.location"})
|
||||
@Presubmit
|
||||
public class GnssSatelliteBlacklistHelperTest {
|
||||
|
||||
private Context mContext;
|
||||
private ContentResolver mContentResolver;
|
||||
@Mock
|
||||
private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
new GnssSatelliteBlacklistHelper(mContext, Looper.myLooper(), mCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blacklistOf2Satellites_callbackIsCalled() {
|
||||
String blacklist = "3,0,5,24";
|
||||
updateBlacklistAndVerifyCallbackIsCalled(blacklist);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blacklistWithSpaces_callbackIsCalled() {
|
||||
String blacklist = "3, 11";
|
||||
updateBlacklistAndVerifyCallbackIsCalled(blacklist);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyBlacklist_callbackIsCalled() {
|
||||
String blacklist = "";
|
||||
updateBlacklistAndVerifyCallbackIsCalled(blacklist);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blacklistWithOddNumberOfValues_callbackIsNotCalled() {
|
||||
String blacklist = "3,0,5";
|
||||
updateBlacklistAndNotifyContentObserver(blacklist);
|
||||
verify(mCallback, never()).onUpdateSatelliteBlacklist(any(int[].class), any(int[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blacklistWithNegativeValue_callbackIsNotCalled() {
|
||||
String blacklist = "3,-11";
|
||||
updateBlacklistAndNotifyContentObserver(blacklist);
|
||||
verify(mCallback, never()).onUpdateSatelliteBlacklist(any(int[].class), any(int[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blacklistWithNonDigitCharacter_callbackIsNotCalled() {
|
||||
String blacklist = "3,1a,5,11";
|
||||
updateBlacklistAndNotifyContentObserver(blacklist);
|
||||
verify(mCallback, never()).onUpdateSatelliteBlacklist(any(int[].class), any(int[].class));
|
||||
}
|
||||
|
||||
private void updateBlacklistAndNotifyContentObserver(String blacklist) {
|
||||
Settings.Global.putString(mContentResolver,
|
||||
Settings.Global.GNSS_SATELLITE_BLACKLIST, blacklist);
|
||||
notifyContentObserverFor(Settings.Global.GNSS_SATELLITE_BLACKLIST);
|
||||
}
|
||||
|
||||
private void updateBlacklistAndVerifyCallbackIsCalled(String blacklist) {
|
||||
updateBlacklistAndNotifyContentObserver(blacklist);
|
||||
|
||||
ArgumentCaptor<int[]> constellationsCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
ArgumentCaptor<int[]> svIdsCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
verify(mCallback).onUpdateSatelliteBlacklist(constellationsCaptor.capture(),
|
||||
svIdsCaptor.capture());
|
||||
|
||||
int[] constellations = constellationsCaptor.getValue();
|
||||
int[] svIds = svIdsCaptor.getValue();
|
||||
List<Integer> values = GnssSatelliteBlacklistHelper.parseSatelliteBlacklist(blacklist);
|
||||
assertThat(values.size()).isEqualTo(constellations.length * 2);
|
||||
assertThat(svIds.length).isEqualTo(constellations.length);
|
||||
for (int i = 0; i < constellations.length; i++) {
|
||||
assertThat(constellations[i]).isEqualTo(values.get(i * 2));
|
||||
assertThat(svIds[i]).isEqualTo(values.get(i * 2 + 1));
|
||||
}
|
||||
}
|
||||
|
||||
private static void notifyContentObserverFor(String globalSetting) {
|
||||
Collection<ContentObserver> contentObservers =
|
||||
Shadows.shadowOf(RuntimeEnvironment.application.getContentResolver())
|
||||
.getContentObservers(Settings.Global.getUriFor(globalSetting));
|
||||
assertThat(contentObservers).isNotEmpty();
|
||||
contentObservers.iterator().next().onChange(false /* selfChange */);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user