Merge "Validate cached allowed state when MCC change." into main
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 611b6a2..2cd0336 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -13972,9 +13972,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
SubscriptionManager.INVALID_SUBSCRIPTION_ID,
"setCachedLocationCountryCode");
- return TelephonyCountryDetector.getInstance(getDefaultPhone().getContext()).setCountryCodes(
- reset, currentNetworkCountryCodes, cachedNetworkCountryCodes, locationCountryCode,
- locationCountryCodeTimestampNanos);
+ return TelephonyCountryDetector.getInstance(getDefaultPhone().getContext(), mFeatureFlags)
+ .setCountryCodes(reset, currentNetworkCountryCodes, cachedNetworkCountryCodes,
+ locationCountryCode, locationCountryCodeTimestampNanos);
}
/**
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index d6a9b37..75a1fb4 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -85,7 +85,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
-import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -130,10 +129,11 @@
private static final boolean DEBUG = !"user".equals(Build.TYPE);
private static final int MAX_CACHE_SIZE = 50;
- private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 1;
+ protected static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 1;
protected static final int EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT = 2;
protected static final int EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT = 3;
protected static final int EVENT_CONFIG_DATA_UPDATED = 4;
+ protected static final int CMD_HANDLE_COUNTRY_CODE_CHANGED = 5;
private static SatelliteAccessController sInstance;
@@ -224,6 +224,25 @@
@Nullable
private PersistentLogger mPersistentLogger = null;
+ private final Object mPossibleChangeInSatelliteAllowedRegionLock = new Object();
+ @GuardedBy("mPossibleChangeInSatelliteAllowedRegionLock")
+ private boolean mIsSatelliteAllowedRegionPossiblyChanged = false;
+ protected long mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos = 0;
+
+ protected int mRetryCountForValidatingPossibleChangeInAllowedRegion;
+ protected static final int
+ DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION = 10;
+ protected static final int
+ DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION = 3;
+ protected static final int DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES = 10;
+
+ private long mRetryIntervalToEvaluateUserInSatelliteAllowedRegion = 0;
+ private int mMaxRetryCountForValidatingPossibleChangeInAllowedRegion = 0;
+ private long mLocationQueryThrottleIntervalNanos = 0;
+
+ @NonNull
+ protected ResultReceiver mHandlerForSatelliteAllowedResult;
+
/**
* Map key: binder of the callback, value: callback to receive the satellite communication
* allowed state changed events.
@@ -234,10 +253,11 @@
@GuardedBy("mSatelliteCommunicationAllowStateLock")
private boolean mCurrentSatelliteAllowedState = false;
- private static final long ALLOWED_STATE_CACHE_VALID_DURATION_HOURS =
- Duration.ofHours(4).toNanos();
+ protected static final long ALLOWED_STATE_CACHE_VALID_DURATION_NANOS =
+ TimeUnit.HOURS.toNanos(4);
+
private boolean mLatestSatelliteCommunicationAllowed;
- private long mLatestSatelliteCommunicationAllowedSetTime;
+ protected long mLatestSatelliteCommunicationAllowedSetTime;
private long mLocationQueryStartTimeMillis;
private long mOnDeviceLookupStartTimeMillis;
@@ -249,10 +269,13 @@
* @param context The context associated with the
* {@link SatelliteAccessController} instance.
* @param featureFlags The FeatureFlags that are supported.
- * @param locationManager The LocationManager for querying current location of
+ * @param locationManager The LocationManager for querying current
+ * location of
* the device.
- * @param looper The Looper to run the SatelliteAccessController on.
- * @param satelliteOnDeviceAccessController The on-device satellite access controller instance.
+ * @param looper The Looper to run the SatelliteAccessController
+ * on.
+ * @param satelliteOnDeviceAccessController The on-device satellite access controller
+ * instance.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected SatelliteAccessController(@NonNull Context context,
@@ -269,7 +292,13 @@
mLocationManager = locationManager;
mTelecomManager = telecomManager;
mSatelliteOnDeviceAccessController = satelliteOnDeviceAccessController;
- mCountryDetector = TelephonyCountryDetector.getInstance(context);
+
+ mCountryDetector = TelephonyCountryDetector.getInstance(context, mFeatureFlags);
+ mCountryDetector.registerForCountryCodeChanged(this,
+ CMD_HANDLE_COUNTRY_CODE_CHANGED, null);
+ initializeHandlerForSatelliteAllowedResult();
+ setIsSatelliteAllowedRegionPossiblyChanged(false);
+
mSatelliteController = SatelliteController.getInstance();
mControllerMetricsStats = ControllerMetricsStats.getInstance();
mAccessControllerMetricsStats = AccessControllerMetricsStats.getInstance();
@@ -391,6 +420,9 @@
AsyncResult ar = (AsyncResult) msg.obj;
updateSatelliteConfigData((Context) ar.userObj);
break;
+ case CMD_HANDLE_COUNTRY_CODE_CHANGED:
+ handleSatelliteAllowedRegionPossiblyChanged();
+ break;
default:
plogw("SatelliteAccessControllerHandler: unexpected message code: " + msg.what);
break;
@@ -752,6 +784,11 @@
mLocationFreshDurationNanos = getSatelliteLocationFreshDurationFromOverlayConfig(context);
mAccessControllerMetricsStats.setConfigDataSource(
SatelliteConstants.CONFIG_DATA_SOURCE_DEVICE_CONFIG);
+ mRetryIntervalToEvaluateUserInSatelliteAllowedRegion =
+ getDelayBeforeRetryValidatingPossibleChangeInSatelliteAllowedRegionMillis(context);
+ mMaxRetryCountForValidatingPossibleChangeInAllowedRegion =
+ getMaxRetryCountForValidatingPossibleChangeInAllowedRegion(context);
+ mLocationQueryThrottleIntervalNanos = getLocationQueryThrottleIntervalNanos(context);
}
private void loadConfigUpdaterConfigs() {
@@ -938,11 +975,15 @@
}
mSatelliteAllowResultReceivers.clear();
}
+ if (!shouldRetryValidatingPossibleChangeInAllowedRegion(resultCode)) {
+ setIsSatelliteAllowedRegionPossiblyChanged(false);
+ }
reportMetrics(resultCode, allowed);
}
/**
- * Telephony-internal logic to verify if satellite access is restricted at the current location.
+ * Telephony-internal logic to verify if satellite access is restricted at the current
+ * location.
*/
private void checkSatelliteAccessRestrictionForCurrentLocation() {
synchronized (mLock) {
@@ -972,6 +1013,89 @@
}
}
+ private boolean shouldRetryValidatingPossibleChangeInAllowedRegion(int resultCode) {
+ return (resultCode == SATELLITE_RESULT_LOCATION_NOT_AVAILABLE);
+ }
+
+ private void initializeHandlerForSatelliteAllowedResult() {
+ mHandlerForSatelliteAllowedResult = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ plogd("query satellite allowed for current "
+ + "location, resultCode=" + resultCode + ", resultData=" + resultData);
+ synchronized (mPossibleChangeInSatelliteAllowedRegionLock) {
+ if (shouldRetryValidatingPossibleChangeInAllowedRegion(resultCode)
+ && (mRetryCountForValidatingPossibleChangeInAllowedRegion
+ < mMaxRetryCountForValidatingPossibleChangeInAllowedRegion)) {
+ mRetryCountForValidatingPossibleChangeInAllowedRegion++;
+ plogd("mRetryCountForValidatingPossibleChangeInAllowedRegion is "
+ + mRetryCountForValidatingPossibleChangeInAllowedRegion);
+ sendDelayedRequestAsync(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED,
+ new Pair<>(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mHandlerForSatelliteAllowedResult),
+ mRetryIntervalToEvaluateUserInSatelliteAllowedRegion);
+ } else {
+ mRetryCountForValidatingPossibleChangeInAllowedRegion = 0;
+ plogd("Stop retry validating the possible change in satellite allowed "
+ + "region");
+ }
+ }
+ }
+ };
+ }
+
+ private void handleSatelliteAllowedRegionPossiblyChanged() {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ ploge("handleSatelliteAllowedRegionPossiblyChanged: "
+ + "The feature flag oemEnabledSatelliteFlag() is not enabled");
+ return;
+ }
+ synchronized (mPossibleChangeInSatelliteAllowedRegionLock) {
+ logd("handleSatelliteAllowedRegionPossiblyChanged");
+ setIsSatelliteAllowedRegionPossiblyChanged(true);
+ requestIsCommunicationAllowedForCurrentLocation(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mHandlerForSatelliteAllowedResult);
+ }
+ }
+
+ protected boolean allowLocationQueryForSatelliteAllowedCheck() {
+ synchronized (mPossibleChangeInSatelliteAllowedRegionLock) {
+ if (!isCommunicationAllowedCacheValid()) {
+ logd("allowLocationQueryForSatelliteAllowedCheck: cache is not valid");
+ return true;
+ }
+
+ if (isSatelliteAllowedRegionPossiblyChanged() && !isLocationQueryThrottled()) {
+ logd("allowLocationQueryForSatelliteAllowedCheck: location query is not throttled");
+ return true;
+ }
+ }
+ logd("allowLocationQueryForSatelliteAllowedCheck: false");
+ return false;
+ }
+
+ private boolean isLocationQueryThrottled() {
+ if (mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos == 0) {
+ plogv("isLocationQueryThrottled: "
+ + "mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos is 0, return "
+ + "false");
+ return false;
+ }
+
+ long currentTime = getElapsedRealtimeNanos();
+ if (currentTime - mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos
+ > mLocationQueryThrottleIntervalNanos) {
+ plogv("isLocationQueryThrottled: currentTime - "
+ + "mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos is "
+ + "bigger than " + mLocationQueryThrottleIntervalNanos + " so return false");
+ return false;
+ }
+
+ plogd("isLocationQueryThrottled : true");
+ return true;
+ }
+
/**
* Telephony-internal logic to verify if satellite access is restricted from the location query.
*/
@@ -982,14 +1106,14 @@
} else {
if (mLocationManager.isLocationEnabled()) {
plogd("location query is allowed");
- if (isCommunicationAllowedCacheValid()) {
+ if (allowLocationQueryForSatelliteAllowedCheck()) {
+ executeLocationQuery();
+ } else {
Bundle bundle = new Bundle();
bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED,
mLatestSatelliteCommunicationAllowed);
sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
mLatestSatelliteCommunicationAllowed);
- } else {
- executeLocationQuery();
}
} else {
plogv("location query is not allowed");
@@ -1006,9 +1130,9 @@
*/
private boolean isCommunicationAllowedCacheValid() {
if (mLatestSatelliteCommunicationAllowedSetTime > 0) {
- long currentTime = SystemClock.elapsedRealtimeNanos();
+ long currentTime = getElapsedRealtimeNanos();
if ((currentTime - mLatestSatelliteCommunicationAllowedSetTime)
- <= ALLOWED_STATE_CACHE_VALID_DURATION_HOURS) {
+ <= ALLOWED_STATE_CACHE_VALID_DURATION_NANOS) {
logv("isCommunicationAllowedCacheValid: cache is valid");
return true;
}
@@ -1018,7 +1142,15 @@
}
private void executeLocationQuery() {
- plogv("executeLocationQuery");
+ plogd("executeLocationQuery");
+ synchronized (mPossibleChangeInSatelliteAllowedRegionLock) {
+ if (isSatelliteAllowedRegionPossiblyChanged()) {
+ mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos =
+ getElapsedRealtimeNanos();
+ plogd("mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos is set "
+ + mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos);
+ }
+ }
synchronized (mLock) {
mFreshLastKnownLocation = getFreshLastKnownLocation();
checkSatelliteAccessRestrictionUsingOnDeviceData();
@@ -1167,7 +1299,7 @@
sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
satelliteAllowed);
mLatestSatelliteCommunicationAllowed = satelliteAllowed;
- mLatestSatelliteCommunicationAllowedSetTime = SystemClock.elapsedRealtimeNanos();
+ mLatestSatelliteCommunicationAllowedSetTime = getElapsedRealtimeNanos();
persistLatestSatelliteCommunicationAllowedState();
} catch (Exception ex) {
ploge("checkSatelliteAccessRestrictionForLocation: ex=" + ex);
@@ -1267,6 +1399,9 @@
long lastKnownLocationAge =
getElapsedRealtimeNanos() - lastKnownLocation.getElapsedRealtimeNanos();
if (lastKnownLocationAge <= getLocationFreshDurationNanos()) {
+ plogd("getFreshLastKnownLocation: lat=" + Rlog.pii(TAG,
+ lastKnownLocation.getLatitude())
+ + ", long=" + Rlog.pii(TAG, lastKnownLocation.getLongitude()));
return lastKnownLocation;
}
}
@@ -1436,6 +1571,63 @@
}
@NonNull
+ private static long getDelayBeforeRetryValidatingPossibleChangeInSatelliteAllowedRegionMillis(
+ @NonNull Context context) {
+ Integer retryDuration = null;
+ try {
+ retryDuration = context.getResources().getInteger(com.android.internal.R.integer
+ .config_satellite_delay_minutes_before_retry_validating_possible_change_in_allowed_region);
+ } catch (Resources.NotFoundException ex) {
+ loge("getDelayBeforeRetryValidatingPossibleChangeInSatelliteAllowedRegionMillis: got "
+ + "ex=" + ex);
+ }
+ if (retryDuration == null) {
+ logd("Use default retry duration for possible change satellite allowed region ="
+ + DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION);
+ retryDuration =
+ DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+ }
+ return TimeUnit.MINUTES.toMillis(retryDuration);
+ }
+
+ @NonNull
+ private static int getMaxRetryCountForValidatingPossibleChangeInAllowedRegion(
+ @NonNull Context context) {
+ Integer maxRetrycount = null;
+ try {
+ maxRetrycount = context.getResources().getInteger(com.android.internal.R.integer
+ .config_satellite_max_retry_count_for_validating_possible_change_in_allowed_region);
+ } catch (Resources.NotFoundException ex) {
+ loge("getMaxRetryCountForValidatingPossibleChangeInAllowedRegion: got ex= " + ex);
+ }
+ if (maxRetrycount == null) {
+ logd("Use default max retry count for possible change satellite allowed region ="
+ + DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION);
+ maxRetrycount =
+ DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+ }
+ return maxRetrycount;
+ }
+
+ @NonNull
+ private static long getLocationQueryThrottleIntervalNanos(@NonNull Context context) {
+ Integer throttleInterval = null;
+ try {
+ throttleInterval = context.getResources().getInteger(com.android.internal.R.integer
+ .config_satellite_location_query_throttle_interval_minutes);
+ } catch (Resources.NotFoundException ex) {
+ loge("getLocationQueryThrottleIntervalNanos: got ex=" + ex);
+ }
+ if (throttleInterval == null) {
+ logd("Use default location query throttle interval ="
+ + DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES);
+ throttleInterval =
+ DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES;
+ }
+ return TimeUnit.MINUTES.toNanos(throttleInterval);
+ }
+
+ @NonNull
private static String[] readStringArrayFromOverlayConfig(
@NonNull Context context, @ArrayRes int id) {
String[] strArray = null;
@@ -1525,6 +1717,17 @@
* @param command command to be executed on the main thread
* @param argument additional parameters required to perform of the operation
*/
+ private void sendDelayedRequestAsync(int command, @NonNull Object argument, long dealyMillis) {
+ Message msg = this.obtainMessage(command, argument);
+ sendMessageDelayed(msg, dealyMillis);
+ }
+
+ /**
+ * Posts the specified command to be executed on the main thread and returns immediately.
+ *
+ * @param command command to be executed on the main thread
+ * @param argument additional parameters required to perform of the operation
+ */
private void sendRequestAsync(int command, @NonNull Object argument) {
Message msg = this.obtainMessage(command, argument);
msg.sendToTarget();
@@ -1550,11 +1753,6 @@
mSatelliteCommunicationAllowedStateChangedListeners.put(callback.asBinder(), callback);
- if (!mFeatureFlags.geofenceEnhancementForBetterUx()) {
- plogd("The feature flag geofenceEnhancementForBetterUx is not enabled");
- return SATELLITE_RESULT_SUCCESS;
- }
-
this.post(() -> {
try {
synchronized (mSatelliteCommunicationAllowStateLock) {
@@ -1596,7 +1794,7 @@
* This API can be used by only CTS to set the cache whether satellite communication is allowed.
*
* @param state a state indicates whether satellite access allowed state should be cached and
- * the allowed state.
+ * the allowed state.
* @return {@code true} if the setting is successful, {@code false} otherwise.
*/
public boolean setIsSatelliteCommunicationAllowedForCurrentLocationCache(String state) {
@@ -1616,7 +1814,7 @@
synchronized (mSatelliteCommunicationAllowStateLock) {
if ("cache_allowed".equalsIgnoreCase(state)) {
- mLatestSatelliteCommunicationAllowedSetTime = SystemClock.elapsedRealtimeNanos();
+ mLatestSatelliteCommunicationAllowedSetTime = getElapsedRealtimeNanos();
mLatestSatelliteCommunicationAllowed = true;
mCurrentSatelliteAllowedState = true;
} else if ("cache_clear_and_not_allowed".equalsIgnoreCase(state)) {
@@ -1673,6 +1871,19 @@
mTotalCheckingStartTimeMillis = 0;
}
+ protected boolean isSatelliteAllowedRegionPossiblyChanged() {
+ synchronized (mPossibleChangeInSatelliteAllowedRegionLock) {
+ return mIsSatelliteAllowedRegionPossiblyChanged;
+ }
+ }
+
+ protected void setIsSatelliteAllowedRegionPossiblyChanged(boolean changed) {
+ synchronized (mPossibleChangeInSatelliteAllowedRegionLock) {
+ plogd("setIsSatelliteAllowedRegionPossiblyChanged : " + changed);
+ mIsSatelliteAllowedRegionPossiblyChanged = changed;
+ }
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
index 8eba53b..cbca7b7 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -22,8 +22,14 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.ALLOWED_STATE_CACHE_VALID_DURATION_NANOS;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.CMD_HANDLE_COUNTRY_CODE_CHANGED;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.CMD_IS_SATELLITE_COMMUNICATION_ALLOWED;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_CONFIG_DATA_UPDATED;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.GOOGLE_US_SAN_SAT_S2_FILE_NAME;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -34,10 +40,12 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -63,6 +71,7 @@
import android.os.Message;
import android.os.ResultReceiver;
import android.telecom.TelecomManager;
+import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteManager;
import android.testing.TestableLooper;
import android.util.Log;
@@ -111,6 +120,8 @@
private static final int TEST_LOCATION_FRESH_DURATION_SECONDS = 10;
private static final long TEST_LOCATION_FRESH_DURATION_NANOS =
TimeUnit.SECONDS.toNanos(TEST_LOCATION_FRESH_DURATION_SECONDS);
+ private static final long TEST_LOCATION_QUERY_THROTTLE_INTERVAL_NANOS =
+ TimeUnit.MINUTES.toNanos(10); // DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES
private static final long TIMEOUT = 500;
private static final List<String> EMPTY_STRING_LIST = new ArrayList<>();
private static final List<String> LOCATION_PROVIDERS =
@@ -170,6 +181,13 @@
private ArgumentCaptor<Integer> mConfigUpdateIntCaptor;
@Captor
private ArgumentCaptor<Object> mConfigUpdateObjectCaptor;
+ @Captor
+ private ArgumentCaptor<Handler> mCountryDetectorHandlerCaptor;
+ @Captor
+ private ArgumentCaptor<Integer> mCountryDetectorIntCaptor;
+ @Captor
+ private ArgumentCaptor<Object> mCountryDetectorObjCaptor;
+
private boolean mQueriedSatelliteAllowed = false;
private int mQueriedSatelliteAllowedResultCode = SATELLITE_RESULT_SUCCESS;
private Semaphore mSatelliteAllowedSemaphore = new Semaphore(0);
@@ -243,6 +261,17 @@
when(mMockResources.getInteger(com.android.internal.R.integer
.config_oem_enabled_satellite_location_fresh_duration))
.thenReturn(TEST_LOCATION_FRESH_DURATION_SECONDS);
+ when(mMockResources.getInteger(com.android.internal.R.integer
+ .config_satellite_delay_minutes_before_retry_validating_possible_change_in_allowed_region))
+ .thenReturn(
+ DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION);
+ when(mMockResources.getInteger(com.android.internal.R.integer
+ .config_satellite_max_retry_count_for_validating_possible_change_in_allowed_region))
+ .thenReturn(
+ DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION);
+ when(mMockResources.getInteger(com.android.internal.R.integer
+ .config_satellite_location_query_throttle_interval_minutes))
+ .thenReturn(DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES);
when(mMockLocationManager.getProviders(true)).thenReturn(LOCATION_PROVIDERS);
when(mMockLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER))
@@ -266,8 +295,12 @@
.putBoolean(anyString(), anyBoolean());
doReturn(mMockSharedPreferencesEditor).when(mMockSharedPreferencesEditor)
.putStringSet(anyString(), any());
+ doReturn(mMockSharedPreferencesEditor).when(mMockSharedPreferencesEditor)
+ .putLong(anyString(), anyLong());
+ doNothing().when(mMockSharedPreferencesEditor).apply();
when(mMockFeatureFlags.satellitePersistentLogging()).thenReturn(true);
+ when(mMockFeatureFlags.geofenceEnhancementForBetterUx()).thenReturn(true);
mSatelliteAccessControllerUT = new TestSatelliteAccessController(mMockContext,
mMockFeatureFlags, mLooper, mMockLocationManager, mMockTelecomManager,
@@ -457,6 +490,136 @@
}
@Test
+ public void testAllowLocationQueryForSatelliteAllowedCheck() {
+ mSatelliteAccessControllerUT.mLatestSatelliteCommunicationAllowedSetTime = 1;
+
+ mSatelliteAccessControllerUT.setIsSatelliteAllowedRegionPossiblyChanged(false);
+ // cash is invalid
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos =
+ ALLOWED_STATE_CACHE_VALID_DURATION_NANOS + 10;
+ assertTrue(mSatelliteAccessControllerUT.allowLocationQueryForSatelliteAllowedCheck());
+
+ // cash is valid
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos =
+ ALLOWED_STATE_CACHE_VALID_DURATION_NANOS - 10;
+ assertFalse(mSatelliteAccessControllerUT.allowLocationQueryForSatelliteAllowedCheck());
+
+ mSatelliteAccessControllerUT.setIsSatelliteAllowedRegionPossiblyChanged(true);
+ // cash is invalid
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos =
+ ALLOWED_STATE_CACHE_VALID_DURATION_NANOS + 10;
+ assertTrue(mSatelliteAccessControllerUT.allowLocationQueryForSatelliteAllowedCheck());
+
+ // cash is valid and throttled
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos =
+ ALLOWED_STATE_CACHE_VALID_DURATION_NANOS - 10;
+
+ // cash is valid and never queried before
+ mSatelliteAccessControllerUT.mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos = 0;
+ assertTrue(mSatelliteAccessControllerUT.allowLocationQueryForSatelliteAllowedCheck());
+
+ // cash is valid and throttled
+ mSatelliteAccessControllerUT.mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos =
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos
+ - TEST_LOCATION_QUERY_THROTTLE_INTERVAL_NANOS + 100;
+ assertFalse(mSatelliteAccessControllerUT.allowLocationQueryForSatelliteAllowedCheck());
+
+ // cash is valid and not throttled
+ mSatelliteAccessControllerUT.mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos =
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos
+ - TEST_LOCATION_QUERY_THROTTLE_INTERVAL_NANOS - 100;
+ assertTrue(mSatelliteAccessControllerUT.allowLocationQueryForSatelliteAllowedCheck());
+ }
+
+ @Test
+ public void testValidatePossibleChangeInSatelliteAllowedRegion() throws Exception {
+ // OEM-enabled satellite is supported
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ verify(mMockCountryDetector).registerForCountryCodeChanged(
+ mCountryDetectorHandlerCaptor.capture(), mCountryDetectorIntCaptor.capture(),
+ mCountryDetectorObjCaptor.capture());
+
+ assertSame(mCountryDetectorHandlerCaptor.getValue(), mSatelliteAccessControllerUT);
+ assertSame(mCountryDetectorIntCaptor.getValue(), CMD_HANDLE_COUNTRY_CODE_CHANGED);
+ assertNull(mCountryDetectorObjCaptor.getValue());
+
+ // Normal case that invokes
+ // mMockSatelliteOnDeviceAccessController.isSatCommunicationAllowedAtLocation
+ clearInvocations(mMockSatelliteOnDeviceAccessController);
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ doReturn(true).when(mMockLocationManager).isLocationEnabled();
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS;
+ sendCommandValidateCountryCodeChangeEvent(mMockContext);
+ verify(mMockSatelliteOnDeviceAccessController,
+ times(1)).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+
+ // Case that isCommunicationAllowedCacheValid is true
+ clearInvocations(mMockSatelliteOnDeviceAccessController);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
+ sendCommandValidateCountryCodeChangeEvent(mMockContext);
+ verify(mMockSatelliteOnDeviceAccessController, never()).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+
+ // Case that mLatestCacheEnforcedValidateTimeNanos is over
+ // ALLOWED_STATE_CACHE_VALIDATE_INTERVAL_NANOS (1hours)
+ clearInvocations(mMockSatelliteOnDeviceAccessController);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos =
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos
+ + TEST_LOCATION_QUERY_THROTTLE_INTERVAL_NANOS + 1;
+ when(mMockLocation0.getElapsedRealtimeNanos())
+ .thenReturn(mSatelliteAccessControllerUT.elapsedRealtimeNanos + 1L);
+ when(mMockLocation1.getElapsedRealtimeNanos())
+ .thenReturn(mSatelliteAccessControllerUT.elapsedRealtimeNanos + 1L);
+ when(mMockLocation0.getLatitude()).thenReturn(2.0);
+ when(mMockLocation0.getLongitude()).thenReturn(2.0);
+ when(mMockLocation1.getLatitude()).thenReturn(3.0);
+ when(mMockLocation1.getLongitude()).thenReturn(3.0);
+ when(mMockSatelliteOnDeviceAccessController.isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class))).thenReturn(false);
+ sendCommandValidateCountryCodeChangeEvent(mMockContext);
+ verify(mMockSatelliteOnDeviceAccessController,
+ times(1)).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ }
+
+ @Test
+ public void testRetryValidatePossibleChangeInSatelliteAllowedRegion() throws Exception {
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ verify(mMockCountryDetector).registerForCountryCodeChanged(
+ mCountryDetectorHandlerCaptor.capture(), mCountryDetectorIntCaptor.capture(),
+ mCountryDetectorObjCaptor.capture());
+
+ assertSame(mCountryDetectorHandlerCaptor.getValue(), mSatelliteAccessControllerUT);
+ assertSame(mCountryDetectorIntCaptor.getValue(), CMD_HANDLE_COUNTRY_CODE_CHANGED);
+ assertNull(mCountryDetectorObjCaptor.getValue());
+
+ assertTrue(mSatelliteAccessControllerUT
+ .getRetryCountPossibleChangeInSatelliteAllowedRegion() == 0);
+
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_LOCATION_NOT_AVAILABLE);
+ sendCommandValidateCountryCodeChangeEvent(mMockContext);
+
+ assertTrue(mSatelliteAccessControllerUT
+ .getRetryCountPossibleChangeInSatelliteAllowedRegion() == 1);
+
+ mSatelliteAccessControllerUT.setRetryCountPossibleChangeInSatelliteAllowedRegion(
+ DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION);
+ sendSatelliteCommunicationAllowedEvent();
+ assertTrue(mSatelliteAccessControllerUT
+ .getRetryCountPossibleChangeInSatelliteAllowedRegion() == 0);
+
+ mSatelliteAccessControllerUT.setRetryCountPossibleChangeInSatelliteAllowedRegion(2);
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ sendSatelliteCommunicationAllowedEvent();
+ assertTrue(mSatelliteAccessControllerUT
+ .getRetryCountPossibleChangeInSatelliteAllowedRegion() == 0);
+ }
+
+ @Test
public void testUpdateSatelliteConfigData() throws Exception {
verify(mMockSatelliteController).registerForConfigUpdateChanged(
mConfigUpdateHandlerCaptor.capture(), mConfigUpdateIntCaptor.capture(),
@@ -528,6 +691,18 @@
verify(mMockCachedAccessRestrictionMap, times(1)).clear();
}
+ private void sendSatelliteCommunicationAllowedEvent() {
+ Pair<Integer, ResultReceiver> requestPair =
+ new Pair<>(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mSatelliteAccessControllerUT.getResultReceiverCurrentLocation());
+ Message msg = mSatelliteAccessControllerUT.obtainMessage(
+ CMD_IS_SATELLITE_COMMUNICATION_ALLOWED);
+ msg.obj = requestPair;
+ msg.sendToTarget();
+ mTestableLooper.processAllMessages();
+ }
+
+
private void sendConfigUpdateChangedEvent(Context context) {
Message msg = mSatelliteAccessControllerUT.obtainMessage(EVENT_CONFIG_DATA_UPDATED);
msg.obj = new AsyncResult(context, SATELLITE_RESULT_SUCCESS, null);
@@ -535,6 +710,13 @@
mTestableLooper.processAllMessages();
}
+ private void sendCommandValidateCountryCodeChangeEvent(Context context) {
+ Message msg = mSatelliteAccessControllerUT.obtainMessage(CMD_HANDLE_COUNTRY_CODE_CHANGED);
+ msg.obj = new AsyncResult(context, SATELLITE_RESULT_SUCCESS, null);
+ msg.sendToTarget();
+ mTestableLooper.processAllMessages();
+ }
+
private void clearAllInvocations() {
clearInvocations(mMockSatelliteController);
clearInvocations(mMockSatelliteOnDeviceAccessController);
@@ -678,5 +860,17 @@
public boolean isWaitForCurrentLocationTimerStarted() {
return hasMessages(EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT);
}
+
+ public int getRetryCountPossibleChangeInSatelliteAllowedRegion() {
+ return mRetryCountForValidatingPossibleChangeInAllowedRegion;
+ }
+
+ public void setRetryCountPossibleChangeInSatelliteAllowedRegion(int retryCount) {
+ mRetryCountForValidatingPossibleChangeInAllowedRegion = retryCount;
+ }
+
+ public ResultReceiver getResultReceiverCurrentLocation() {
+ return mHandlerForSatelliteAllowedResult;
+ }
}
}