reduce number of location query

1. remove query Country Code to prevent HW and AK gets satellute supported state
2. adopb 24hr location result cache to return when it is not emergency case.
3. Add an internal interface to set/clear 24Hr cache as CTS on CF can't
   do the location query

Bug: 340331500
Test: atest AccessControllerTest SatelliteManagerTest
SatelliteManagerTestOnMockService
    manually test using fake emergency call

Change-Id: I88c495ead4f12b3cf7c8a5b4f1752ef0912698e9
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index e66b784..df79da8 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -13869,6 +13869,32 @@
     }
 
     /**
+     * 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.
+     * @return {@code true} if the setting is successful, {@code false} otherwise.
+     */
+    public boolean setIsSatelliteCommunicationAllowedForCurrentLocationCache(String state) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            Log.d(LOG_TAG, "setIsSatelliteCommunicationAllowedForCurrentLocationCache: "
+                    + "oemEnabledSatelliteFlag is disabled");
+            return false;
+        }
+
+        Log.d(LOG_TAG, "setIsSatelliteCommunicationAllowedForCurrentLocationCache: "
+                + "state=" + state);
+        TelephonyPermissions.enforceShellOnly(
+                Binder.getCallingUid(),
+                "setIsSatelliteCommunicationAllowedForCurrentLocationCache");
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+                "setIsSatelliteCommunicationAllowedForCurrentLocationCache");
+        return mSatelliteAccessController.setIsSatelliteCommunicationAllowedForCurrentLocationCache(
+                state);
+    }
+
+    /**
      * Sets the service defined in ComponentName to be bound.
      *
      * This should only be used for testing.
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 23232ce..2ae8d28 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -207,6 +207,8 @@
             "set-oem-enabled-satellite-provision-status";
     private static final String SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE =
             "set-should-send-datagram-to-modem-in-demo-mode";
+    private static final String SET_IS_SATELLITE_COMMUNICATION_ALLOWED_FOR_CURRENT_LOCATION_CACHE =
+            "set-is-satellite-communication-allowed-for-current-location-cache";
 
     private static final String DOMAIN_SELECTION_SUBCOMMAND = "domainselection";
     private static final String DOMAIN_SELECTION_SET_SERVICE_OVERRIDE = "set-dss-override";
@@ -418,6 +420,8 @@
                 return handleSetCountryCodes();
             case SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS:
                 return handleSetOemEnabledSatelliteProvisionStatus();
+            case SET_IS_SATELLITE_COMMUNICATION_ALLOWED_FOR_CURRENT_LOCATION_CACHE:
+                return handleSetIsSatelliteCommunicationAllowedForCurrentLocationCache();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -3699,6 +3703,61 @@
         return 0;
     }
 
+    private int handleSetIsSatelliteCommunicationAllowedForCurrentLocationCache() {
+        PrintWriter errPw = getErrPrintWriter();
+        String opt;
+        String state;
+
+        if ((opt = getNextArg()) == null) {
+            errPw.println(
+                    "adb shell cmd phone set-is-satellite-communication-allowed-for-current"
+                            + "-location-cache :"
+                            + " Invalid Argument");
+            return -1;
+        } else {
+            switch (opt) {
+                case "-a": {
+                    state = "cache_allowed";
+                    break;
+                }
+                case "-n": {
+                    state = "cache_clear_and_not_allowed";
+                    break;
+                }
+                case "-c": {
+                    state = "clear_cache_only";
+                    break;
+                }
+                default:
+                    errPw.println(
+                            "adb shell cmd phone set-is-satellite-communication-allowed-for-current"
+                                    + "-location-cache :"
+                                    + " Invalid Argument");
+                    return -1;
+            }
+        }
+
+        Log.d(LOG_TAG, "handleSetIsSatelliteCommunicationAllowedForCurrentLocationCache("
+                + state + ")");
+
+        try {
+            boolean result = mInterface.setIsSatelliteCommunicationAllowedForCurrentLocationCache(
+                    state);
+            if (VDBG) {
+                Log.v(LOG_TAG, "setIsSatelliteCommunicationAllowedForCurrentLocationCache "
+                        + "returns: "
+                        + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "setIsSatelliteCommunicationAllowedForCurrentLocationCache("
+                    + state + "), error = " + e.getMessage());
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
     /**
      * Sample inputStr = "US,UK,CA;2,1,3"
      * Sample output: {[US,2], [UK,1], [CA,3]}
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index ccef8a9..acf1205 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -76,6 +76,7 @@
 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;
@@ -208,6 +209,10 @@
     @GuardedBy("mSatelliteCommunicationAllowStateLock")
     private boolean mCurrentSatelliteAllowedState = false;
 
+    private static final long NANOS_IN_DAY = Duration.ofDays(1).toNanos();
+    private boolean mLatestSatelliteCommunicationAllowed;
+    private long mLatestSatelliteCommunicationAllowedSetTime;
+
     /**
      * Create a SatelliteAccessController instance.
      *
@@ -791,7 +796,7 @@
                         sendSatelliteAllowResultToReceivers(resultCode, bundle, false);
                     } else {
                         logd("Satellite is provisioned");
-                        checkSatelliteAccessRestrictionForCurrentLocation();
+                        checkSatelliteAccessRestrictionUsingGPS();
                     }
                 } else {
                     loge("KEY_SATELLITE_PROVISIONED does not exist.");
@@ -842,6 +847,55 @@
     }
 
     /**
+     * Telephony-internal logic to verify if satellite access is restricted from the location query.
+     */
+    private void checkSatelliteAccessRestrictionUsingGPS() {
+        logv("checkSatelliteAccessRestrictionUsingGPS:");
+        if (isInEmergency()) {
+            executeLocationQuery();
+        } else {
+            if (mLocationManager.isLocationEnabled()) {
+                logd("location query is allowed");
+                if (isCommunicationAllowedCacheValid()) {
+                    Bundle bundle = new Bundle();
+                    bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED,
+                            mLatestSatelliteCommunicationAllowed);
+                    sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
+                            mLatestSatelliteCommunicationAllowed);
+                } else {
+                    executeLocationQuery();
+                }
+            } else {
+                logv("location query is not allowed");
+                Bundle bundle = new Bundle();
+                bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
+                sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle, false);
+            }
+        }
+    }
+
+    /* returns true,if the latest query was executed in 24Hr, or returns false. */
+    private boolean isCommunicationAllowedCacheValid() {
+        if (mLatestSatelliteCommunicationAllowedSetTime > 0) {
+            long currentTime = SystemClock.elapsedRealtimeNanos();
+            if ((currentTime - mLatestSatelliteCommunicationAllowedSetTime) <= NANOS_IN_DAY) {
+                logv("isCommunicationAllowedCacheValid: cache is valid");
+                return true;
+            }
+        }
+        logv("isCommunicationAllowedCacheValid: cache is expired");
+        return false;
+    }
+
+    private void executeLocationQuery() {
+        logv("executeLocationQuery");
+        synchronized (mLock) {
+            mFreshLastKnownLocation = getFreshLastKnownLocation();
+            checkSatelliteAccessRestrictionUsingOnDeviceData();
+        }
+    }
+
+    /**
      * This function synchronously checks if satellite is allowed at current location using cached
      * country codes.
      */
@@ -918,7 +972,18 @@
             if (location != null) {
                 checkSatelliteAccessRestrictionForLocation(location);
             } else {
-                checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+                logd("current location is not available");
+                Bundle bundle = new Bundle();
+                if (isCommunicationAllowedCacheValid()) {
+                    logd("onCurrentLocationAvailable: 24Hr cache is still valid, using it");
+                    bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED,
+                            mLatestSatelliteCommunicationAllowed);
+                    sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
+                            mLatestSatelliteCommunicationAllowed);
+                } else {
+                    bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
+                    sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle, false);
+                }
             }
         }
     }
@@ -936,7 +1001,10 @@
                 } else {
                     if (!initSatelliteOnDeviceAccessController()) {
                         loge("Failed to init SatelliteOnDeviceAccessController");
-                        checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+                        Bundle bundle = new Bundle();
+                        bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
+                        sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
+                                false);
                         return;
                     }
                     satelliteAllowed = mSatelliteOnDeviceAccessController
@@ -947,11 +1015,23 @@
                 bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, satelliteAllowed);
                 sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
                         satelliteAllowed);
+                mLatestSatelliteCommunicationAllowed = satelliteAllowed;
+                mLatestSatelliteCommunicationAllowedSetTime = SystemClock.elapsedRealtimeNanos();
             } catch (Exception ex) {
                 loge("checkSatelliteAccessRestrictionForLocation: ex=" + ex);
                 reportAnomaly(UUID_ON_DEVICE_LOOKUP_EXCEPTION,
                         "On-device satellite lookup exception");
-                checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+                Bundle bundle = new Bundle();
+                if (isCommunicationAllowedCacheValid()) {
+                    bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED,
+                            mLatestSatelliteCommunicationAllowed);
+                    logd("checkSatelliteAccessRestrictionForLocation: 24Hr cache is still valid, "
+                            + "using it");
+                } else {
+                    bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
+                }
+                sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
+                        mLatestSatelliteCommunicationAllowed);
             }
         }
     }
@@ -1327,6 +1407,49 @@
         mSatelliteCommunicationAllowedStateChangedListeners.remove(callback.asBinder());
     }
 
+    /**
+     * 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.
+     * @return {@code true} if the setting is successful, {@code false} otherwise.
+     */
+    public boolean setIsSatelliteCommunicationAllowedForCurrentLocationCache(String state) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            logd("setIsSatelliteCommunicationAllowedForCurrentLocationCache: "
+                    + "oemEnabledSatelliteFlag is disabled");
+            return false;
+        }
+
+        if (!isMockModemAllowed()) {
+            logd("setIsSatelliteCommunicationAllowedForCurrentLocationCache: "
+                    + "mock modem not allowed.");
+            return false;
+        }
+
+        logd("setIsSatelliteCommunicationAllowedForCurrentLocationCache: state=" + state);
+
+        synchronized (mSatelliteCommunicationAllowStateLock) {
+            if ("cache_allowed".equalsIgnoreCase(state)) {
+                mLatestSatelliteCommunicationAllowedSetTime = SystemClock.elapsedRealtimeNanos();
+                mLatestSatelliteCommunicationAllowed = true;
+                mCurrentSatelliteAllowedState = true;
+            } else if ("cache_clear_and_not_allowed".equalsIgnoreCase(state)) {
+                mLatestSatelliteCommunicationAllowedSetTime = 0;
+                mLatestSatelliteCommunicationAllowed = false;
+                mCurrentSatelliteAllowedState = false;
+            } else if ("clear_cache_only".equalsIgnoreCase(state)) {
+                mLatestSatelliteCommunicationAllowedSetTime = 0;
+                mLatestSatelliteCommunicationAllowed = false;
+            } else {
+                loge("setIsSatelliteCommunicationAllowedForCurrentLocationCache: invalid state="
+                        + state);
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void notifySatelliteCommunicationAllowedStateChanged(boolean allowState) {
         logd("notifySatelliteCommunicationAllowedStateChanged: allowState=" + allowState);
 
@@ -1355,4 +1478,8 @@
     private static void loge(@NonNull String log) {
         Rlog.e(TAG, log);
     }
+
+    private static void logv(@NonNull String log) {
+        Rlog.v(TAG, log);
+    }
 }