Merge "[NTN][Geofence] CTS for geofence enhancement" into main
diff --git a/assets/google_us_san_mtv_sat_s2.dat b/assets/google_us_san_mtv_sat_s2.dat
new file mode 100644
index 0000000..26516010
--- /dev/null
+++ b/assets/google_us_san_mtv_sat_s2.dat
Binary files differ
diff --git a/assets/satellite_access_config.json b/assets/satellite_access_config.json
new file mode 100644
index 0000000..4f9f853
--- /dev/null
+++ b/assets/satellite_access_config.json
@@ -0,0 +1,140 @@
+{
+    "access_control_configs": [
+        {
+            "config_id": 0,
+            "satellite_infos": [
+                {
+                    "satellite_id": "0db0312f-d73f-444d-b99b-a893dfb42edf",
+                    "satellite_position": {
+                        "longitude": -150.3,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        259,
+                        260
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3000,
+                            "end_earfcn": 4300
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                6,
+                7,
+                8
+            ]
+        },
+        {
+            "config_id": 1,
+            "satellite_infos": [
+                {
+                    "satellite_id": "1dec24f8-9223-4196-ad7a-a03002db7af7",
+                    "satellite_position": {
+                        "longitude": 15.5,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        257,
+                        258
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3200,
+                            "end_earfcn": 3200
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                9,
+                10,
+                11
+            ]
+        },
+        {
+            "config_id": 2,
+            "satellite_infos": [
+                {
+                    "satellite_id": "f60cb479-d85b-4f4e-b050-cc428f5eb4a4",
+                    "satellite_position": {
+                        "longitude": -150,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        259,
+                        260
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3300,
+                            "end_earfcn": 3400
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                12,
+                13,
+                14
+            ]
+        },
+        {
+            "config_id": 3,
+            "satellite_infos": [
+                {
+                    "satellite_id": "c5837d96-9585-46aa-8dd0-a974583737fb",
+                    "satellite_position": {
+                        "longitude": -155,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        261,
+                        262
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3500,
+                            "end_earfcn": 3600
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                15,
+                16,
+                17
+            ]
+        }
+        ,
+        {
+            "config_id": 4,
+            "satellite_infos": [
+                {
+                    "satellite_id": "6ef2a128-0477-4271-895f-dc4a221d2b23",
+                    "satellite_position": {
+                        "longitude": -66,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        263,
+                        264
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3700,
+                            "end_earfcn": 3800
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                18,
+                19,
+                20
+            ]
+        }
+    ]
+}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 0afb24f..495c7f2 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -14363,12 +14363,13 @@
      */
     public boolean setSatelliteAccessControlOverlayConfigs(boolean reset, boolean isAllowed,
             String s2CellFile, long locationFreshDurationNanos,
-            List<String> satelliteCountryCodes) {
+            List<String> satelliteCountryCodes, String satelliteAccessConfigurationFile) {
         Log.d(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: reset=" + reset
                 + ", isAllowed" + isAllowed + ", s2CellFile=" + s2CellFile
                 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
                 + ", satelliteCountryCodes=" + ((satelliteCountryCodes != null)
-                ? String.join(", ", satelliteCountryCodes) : null));
+                ? String.join(", ", satelliteCountryCodes) : null)
+                + ", satelliteAccessConfigurationFile=" + satelliteAccessConfigurationFile);
         TelephonyPermissions.enforceShellOnly(
                 Binder.getCallingUid(), "setSatelliteAccessControlOverlayConfigs");
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
@@ -14377,7 +14378,8 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             return mSatelliteAccessController.setSatelliteAccessControlOverlayConfigs(reset,
-                    isAllowed, s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
+                    isAllowed, s2CellFile, locationFreshDurationNanos, satelliteCountryCodes,
+                    satelliteAccessConfigurationFile);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 93ac55e..cd6a369 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -3593,9 +3593,11 @@
         String s2CellFile = null;
         long locationFreshDurationNanos = 0;
         List<String> satelliteCountryCodes = null;
+        String satelliteAccessConfigurationFile = null;
 
         String opt;
         while ((opt = getNextOption()) != null) {
+            Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: opt=" + opt);
             switch (opt) {
                 case "-r": {
                     reset = true;
@@ -3618,16 +3620,22 @@
                     satelliteCountryCodes = Arrays.asList(countryCodeStr.split(","));
                     break;
                 }
+                case "-g": {
+                    satelliteAccessConfigurationFile = getNextArgRequired();
+                    break;
+                }
             }
         }
         Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: reset=" + reset
                 + ", isAllowed=" + isAllowed + ", s2CellFile=" + s2CellFile
                 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
-                + ", satelliteCountryCodes=" + satelliteCountryCodes);
+                + ", satelliteCountryCodes=" + satelliteCountryCodes
+                + ", satelliteAccessConfigurationFile=" + satelliteAccessConfigurationFile);
 
         try {
             boolean result = mInterface.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
-                    s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
+                    s2CellFile, locationFreshDurationNanos, satelliteCountryCodes,
+                    satelliteAccessConfigurationFile);
             if (VDBG) {
                 Log.v(LOG_TAG, "setSatelliteAccessControlOverlayConfigs result =" + result);
             }
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index f17377c..c837772 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -285,6 +285,8 @@
     private boolean mOverriddenIsSatelliteAllowAccessControl;
     @Nullable
     private File mOverriddenSatelliteS2CellFile;
+    @Nullable
+    private String mOverriddenSatelliteConfigurationFileName;
     private long mOverriddenLocationFreshDurationNanos;
 
     @GuardedBy("mLock")
@@ -331,7 +333,12 @@
 
     /** These are used for CTS test */
     private Path mCtsSatS2FilePath = null;
+    private Path mCtsSatelliteAccessConfigurationFilePath = null;
     protected static final String GOOGLE_US_SAN_SAT_S2_FILE_NAME = "google_us_san_sat_s2.dat";
+    protected static final String GOOGLE_US_SAN_SAT_MTV_S2_FILE_NAME =
+            "google_us_san_mtv_sat_s2.dat";
+    protected static final String SATELLITE_ACCESS_CONFIG_FILE_NAME =
+            "satellite_access_config.json";
 
     /** These are for config updater config data */
     private static final String SATELLITE_ACCESS_CONTROL_DATA_DIR = "satellite_access_control";
@@ -614,8 +621,8 @@
                         mNewRegionalConfigId = null;
                     }
                 }
-                updateRegionalConfigId();
             }
+            updateRegionalConfigId();
         }
     }
 
@@ -759,7 +766,8 @@
      */
     public boolean setSatelliteAccessControlOverlayConfigs(boolean reset, boolean isAllowed,
             @Nullable String s2CellFile, long locationFreshDurationNanos,
-            @Nullable List<String> satelliteCountryCodes) {
+            @Nullable List<String> satelliteCountryCodes,
+            @Nullable String satelliteConfigurationFile) {
         if (!isMockModemAllowed()) {
             plogd("setSatelliteAccessControllerOverlayConfigs: mock modem is not allowed");
             return false;
@@ -768,7 +776,8 @@
                 + ", isAllowed" + isAllowed + ", s2CellFile=" + s2CellFile
                 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
                 + ", satelliteCountryCodes=" + ((satelliteCountryCodes != null)
-                ? String.join(", ", satelliteCountryCodes) : null));
+                ? String.join(", ", satelliteCountryCodes) : null)
+                + ", satelliteConfigurationFile=" + satelliteConfigurationFile);
         synchronized (mLock) {
             if (reset) {
                 mIsOverlayConfigOverridden = false;
@@ -784,9 +793,25 @@
                                 + " does not exist");
                         mOverriddenSatelliteS2CellFile = null;
                     }
+                    mCachedAccessRestrictionMap.clear();
                 } else {
                     mOverriddenSatelliteS2CellFile = null;
                 }
+                if (!TextUtils.isEmpty(satelliteConfigurationFile)) {
+                    File overriddenSatelliteConfigurationFile = getTestSatelliteConfiguration(
+                            satelliteConfigurationFile);
+                    if (overriddenSatelliteConfigurationFile.exists()) {
+                        mOverriddenSatelliteConfigurationFileName =
+                                overriddenSatelliteConfigurationFile.getAbsolutePath();
+                    } else {
+                        plogd("The overriding file "
+                                + overriddenSatelliteConfigurationFile.getAbsolutePath()
+                                + " does not exist");
+                        mOverriddenSatelliteConfigurationFileName = null;
+                    }
+                } else {
+                    mOverriddenSatelliteConfigurationFileName = null;
+                }
                 mOverriddenLocationFreshDurationNanos = locationFreshDurationNanos;
                 if (satelliteCountryCodes != null) {
                     mOverriddenSatelliteCountryCodes = satelliteCountryCodes;
@@ -824,8 +849,9 @@
 
     protected File getTestSatelliteS2File(String fileName) {
         plogd("getTestSatelliteS2File: fileName=" + fileName);
-        if (TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_S2_FILE_NAME)) {
-            mCtsSatS2FilePath = copyTestSatS2FileToPhoneDirectory(GOOGLE_US_SAN_SAT_S2_FILE_NAME);
+        if (TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_S2_FILE_NAME)
+                || TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_MTV_S2_FILE_NAME)) {
+            mCtsSatS2FilePath = copyTestAssetFileToPhoneDirectory(fileName);
             if (mCtsSatS2FilePath != null) {
                 return mCtsSatS2FilePath.toFile();
             } else {
@@ -835,8 +861,21 @@
         return new File(fileName);
     }
 
+    protected File getTestSatelliteConfiguration(String fileName) {
+        plogd("getTestSatelliteConfiguration: fileName=" + fileName);
+        if (TextUtils.equals(fileName, SATELLITE_ACCESS_CONFIG_FILE_NAME)) {
+            mCtsSatelliteAccessConfigurationFilePath = copyTestAssetFileToPhoneDirectory(fileName);
+            if (mCtsSatelliteAccessConfigurationFilePath != null) {
+                return mCtsSatelliteAccessConfigurationFilePath.toFile();
+            } else {
+                ploge("getTestSatelliteConfiguration: mCtsSatelliteConfigurationFilePath is null");
+            }
+        }
+        return new File(fileName);
+    }
+
     @Nullable
-    private static Path copyTestSatS2FileToPhoneDirectory(String sourceFileName) {
+    private static Path copyTestAssetFileToPhoneDirectory(String sourceFileName) {
         PhoneGlobals phoneGlobals = PhoneGlobals.getInstance();
         File ctsFile = phoneGlobals.getDir("cts", Context.MODE_PRIVATE);
         if (!ctsFile.exists()) {
@@ -844,26 +883,26 @@
         }
 
         Path targetDir = ctsFile.toPath();
-        Path targetSatS2FilePath = targetDir.resolve(sourceFileName);
+        Path targetFilePath = targetDir.resolve(sourceFileName);
         try {
             var assetManager = phoneGlobals.getAssets();
             if (assetManager == null) {
-                loge("copyTestSatS2FileToPhoneDirectory: no assets");
+                loge("copyTestAssetFileToPhoneDirectory: no assets");
                 return null;
             }
             InputStream inputStream = assetManager.open(sourceFileName);
             if (inputStream == null) {
-                loge("copyTestSatS2FileToPhoneDirectory: Resource=" + sourceFileName
+                loge("copyTestAssetFileToPhoneDirectory: Resource=" + sourceFileName
                         + " not found");
                 return null;
             } else {
-                Files.copy(inputStream, targetSatS2FilePath, StandardCopyOption.REPLACE_EXISTING);
+                Files.copy(inputStream, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
             }
         } catch (IOException ex) {
-            loge("copyTestSatS2FileToPhoneDirectory: ex=" + ex);
+            loge("copyTestAssetFileToPhoneDirectory: ex=" + ex);
             return null;
         }
-        return targetSatS2FilePath;
+        return targetFilePath;
     }
 
     @Nullable
@@ -1128,8 +1167,16 @@
     }
 
     protected void loadSatelliteAccessConfigurationFromDeviceConfig() {
-        String satelliteConfigurationFileName =
-                getSatelliteConfigurationFileNameFromOverlayConfig(mContext);
+        logd("loadSatelliteAccessConfigurationFromDeviceConfig:");
+        String satelliteConfigurationFileName;
+        synchronized (mLock) {
+            if (mIsOverlayConfigOverridden && mOverriddenSatelliteConfigurationFileName != null) {
+                satelliteConfigurationFileName = mOverriddenSatelliteConfigurationFileName;
+            } else {
+                satelliteConfigurationFileName = getSatelliteConfigurationFileNameFromOverlayConfig(
+                        mContext);
+            }
+        }
         loadSatelliteAccessConfigurationFromFile(satelliteConfigurationFileName);
     }