Merge "Pass emergency session information to modem" into 24D1-dev
diff --git a/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java b/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
index 4b10cae..f9261ff 100644
--- a/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
+++ b/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
@@ -24,6 +24,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.telephony.uicc.IccFileHandler;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.util.State;
@@ -40,11 +41,14 @@
     private static final int CMD_START = 1;
     private static final int CMD_PARAMS_READY = 2;
 
+    private final Object mLock = new Object();
     // members
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @GuardedBy("mLock")
     private CommandParamsFactory mCmdParamsFactory = null;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private RilMessage mCurrentRilMessage = null;
+    @GuardedBy("mLock")
     private Handler mCaller = null;
     private static int mSimCount = 0;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -113,9 +117,13 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     private void sendCmdForExecution(RilMessage rilMsg) {
-        Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
-                new RilMessage(rilMsg));
-        msg.sendToTarget();
+        synchronized (mLock) {
+            if (mCaller != null) {
+                Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
+                        new RilMessage(rilMsg));
+                msg.sendToTarget();
+            }
+        }
     }
 
     private RilMessageDecoder(Handler caller, IccFileHandler fh, Context context) {
@@ -125,8 +133,10 @@
         addState(mStateCmdParamsReady);
         setInitialState(mStateStart);
 
-        mCaller = caller;
-        mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh, context);
+        synchronized (mLock) {
+            mCaller = caller;
+            mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh, context);
+        }
     }
 
     private RilMessageDecoder() {
@@ -166,7 +176,7 @@
     }
 
     private boolean decodeMessageParams(RilMessage rilMsg) {
-        boolean decodingStarted;
+        boolean decodingStarted = false;
 
         mCurrentRilMessage = rilMsg;
         switch(rilMsg.mId) {
@@ -188,16 +198,21 @@
                 decodingStarted = false;
                 break;
             }
-            try {
-                // Start asynch parsing of the command parameters.
-                mCmdParamsFactory.make(BerTlv.decode(rawData));
-                decodingStarted = true;
-            } catch (ResultException e) {
-                // send to Service for proper RIL communication.
-                CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
-                mCurrentRilMessage.mResCode = e.result();
-                sendCmdForExecution(mCurrentRilMessage);
-                decodingStarted = false;
+
+            synchronized (mLock) {
+                if (mCmdParamsFactory != null) {
+                    try {
+                        // Start asynch parsing of the command parameters.
+                        mCmdParamsFactory.make(BerTlv.decode(rawData));
+                        decodingStarted = true;
+                    } catch (ResultException e) {
+                        // send to Service for proper RIL communication.
+                        CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
+                        mCurrentRilMessage.mResCode = e.result();
+                        sendCmdForExecution(mCurrentRilMessage);
+                        decodingStarted = false;
+                    }
+                }
             }
             break;
         default:
@@ -211,10 +226,16 @@
         quitNow();
         mStateStart = null;
         mStateCmdParamsReady = null;
-        mCmdParamsFactory.dispose();
-        mCmdParamsFactory = null;
+
+        synchronized (mLock) {
+            if (mCmdParamsFactory != null) {
+                mCmdParamsFactory.dispose();
+                mCmdParamsFactory = null;
+            }
+            mCaller = null;
+        }
+
         mCurrentRilMessage = null;
-        mCaller = null;
         mInstance = null;
     }
 }
diff --git a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
index 0db7844..85d5a35 100644
--- a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
+++ b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
@@ -20,12 +20,14 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
+import android.os.FileUtils;
 import android.util.Log;
-import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.satellite.SatelliteConfig;
 import com.android.internal.telephony.satellite.SatelliteConfigParser;
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.server.updates.ConfigUpdateInstallReceiver;
 
 import libcore.io.IoUtils;
@@ -33,6 +35,8 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 
@@ -43,7 +47,8 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected static final String UPDATE_DIR = "/data/misc/telephonyconfig";
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    protected static final String UPDATE_CONTENT_PATH = "telephony_config.pb";
+    protected static final String NEW_CONFIG_CONTENT_PATH = "new_telephony_config.pb";
+    protected static final String VALID_CONFIG_CONTENT_PATH = "valid_telephony_config.pb";
     protected static final String UPDATE_METADATA_PATH = "metadata/";
     public static final String VERSION = "version";
 
@@ -66,7 +71,7 @@
     }
 
     public TelephonyConfigUpdateInstallReceiver() {
-        super(UPDATE_DIR, UPDATE_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION);
+        super(UPDATE_DIR, NEW_CONFIG_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION);
     }
 
     /**
@@ -74,57 +79,94 @@
      */
     @Nullable
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    public byte[] getCurrentContent() {
+    public byte[] getContentFromContentPath(@NonNull File contentPath) {
         try {
-            return IoUtils.readFileAsByteArray(updateContent.getCanonicalPath());
+            return IoUtils.readFileAsByteArray(contentPath.getCanonicalPath());
         } catch (IOException e) {
-            Slog.i(TAG, "Failed to read current content, assuming first update!");
+            Log.e(TAG, "Failed to read current content : " + contentPath);
             return null;
         }
     }
 
+    /**
+     * @param parser target of validation.
+     * @return {@code true} if all the config data are valid {@code false} otherwise.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean isValidSatelliteCarrierConfigData(@NonNull ConfigParser parser) {
+        SatelliteConfig satelliteConfig = (SatelliteConfig) parser.getConfig();
+        if (satelliteConfig == null) {
+            Log.e(TAG, "satelliteConfig is null");
+            return false;
+        }
+
+        // If no carrier config exist then it is considered as a valid config
+        Set<Integer> carrierIds = satelliteConfig.getAllSatelliteCarrierIds();
+        for (int carrierId : carrierIds) {
+            Map<String, Set<Integer>> plmnsServices =
+                    satelliteConfig.getSupportedSatelliteServices(carrierId);
+            Set<String> plmns = plmnsServices.keySet();
+            for (String plmn : plmns) {
+                if (!TelephonyUtils.isValidPlmn(plmn)) {
+                    Log.e(TAG, "found invalid plmn : " + plmn);
+                    return false;
+                }
+                Set<Integer> serviceSet = plmnsServices.get(plmn);
+                for (int service : serviceSet) {
+                    if (!TelephonyUtils.isValidService(service)) {
+                        Log.e(TAG, "found invalid service : " + service);
+                        return false;
+                    }
+                }
+            }
+        }
+        Log.d(TAG, "the config data is valid");
+        return true;
+    }
+
+
     @Override
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
     public void postInstall(Context context, Intent intent) {
         Log.d(TAG, "Telephony config is updated in file partition");
-        ConfigParser updatedConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
-                getCurrentContent());
 
-        if (updatedConfigParser == null) {
-            Log.d(TAG, "updatedConfigParser is null");
+        ConfigParser newConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
+                getContentFromContentPath(updateContent));
+
+        if (newConfigParser == null) {
+            Log.e(TAG, "newConfigParser is null");
             return;
         }
 
-        boolean isParserChanged = false;
+        if (!isValidSatelliteCarrierConfigData(newConfigParser)) {
+            Log.e(TAG, "received config data has invalid satellite carrier config data");
+            return;
+        }
 
         synchronized (getInstance().mConfigParserLock) {
-            if (getInstance().mConfigParser == null) {
-                getInstance().mConfigParser = updatedConfigParser;
-                isParserChanged = true;
-            } else {
-                int updatedVersion = updatedConfigParser.mVersion;
+            if (getInstance().mConfigParser != null) {
+                int updatedVersion = newConfigParser.mVersion;
                 int previousVersion = getInstance().mConfigParser.mVersion;
                 Log.d(TAG, "previous version is " + previousVersion + " | updated version is "
                         + updatedVersion);
-                if (updatedVersion > previousVersion) {
-                    getInstance().mConfigParser = updatedConfigParser;
-                    isParserChanged = true;
+                if (updatedVersion <= previousVersion) {
+                    Log.e(TAG, "updatedVersion is smaller than previousVersion");
+                    return;
                 }
             }
+            getInstance().mConfigParser = newConfigParser;
+        }
+
+        if (!getInstance().mCallbackHashMap.keySet().isEmpty()) {
+            Iterator<Executor> iterator = getInstance().mCallbackHashMap.keySet().iterator();
+            while (iterator.hasNext()) {
+                Executor executor = iterator.next();
+                getInstance().mCallbackHashMap.get(executor).onChanged(newConfigParser);
+            }
         }
 
-        if (isParserChanged) {
-            if (getInstance().mCallbackHashMap.keySet().isEmpty()) {
-                Log.d(TAG, "mCallbackHashMap.keySet().isEmpty");
-                return;
-            }
-            Iterator<Executor> iterator =
-                    getInstance().mCallbackHashMap.keySet().iterator();
-            while (iterator.hasNext()) {
-                Executor executor = iterator.next();
-                getInstance().mCallbackHashMap.get(executor).onChanged(
-                        updatedConfigParser);
-            }
+        if (!copySourceFileToTargetFile(NEW_CONFIG_CONTENT_PATH, VALID_CONFIG_CONTENT_PATH)) {
+            Log.e(TAG, "fail to copy to the valid satellite carrier config data");
         }
     }
 
@@ -135,7 +177,9 @@
         synchronized (getInstance().mConfigParserLock) {
             if (getInstance().mConfigParser == null) {
                 Log.d(TAG, "CreateNewConfigParser with domain " + domain);
-                getInstance().mConfigParser = getNewConfigParser(domain, getCurrentContent());
+                getInstance().mConfigParser = getNewConfigParser(
+                        domain, getContentFromContentPath(new File(updateDir,
+                                VALID_CONFIG_CONTENT_PATH)));
             }
             return getInstance().mConfigParser;
         }
@@ -197,4 +241,35 @@
                 return null;
         }
     }
+
+    /**
+     * @param sourceFileName source file name
+     * @param targetFileName target file name
+     * @return {@code true} if successful, {@code false} otherwise
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean copySourceFileToTargetFile(
+            @NonNull String sourceFileName, @NonNull String targetFileName) {
+        try {
+            File sourceFile = new File(UPDATE_DIR, sourceFileName);
+            File targetFile = new File(UPDATE_DIR, targetFileName);
+            Log.d(TAG, "copy " + sourceFile.getName() + " >> " + targetFile.getName());
+
+            if (sourceFile.exists()) {
+                if (targetFile.exists()) {
+                    targetFile.delete();
+                }
+                FileUtils.copy(sourceFile, targetFile);
+                FileUtils.copyPermissions(sourceFile, targetFile);
+                Log.d(TAG, "success to copy the file " + sourceFile.getName() + " to "
+                        + targetFile.getName());
+                return true;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "copy error : " + e);
+            return false;
+        }
+        Log.d(TAG, "source file is not exist, no file to copy");
+        return false;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
index 60950f2..7aadf0d 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -139,6 +140,19 @@
     }
 
     /**
+     * Get carrier identifier set for the satellite
+     *
+     * @return carrier identifier set from the config data.
+     */
+    @NonNull
+    public Set<Integer> getAllSatelliteCarrierIds() {
+        if (mSupportedServicesPerCarrier != null) {
+            return new ArraySet<>(mSupportedServicesPerCarrier.keySet());
+        }
+        return new ArraySet<>();
+    }
+
+    /**
      * @return satellite region country codes
      */
     @NonNull
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 375528d..b0ed7f9 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -394,6 +394,8 @@
     private static final String NOTIFICATION_CHANNEL_ID = "satellite";
 
     private final RegistrantList mSatelliteConfigUpdateChangedRegistrants = new RegistrantList();
+    private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver;
+    private final UwbAdapterStateCallback mUwbAdapterStateCallback;
 
     /**
      * @return The singleton instance of SatelliteController.
@@ -463,6 +465,8 @@
         mContentResolver = mContext.getContentResolver();
         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
 
+        mBTWifiNFCSateReceiver = new BTWifiNFCStateReceiver();
+        mUwbAdapterStateCallback = new UwbAdapterStateCallback();
         initializeSatelliteModeRadios();
 
         ContentObserver satelliteModeRadiosContentObserver = new ContentObserver(this) {
@@ -526,11 +530,12 @@
      * Get satelliteConfig from SatelliteConfigParser
      */
     public SatelliteConfig getSatelliteConfig() {
-        if (getSatelliteConfigParser() == null) {
-            Log.d(TAG, "getSatelliteConfigParser() is not ready");
+        SatelliteConfigParser satelliteConfigParser = getSatelliteConfigParser();
+        if (satelliteConfigParser == null) {
+            Log.d(TAG, "satelliteConfigParser is not ready");
             return null;
         }
-        return (SatelliteConfig) getSatelliteConfigParser().getConfig();
+        return satelliteConfigParser.getConfig();
     }
 
     /**
@@ -545,8 +550,6 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected void initializeSatelliteModeRadios() {
         if (mContentResolver != null) {
-            BTWifiNFCStateReceiver bTWifiNFCSateReceiver = new BTWifiNFCStateReceiver();
-            UwbAdapterStateCallback uwbAdapterStateCallback = new UwbAdapterStateCallback();
             IntentFilter radioStateIntentFilter = new IntentFilter();
 
             synchronized (mRadioStateLock) {
@@ -600,7 +603,14 @@
                         radioStateIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
                     }
                 }
-                mContext.registerReceiver(bTWifiNFCSateReceiver, radioStateIntentFilter);
+
+                try {
+                    // Unregister receiver before registering it.
+                    mContext.unregisterReceiver(mBTWifiNFCSateReceiver);
+                } catch (IllegalArgumentException e) {
+                    logd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e);
+                }
+                mContext.registerReceiver(mBTWifiNFCSateReceiver, radioStateIntentFilter);
 
                 if (satelliteModeRadios.contains(Settings.Global.RADIO_UWB)) {
                     UwbManager uwbManager = mContext.getSystemService(UwbManager.class);
@@ -609,8 +619,10 @@
                         mUwbStateEnabled = uwbManager.isUwbEnabled();
                         final long identity = Binder.clearCallingIdentity();
                         try {
+                            // Unregister callback before registering it.
+                            uwbManager.unregisterAdapterStateCallback(mUwbAdapterStateCallback);
                             uwbManager.registerAdapterStateCallback(mContext.getMainExecutor(),
-                                    uwbAdapterStateCallback);
+                                    mUwbAdapterStateCallback);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
                         }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
index 629327d..0563481 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
@@ -16,34 +16,47 @@
 
 package com.android.internal.telephony.configupdate;
 
-import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.UPDATE_CONTENT_PATH;
+import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
+import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
+
+import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.NEW_CONFIG_CONTENT_PATH;
 import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.UPDATE_DIR;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeast;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.Intent;
+import android.util.ArraySet;
 
 import androidx.annotation.Nullable;
 
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.satellite.SatelliteConfig;
 import com.android.internal.telephony.satellite.SatelliteConfigParser;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -74,7 +87,7 @@
         TelephonyConfigUpdateInstallReceiver testReceiver =
                 new TelephonyConfigUpdateInstallReceiver();
         assertEquals(UPDATE_DIR, testReceiver.getUpdateDir().toString());
-        assertEquals(new File(new File(UPDATE_DIR), UPDATE_CONTENT_PATH).toString(),
+        assertEquals(new File(new File(UPDATE_DIR), NEW_CONFIG_CONTENT_PATH).toString(),
                 testReceiver.getUpdateContent().toString());
     }
 
@@ -92,38 +105,133 @@
         // create spyTelephonyConfigUpdateInstallReceiver
         TelephonyConfigUpdateInstallReceiver spyTelephonyConfigUpdateInstallReceiver =
                 spy(new TelephonyConfigUpdateInstallReceiver());
-
-        // mock BeforeParser
-        String mBase64StrForPBByteArray =
-                "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
-        byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
-        doReturn(mBytesProtoBuffer).when(
-                spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
-        SatelliteConfigParser mMockSatelliteConfigParserBefore =
-                spy(new SatelliteConfigParser(mBytesProtoBuffer));
-        doReturn(mMockSatelliteConfigParserBefore).when(
-                spyTelephonyConfigUpdateInstallReceiver).getConfigParser(DOMAIN_SATELLITE);
-
-        // mock UpdatedParser
-        SatelliteConfigParser spySatelliteConfigParserAfter =
-                spy(new SatelliteConfigParser(mBytesProtoBuffer));
-        doReturn(5).when(spySatelliteConfigParserAfter).getVersion();
-        doReturn(spySatelliteConfigParserAfter).when(spyTelephonyConfigUpdateInstallReceiver)
-                .getNewConfigParser(any(), any());
-
+        doReturn(true).when(spyTelephonyConfigUpdateInstallReceiver)
+                .copySourceFileToTargetFile(any(), any());
         replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
                 null, spyTelephonyConfigUpdateInstallReceiver);
 
         assertSame(spyTelephonyConfigUpdateInstallReceiver,
                 TelephonyConfigUpdateInstallReceiver.getInstance());
 
+        // valid config data case
+        // mVersion:4 | mSupportedServicesPerCarrier:{1={310160=[1, 2, 3], 310220=[3]}} |
+        // mSatelliteRegionCountryCodes:[US] | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+        String mBase64StrForPBByteArray =
+                "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+        byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+        doReturn(mBytesProtoBuffer).when(
+                spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+        // mock UpdatedParser
+        SatelliteConfigParser spyValidParser =
+                spy(new SatelliteConfigParser(mBytesProtoBuffer));
+
         ConcurrentHashMap<Executor, ConfigProviderAdaptor.Callback> spyCallbackHashMap = spy(
                 new ConcurrentHashMap<>());
         spyCallbackHashMap.put(mExecutor, mCallback);
         spyTelephonyConfigUpdateInstallReceiver.setCallbackMap(spyCallbackHashMap);
+
         spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
 
-        verify(spyCallbackHashMap, atLeast(1)).keySet();
+        verify(spyCallbackHashMap, times(2)).keySet();
+        verify(spyTelephonyConfigUpdateInstallReceiver, times(1))
+                .copySourceFileToTargetFile(any(), any());
+        Mockito.clearInvocations(spyCallbackHashMap);
+        Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+        replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "mConfigParser",
+                spyTelephonyConfigUpdateInstallReceiver, spyValidParser);
+
+        // valid config data but smaller version case
+        // mVersion:3 | mSupportedServicesPerCarrier:{1={12345=[1, 2]}} |
+        // mSatelliteRegionCountryCodes:[US] | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+        mBase64StrForPBByteArray =
+                "CicIAxIPCAESCwoFMTIzNDUQARACGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+        mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+
+        // mock UpdatedParser
+        SatelliteConfigParser spyInvalidParser =
+                spy(new SatelliteConfigParser(mBytesProtoBuffer));
+        doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+                .getNewConfigParser(any(), any());
+
+        spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+        verify(spyCallbackHashMap, times(0)).keySet();
+        verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+                .copySourceFileToTargetFile(any(), any());
+        Mockito.clearInvocations(spyCallbackHashMap);
+        Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+        // Empty config data case which is valid
+        // mSupportedServicesPerCarrier:{} | mSatelliteRegionCountryCodes:[US] |
+        // mIsSatelliteRegionAllowed:true | s2CellFile size:30
+        mBase64StrForPBByteArray =
+                "CioIDBomCh4wMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkSAlVTGAE=";
+        mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+        doReturn(mBytesProtoBuffer).when(
+                spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+        // mock UpdatedParser
+        SatelliteConfigParser spyValidEmptyParser =
+                spy(new SatelliteConfigParser(mBytesProtoBuffer));
+        doReturn(spyValidEmptyParser).when(spyTelephonyConfigUpdateInstallReceiver)
+                .getNewConfigParser(any(), any());
+
+        spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+        verify(spyCallbackHashMap, times(2)).keySet();
+        verify(spyTelephonyConfigUpdateInstallReceiver, times(1))
+                .copySourceFileToTargetFile(any(), any());
+        Mockito.clearInvocations(spyCallbackHashMap);
+        Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+        // Wrong plmn("1234") config data case
+        // mSupportedServicesPerCarrier:{1={"1234"=[1, 2, 3]}} |
+        // mSatelliteRegionCountryCodes:[US]
+        // | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+        mBase64StrForPBByteArray =
+                "CigIDBIQCAESDAoEMTIzNBABEAIQAxoSCgowMTIzNDU2Nzg5EgJVUxgB";
+        mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+        doReturn(mBytesProtoBuffer).when(
+                spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+        // mock UpdatedParser
+        spyInvalidParser =
+                spy(new SatelliteConfigParser(mBytesProtoBuffer));
+        doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+                .getNewConfigParser(any(), any());
+
+        spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+        verify(spyCallbackHashMap, times(0)).keySet();
+        verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+                .copySourceFileToTargetFile(any(), any());
+        Mockito.clearInvocations(spyCallbackHashMap);
+        Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+        // Wrong service("8") config data case
+        // mSupportedServicesPerCarrier:{1={12345=[6, "8"]}} |
+        // mSatelliteRegionCountryCodes:[US] |
+        // mIsSatelliteRegionAllowed:true | s2CellFile size:10
+        mBase64StrForPBByteArray =
+                "CicIDBIPCAESCwoFMTIzNDUQBhAIGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+        mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+        doReturn(mBytesProtoBuffer).when(
+                spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+        // mock UpdatedParser
+        spyInvalidParser =
+                spy(new SatelliteConfigParser(mBytesProtoBuffer));
+        doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+                .getNewConfigParser(any(), any());
+
+        spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+        verify(spyCallbackHashMap, times(0)).keySet();
+        verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+                .copySourceFileToTargetFile(any(), any());
+        Mockito.clearInvocations(spyCallbackHashMap);
+        Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
     }
 
 
@@ -133,7 +241,7 @@
                 spy(new TelephonyConfigUpdateInstallReceiver());
 
         doReturn(null).when(
-                spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
+                spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
 
         replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
                 null, spyTelephonyConfigUpdateInstallReceiver);
@@ -144,7 +252,7 @@
                 "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
         byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
         doReturn(mBytesProtoBuffer).when(
-                spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
+                spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
 
         replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
                 null, spyTelephonyConfigUpdateInstallReceiver);
@@ -172,4 +280,59 @@
         testReceiver.unregisterCallback(testCallback);
         assertEquals(0, testReceiver.getCallbackMap().size());
     }
+
+    @Test
+    public void testIsValidSatelliteCarrierConfigData() {
+        TelephonyConfigUpdateInstallReceiver spyTelephonyConfigUpdateInstallReceiver =
+                spy(new TelephonyConfigUpdateInstallReceiver());
+        SatelliteConfigParser mockParser = mock(SatelliteConfigParser.class);
+        SatelliteConfig mockConfig = mock(SatelliteConfig.class);
+        doReturn(new ArraySet<>()).when(mockConfig).getAllSatelliteCarrierIds();
+        doReturn(mockConfig).when(mockParser).getConfig();
+
+        assertTrue(spyTelephonyConfigUpdateInstallReceiver
+                .isValidSatelliteCarrierConfigData(mockParser));
+
+        doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+        Map<String, Set<Integer>> validPlmnsServices = new HashMap<>();
+        validPlmnsServices.put("123456", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+        validPlmnsServices.put("12345", Set.of(FIRST_SERVICE_TYPE, 4, LAST_SERVICE_TYPE));
+        doReturn(validPlmnsServices).when(mockConfig).getSupportedSatelliteServices(anyInt());
+        doReturn(mockConfig).when(mockParser).getConfig();
+
+        assertTrue(spyTelephonyConfigUpdateInstallReceiver
+                .isValidSatelliteCarrierConfigData(mockParser));
+
+        doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+        Map<String, Set<Integer>> invalidPlmnsServices1 = new HashMap<>();
+        invalidPlmnsServices1.put("123456", Set.of(FIRST_SERVICE_TYPE - 1, 3, LAST_SERVICE_TYPE));
+        doReturn(invalidPlmnsServices1).when(mockConfig).getSupportedSatelliteServices(anyInt());
+        doReturn(mockConfig).when(mockParser).getConfig();
+        assertFalse(spyTelephonyConfigUpdateInstallReceiver
+                .isValidSatelliteCarrierConfigData(mockParser));
+
+        doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+        Map<String, Set<Integer>> invalidPlmnsServices2 = new HashMap<>();
+        invalidPlmnsServices2.put("123456", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE + 1));
+        doReturn(invalidPlmnsServices2).when(mockConfig).getSupportedSatelliteServices(anyInt());
+        doReturn(mockConfig).when(mockParser).getConfig();
+        assertFalse(spyTelephonyConfigUpdateInstallReceiver
+                .isValidSatelliteCarrierConfigData(mockParser));
+
+        doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+        Map<String, Set<Integer>> invalidPlmnsServices3 = new HashMap<>();
+        invalidPlmnsServices3.put("1234", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+        doReturn(invalidPlmnsServices3).when(mockConfig).getSupportedSatelliteServices(anyInt());
+        doReturn(mockConfig).when(mockParser).getConfig();
+        assertFalse(spyTelephonyConfigUpdateInstallReceiver
+                .isValidSatelliteCarrierConfigData(mockParser));
+
+        doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+        Map<String, Set<Integer>> invalidPlmnsServices4 = new HashMap<>();
+        invalidPlmnsServices4.put("1234567", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+        doReturn(invalidPlmnsServices4).when(mockConfig).getSupportedSatelliteServices(anyInt());
+        doReturn(mockConfig).when(mockParser).getConfig();
+        assertFalse(spyTelephonyConfigUpdateInstallReceiver
+                .isValidSatelliteCarrierConfigData(mockParser));
+    }
 }