Merge tag 'android-security-10.0.0_r53' into int/10/fp2

Android security 10.0.0 release 53

* tag 'android-security-10.0.0_r53':

Change-Id: Ifcca0517e57b1c2250972c6e6d3eb5985775a390
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 35de8c1..b1163dd 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -26,15 +26,18 @@
         android:process="com.android.phone"
         android:persistent="true">
 
-        <receiver android:name="ONSAutoBoot">
+        <receiver android:name="ONSAutoBoot"
+            android:directBootAware="true">
             <intent-filter>
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
+                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
         <service android:name=".OpportunisticNetworkService"
                  android:enabled="true"
-                 android:exported="true"/>
+                 android:exported="true"
+                 android:directBootAware="true"
+                 android:singleUser="true" />
 
     </application>
 </manifest>
diff --git a/src/com/android/ons/ONSAutoBoot.java b/src/com/android/ons/ONSAutoBoot.java
index 7d8ef75..77c5c8f 100644
--- a/src/com/android/ons/ONSAutoBoot.java
+++ b/src/com/android/ons/ONSAutoBoot.java
@@ -27,7 +27,8 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+        Log.d(TAG, "Received " + intent.getAction());
+        if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
             ComponentName comp = new ComponentName(context.getPackageName(),
                     OpportunisticNetworkService.class.getName());
             ComponentName service = context.startService(new Intent().setComponent(comp));
diff --git a/src/com/android/ons/ONSProfileSelector.java b/src/com/android/ons/ONSProfileSelector.java
index 04fd3dd..83c4883 100644
--- a/src/com/android/ons/ONSProfileSelector.java
+++ b/src/com/android/ons/ONSProfileSelector.java
@@ -74,6 +74,9 @@
     /* message to indicate Subscription switch completion */
     private static final int MSG_SUB_SWITCH_COMPLETE = 3;
 
+    /* message to stop profile selection process */
+    private static final int MSG_STOP_PROFILE_SELECTION = 4;
+
     private boolean mIsEnabled = false;
 
     @VisibleForTesting
@@ -81,7 +84,8 @@
 
     @VisibleForTesting
     protected TelephonyManager mTelephonyManager;
-    private TelephonyManager mSubscriptionBoundTelephonyManager;
+    @VisibleForTesting
+    protected TelephonyManager mSubscriptionBoundTelephonyManager;
 
     @VisibleForTesting
     protected ONSNetworkScanCtlr mNetworkScanCtlr;
@@ -93,7 +97,8 @@
     private ONSProfileSelectionCallback mProfileSelectionCallback;
     private int mSequenceId;
     private int mSubId;
-    private int mCurrentDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    @VisibleForTesting
+    protected int mCurrentDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private ArrayList<AvailableNetworkInfo> mAvailableNetworkInfos;
     private IUpdateAvailableNetworksCallback mNetworkScanCallback;
 
@@ -116,7 +121,9 @@
                     if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                         sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
                                 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
-                        mNetworkScanCallback = null;
+                        synchronized (mLock) {
+                            mNetworkScanCallback = null;
+                        }
                         return;
                     }
 
@@ -128,14 +135,16 @@
                 @Override
                 public void onError(int error) {
                     log("Network scan failed with error " + error);
-                    if (mIsEnabled && mAvailableNetworkInfos != null
+                    synchronized (mLock) {
+                        if (mIsEnabled && mAvailableNetworkInfos != null
                             && mAvailableNetworkInfos.size() > 0) {
-                        handleNetworkScanResult(mAvailableNetworkInfos.get(0).getSubId());
-                    } else {
-                        if (mNetworkScanCallback != null) {
-                            sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
+                            handleNetworkScanResult(mAvailableNetworkInfos.get(0).getSubId());
+                        } else {
+                            if (mNetworkScanCallback != null) {
+                                sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
                                     TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
-                            mNetworkScanCallback = null;
+                                mNetworkScanCallback = null;
+                            }
                         }
                     }
                 }
@@ -151,7 +160,10 @@
                                 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
                         }
                         mProfileSelectionCallback.onProfileSelectionDone();
-                        mNetworkScanCallback = null;
+                        synchronized (mLock) {
+                            mNetworkScanCallback = null;
+                            mAvailableNetworkInfos = null;
+                        }
                     } else {
                         logDebug("switch to sub:" + subId);
                         switchToSubscription(subId);
@@ -165,6 +177,7 @@
             new SubscriptionManager.OnOpportunisticSubscriptionsChangedListener() {
                 @Override
                 public void onOpportunisticSubscriptionsChanged() {
+                    logDebug("onOpportunisticSubscriptionsChanged.");
                     mHandler.sendEmptyMessage(MSG_PROFILE_UPDATE);
                 }
             };
@@ -245,13 +258,17 @@
 
     private int getSubIdUsingAvailableNetworks(String mcc, String mnc, int priorityLevel) {
         String mccMnc = mcc + mnc;
-        for (AvailableNetworkInfo availableNetworkInfo : mAvailableNetworkInfos) {
-            if (availableNetworkInfo.getPriority() != priorityLevel) {
-                continue;
-            }
-            for (String availableMccMnc : availableNetworkInfo.getMccMncs()) {
-                if (TextUtils.equals(availableMccMnc, mccMnc)) {
-                    return availableNetworkInfo.getSubId();
+        synchronized (mLock) {
+            if (mAvailableNetworkInfos != null) {
+                for (AvailableNetworkInfo availableNetworkInfo : mAvailableNetworkInfos) {
+                    if (availableNetworkInfo.getPriority() != priorityLevel) {
+                        continue;
+                    }
+                    for (String availableMccMnc : availableNetworkInfo.getMccMncs()) {
+                        if (TextUtils.equals(availableMccMnc, mccMnc)) {
+                            return availableNetworkInfo.getSubId();
+                        }
+                    }
                 }
             }
         }
@@ -313,8 +330,7 @@
         callbackIntent.putExtra("subId", subId);
         mSubId = subId;
         PendingIntent replyIntent = PendingIntent.getService(mContext,
-                1, callbackIntent,
-                Intent.FILL_IN_ACTION);
+                1, callbackIntent, PendingIntent.FLAG_ONE_SHOT);
         mSubscriptionManager.switchToSubscription(subId, replyIntent);
     }
 
@@ -344,6 +360,8 @@
                 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
         }
         mProfileSelectionCallback.onProfileSelectionDone();
+        mNetworkScanCallback = null;
+        mAvailableNetworkInfos = null;
     }
 
     private void updateToken() {
@@ -451,6 +469,13 @@
         }
 
         if (isSame(availableNetworks, mAvailableNetworkInfos)) {
+            logDebug("received duplicate requests");
+            /* If we receive same request more than once, send abort response for earlier one
+               and send actual response for the latest callback.
+            */
+            sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
+                TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
+            mNetworkScanCallback = callbackStub;
             return;
         }
 
@@ -482,6 +507,7 @@
                             TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
                     }
                     mProfileSelectionCallback.onProfileSelectionDone();
+                    mAvailableNetworkInfos = null;
                 }
             } else {
                 mNetworkScanCallback = callbackStub;
@@ -586,27 +612,42 @@
     }
 
     private boolean enableModem(int subId, boolean enable) {
-        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+        if (!mSubscriptionManager.isActiveSubId(subId)) {
             return false;
         }
 
+        // If disabling modem for opportunistic sub, make sure to switch data back to default sub.
+        if (!enable) {
+            if (mSubscriptionManager.getPreferredDataSubscriptionId() == subId) {
+                selectProfileForData(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, null);
+            }
+        }
         int phoneId = SubscriptionManager.getPhoneId(subId);
+        /*  Todo: b/135067156
+         *  Reenable this code once 135067156 is fixed
         if (mSubscriptionBoundTelephonyManager.isModemEnabledForSlot(phoneId) == enable) {
             logDebug("modem is already enabled ");
             return true;
-        }
+        } */
 
         return mSubscriptionBoundTelephonyManager.enableModemForSlot(phoneId, enable);
     }
 
+    private void stopProfileSelectionProcess(IUpdateAvailableNetworksCallback callbackStub) {
+        stopProfileScanningPrecedure();
+        logDebug("stopProfileSelection");
+        disableOpportunisticModem(callbackStub);
+    }
+
     private void stopProfileScanningPrecedure() {
-        if (mNetworkScanCallback != null) {
-            sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
-                    TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
-            mNetworkScanCallback = null;
-        }
-        mNetworkScanCtlr.stopNetworkScan();
         synchronized (mLock) {
+            if (mNetworkScanCallback != null) {
+                sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
+                        TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
+                mNetworkScanCallback = null;
+            }
+            mNetworkScanCtlr.stopNetworkScan();
+
             mAvailableNetworkInfos = null;
             mIsEnabled = false;
         }
@@ -652,6 +693,10 @@
             IUpdateAvailableNetworksCallback callbackStub) {
         logDebug("startProfileSelection availableNetworks: " + availableNetworks);
         if (availableNetworks == null || availableNetworks.size() == 0) {
+            if (callbackStub != null) {
+                sendUpdateNetworksCallbackHelper(callbackStub,
+                        TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+            }
             return;
         }
         Object[] objects = new Object[]{availableNetworks, callbackStub};
@@ -693,7 +738,6 @@
                 return;
             }
             mCurrentDataSubId = subId;
-            sendSetOpptCallbackHelper(callbackStub, TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
         } else {
             log("Inactive sub passed for preferred data " + subId);
             sendSetOpptCallbackHelper(callbackStub,
@@ -709,9 +753,9 @@
      * stop profile selection procedure
      */
     public void stopProfileSelection(IUpdateAvailableNetworksCallback callbackStub) {
-        stopProfileScanningPrecedure();
         logDebug("stopProfileSelection");
-        disableOpportunisticModem(callbackStub);
+        Message message = Message.obtain(mHandler, MSG_STOP_PROFILE_SELECTION, callbackStub);
+        message.sendToTarget();
     }
 
     @VisibleForTesting
@@ -724,6 +768,24 @@
         }
     }
 
+    private void enableModemStackForNonOpportunisticSlots() {
+        int phoneCount = mTelephonyManager.getPhoneCount();
+        // Do nothing in single SIM mode.
+        if (phoneCount < 2) return;
+
+        for (int i = 0; i < phoneCount; i++) {
+            boolean hasActiveOpptProfile = false;
+            for (SubscriptionInfo info : mOppSubscriptionInfos) {
+                if (info.getSimSlotIndex() == i) {
+                    hasActiveOpptProfile = true;
+                }
+            }
+            // If the slot doesn't have active opportunistic profile anymore, it's back to
+            // DSDS use-case. Make sure the the modem stack is enabled.
+            if (!hasActiveOpptProfile) mTelephonyManager.enableModemForSlot(i, true);
+        }
+    }
+
     @VisibleForTesting
     protected void init(Context c, ONSProfileSelectionCallback profileSelectionCallback) {
         mContext = c;
@@ -748,6 +810,7 @@
                     case MSG_PROFILE_UPDATE:
                         synchronized (mLock) {
                             updateOpportunisticSubscriptions();
+                            enableModemStackForNonOpportunisticSlots();
                         }
                         break;
                     case MSG_START_PROFILE_SELECTION:
@@ -756,6 +819,12 @@
                             checkProfileUpdate((Object[]) msg.obj);
                         }
                         break;
+                    case MSG_STOP_PROFILE_SELECTION:
+                        logDebug("Msg received to stop profile selection");
+                        synchronized (mLock) {
+                            stopProfileSelectionProcess((IUpdateAvailableNetworksCallback) msg.obj);
+                        }
+                        break;
                     case MSG_SUB_SWITCH_COMPLETE:
                         logDebug("Msg received for sub switch");
                         synchronized (mLock) {
diff --git a/src/com/android/ons/OpportunisticNetworkService.java b/src/com/android/ons/OpportunisticNetworkService.java
index 91a17b2..e55b62c 100644
--- a/src/com/android/ons/OpportunisticNetworkService.java
+++ b/src/com/android/ons/OpportunisticNetworkService.java
@@ -52,15 +52,15 @@
  * Use the same to provide user opportunistic data in areas with corresponding networks
  */
 public class OpportunisticNetworkService extends Service {
-    private Context mContext;
+    @VisibleForTesting protected Context mContext;
     private TelephonyManager mTelephonyManager;
-    private SubscriptionManager mSubscriptionManager;
+    @VisibleForTesting protected SubscriptionManager mSubscriptionManager;
 
     private final Object mLock = new Object();
-    private boolean mIsEnabled;
+    @VisibleForTesting protected boolean mIsEnabled;
     private ONSProfileSelector mProfileSelector;
     private SharedPreferences mSharedPref;
-    private HashMap<String, ONSConfigInput> mONSConfigInputHashMap;
+    @VisibleForTesting protected HashMap<String, ONSConfigInput> mONSConfigInputHashMap;
 
     private static final String TAG = "ONS";
     private static final String PREF_NAME = TAG;
@@ -118,16 +118,22 @@
         return false;
     }
 
-    private void handleSimStateChange() {
+    @VisibleForTesting
+    protected void handleSimStateChange() {
         logDebug("SIM state changed");
-        ONSConfigInput onsConfigInput = mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME);
-        if (onsConfigInput == null) {
+        ONSConfigInput carrierAppConfigInput = mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME);
+        if (carrierAppConfigInput == null) {
             return;
         }
         List<SubscriptionInfo> subscriptionInfos =
             mSubscriptionManager.getActiveSubscriptionInfoList(false);
+        if (subscriptionInfos == null) {
+          return;
+        }
+
+        logDebug("handleSimStateChange: subscriptionInfos - " + subscriptionInfos);
         for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
-            if (subscriptionInfo.getSubscriptionId() == onsConfigInput.getPrimarySub()) {
+            if (subscriptionInfo.getSubscriptionId() == carrierAppConfigInput.getPrimarySub()) {
                 return;
             }
         }
@@ -142,9 +148,6 @@
                     mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME).getAvailableNetworkInfos(),
                     mONSConfigInputHashMap.get(
                             SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback());
-        } else {
-            mProfileSelector.stopProfileSelection(mONSConfigInputHashMap.get(
-                    SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback());
         }
     }
 
@@ -232,7 +235,15 @@
                     TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId,
                             "setPreferredDataSubscriptionId");
                 }
+            } else {
+                if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) != null) {
+                    sendSetOpptCallbackHelper(callbackStub,
+                        TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
+                    return;
+                }
             }
+
+
             final long identity = Binder.clearCallingIdentity();
             try {
                 mProfileSelector.selectProfileForData(subId, needValidation, callbackStub);
@@ -352,11 +363,13 @@
      * Start sub components if already enabled.
      * @param context context instance
      */
-    private void initialize(Context context) {
+    @VisibleForTesting
+    protected void initialize(Context context) {
         mContext = context;
         mTelephonyManager = TelephonyManager.from(mContext);
         mProfileSelector = new ONSProfileSelector(mContext, mProfileSelectionCallback);
-        mSharedPref = mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+        mSharedPref = mContext.createDeviceProtectedStorageContext().getSharedPreferences(
+                PREF_NAME, Context.MODE_PRIVATE);
         mSubscriptionManager = (SubscriptionManager) mContext.getSystemService(
                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         mONSConfigInputHashMap = new HashMap<String, ONSConfigInput>();
@@ -385,7 +398,9 @@
             }
 
             for (AvailableNetworkInfo availableNetworkInfo : availableNetworks) {
-                if (mSubscriptionManager.isActiveSubId(availableNetworkInfo.getSubId())) {
+                if (Binder.withCleanCallingIdentity(
+                            () -> mSubscriptionManager.isActiveSubId(
+                                    availableNetworkInfo.getSubId()))) {
                     TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
                         availableNetworkInfo.getSubId(), "updateAvailableNetworks");
                 } else {
@@ -403,14 +418,19 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworks, callbackStub);
-                onsConfigInput.setPrimarySub(
-                        mSubscriptionManager.getDefaultVoiceSubscriptionInfo().getSubscriptionId());
-                onsConfigInput.setPreferredDataSub(availableNetworks.get(0).getSubId());
-                mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, onsConfigInput);
+                SubscriptionInfo subscriptionInfo = mSubscriptionManager.getDefaultVoiceSubscriptionInfo();
+                if (subscriptionInfo != null) {
+                    onsConfigInput.setPrimarySub(subscriptionInfo.getSubscriptionId());
+                    onsConfigInput.setPreferredDataSub(availableNetworks.get(0).getSubId());
+                    mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, onsConfigInput);
+                }
 
                 if (mIsEnabled) {
                     /*  if carrier is reporting availability, then it takes higher priority. */
                     mProfileSelector.startProfileSelection(availableNetworks, callbackStub);
+                } else {
+                    sendUpdateNetworksCallbackHelper(callbackStub,
+                            TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -452,6 +472,15 @@
         }
     }
 
+    private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) {
+        if (callback == null) return;
+        try {
+            callback.onComplete(result);
+        } catch (RemoteException exception) {
+            log("RemoteException " + exception);
+        }
+    }
+
     private void handleSystemAppAvailableNetworks(
             ArrayList<AvailableNetworkInfo> availableNetworks,
             IUpdateAvailableNetworksCallback callbackStub) {
@@ -469,8 +498,13 @@
                         new ONSConfigInput(availableNetworks, callbackStub));
 
                 /* reporting availability. proceed if carrier app has not requested any */
-                if (mIsEnabled && mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) == null) {
-                    mProfileSelector.startProfileSelection(availableNetworks, callbackStub);
+                if (mIsEnabled) {
+                    if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) == null) {
+                        mProfileSelector.startProfileSelection(availableNetworks, callbackStub);
+                    }
+                } else {
+                    sendUpdateNetworksCallbackHelper(callbackStub,
+                            TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED);
                 }
             } else {
                 if (!mIsEnabled) {
diff --git a/tests/src/com/android/ons/ONSProfileSelectorTest.java b/tests/src/com/android/ons/ONSProfileSelectorTest.java
index 0046783..253971f 100644
--- a/tests/src/com/android/ons/ONSProfileSelectorTest.java
+++ b/tests/src/com/android/ons/ONSProfileSelectorTest.java
@@ -42,6 +42,7 @@
 import java.util.List;
 
 public class ONSProfileSelectorTest extends ONSBaseTest {
+
     private MyONSProfileSelector mONSProfileSelector;
     private boolean testFailed;
     private boolean mCallbackInvoked;
@@ -49,24 +50,27 @@
     private int mResult;
     @Mock
     ONSNetworkScanCtlr mONSNetworkScanCtlr;
+    @Mock
+    TelephonyManager mSubscriptionBoundTelephonyManager;
     private Looper mLooper;
     private static final String TAG = "ONSProfileSelectorTest";
 
     MyONSProfileSelector.ONSProfileSelectionCallback mONSProfileSelectionCallback =
-            new MyONSProfileSelector.ONSProfileSelectionCallback() {
-        public void onProfileSelectionDone() {
-            mCallbackInvoked = true;
-            setReady(true);
-        }
-    };
+        new MyONSProfileSelector.ONSProfileSelectionCallback() {
+            public void onProfileSelectionDone() {
+                mCallbackInvoked = true;
+                setReady(true);
+            }
+        };
 
     public class MyONSProfileSelector extends ONSProfileSelector {
+
         public SubscriptionManager.OnOpportunisticSubscriptionsChangedListener mProfileChngLstnrCpy;
         public BroadcastReceiver mProfileSelectorBroadcastReceiverCpy;
         public ONSNetworkScanCtlr.NetworkAvailableCallBack mNetworkAvailableCallBackCpy;
 
         public MyONSProfileSelector(Context c,
-                MyONSProfileSelector.ONSProfileSelectionCallback aNSProfileSelectionCallback) {
+            MyONSProfileSelector.ONSProfileSelectionCallback aNSProfileSelectionCallback) {
             super(c, aNSProfileSelectionCallback);
         }
 
@@ -78,10 +82,20 @@
             updateOpportunisticSubscriptions();
         }
 
+        public int getCurrentPreferredData() {
+            return mCurrentDataSubId;
+        }
+
+        public void setCurrentPreferredData(int subId) {
+            mCurrentDataSubId = subId;
+        }
+
         protected void init(Context c,
-                MyONSProfileSelector.ONSProfileSelectionCallback aNSProfileSelectionCallback) {
+            MyONSProfileSelector.ONSProfileSelectionCallback aNSProfileSelectionCallback) {
             super.init(c, aNSProfileSelectionCallback);
             this.mSubscriptionManager = ONSProfileSelectorTest.this.mSubscriptionManager;
+            this.mSubscriptionBoundTelephonyManager =
+                ONSProfileSelectorTest.this.mSubscriptionBoundTelephonyManager;
             mProfileChngLstnrCpy = mProfileChangeListener;
             mProfileSelectorBroadcastReceiverCpy = null;
             mNetworkAvailableCallBackCpy = mNetworkAvailableCallBack;
@@ -112,11 +126,11 @@
         CellIdentityLte cellIdentityLte = new CellIdentityLte(310, 210, 1, 1, 1);
         CellInfoLte cellInfoLte = new CellInfoLte();
         cellInfoLte.setCellIdentity(cellIdentityLte);
-        results2.add((CellInfo)cellInfoLte);
+        results2.add((CellInfo) cellInfoLte);
         ArrayList<String> mccMncs = new ArrayList<>();
         mccMncs.add("310210");
         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
-                new ArrayList<Integer>());
+            new ArrayList<Integer>());
         ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
         availableNetworkInfos.add(availableNetworkInfo);
 
@@ -137,9 +151,9 @@
                 Looper.prepare();
                 doReturn(true).when(mONSNetworkScanCtlr).startFastNetworkScan(anyObject());
                 doReturn(new ArrayList<>()).when(mSubscriptionManager)
-                        .getOpportunisticSubscriptions();
+                    .getOpportunisticSubscriptions();
                 mONSProfileSelector = new MyONSProfileSelector(mContext,
-                        mONSProfileSelectionCallback);
+                    mONSProfileSelectionCallback);
                 mONSProfileSelector.updateOppSubs();
                 mONSProfileSelector.startProfileSelection(availableNetworkInfos, mCallback);
                 mLooper = Looper.myLooper();
@@ -164,20 +178,20 @@
     public void testStartProfileSelectionSuccess() {
         List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
         SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
-                "123", 1, null, "310", "210", "", false, null, "1");
+            "123", 1, null, "310", "210", "", false, null, "1");
         SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
-                "123", 1, null, "310", "211", "", false, null, "1");
+            "123", 1, null, "310", "211", "", false, null, "1");
         subscriptionInfoList.add(subscriptionInfo);
 
         List<CellInfo> results2 = new ArrayList<CellInfo>();
         CellIdentityLte cellIdentityLte = new CellIdentityLte(310, 210, 1, 1, 1);
         CellInfoLte cellInfoLte = new CellInfoLte();
         cellInfoLte.setCellIdentity(cellIdentityLte);
-        results2.add((CellInfo)cellInfoLte);
+        results2.add((CellInfo) cellInfoLte);
         ArrayList<String> mccMncs = new ArrayList<>();
         mccMncs.add("310210");
         AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
-                new ArrayList<Integer>());
+            new ArrayList<Integer>());
         ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
         availableNetworkInfos.add(availableNetworkInfo);
 
@@ -194,14 +208,17 @@
             @Override
             public void run() {
                 Looper.prepare();
-                doReturn(subscriptionInfoList).when(mSubscriptionManager).getOpportunisticSubscriptions();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                    .getOpportunisticSubscriptions();
                 doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
+                doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
+                    anyInt(), anyBoolean());
                 mONSProfileSelector = new MyONSProfileSelector(mContext,
-                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
-                    public void onProfileSelectionDone() {
-                        setReady(true);
-                    }
-                });
+                    new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                        public void onProfileSelectionDone() {
+                            setReady(true);
+                        }
+                    });
                 mONSProfileSelector.updateOppSubs();
                 mONSProfileSelector.startProfileSelection(availableNetworkInfos, mCallback);
                 mLooper = Looper.myLooper();
@@ -259,7 +276,8 @@
             @Override
             public void run() {
                 Looper.prepare();
-                doReturn(opportunisticSubscriptionInfoList).when(mSubscriptionManager).getOpportunisticSubscriptions();
+                doReturn(opportunisticSubscriptionInfoList).when(mSubscriptionManager)
+                    .getOpportunisticSubscriptions();
                 doReturn(false).when(mSubscriptionManager).isActiveSubId(anyInt());
                 doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
                     .getActiveSubscriptionInfoList(anyBoolean());
@@ -310,9 +328,10 @@
             public void run() {
                 Looper.prepare();
                 mONSProfileSelector = new MyONSProfileSelector(mContext,
-                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
-                            public void onProfileSelectionDone() {}
-                        });
+                    new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                        public void onProfileSelectionDone() {
+                        }
+                    });
                 mLooper = Looper.myLooper();
                 setReady(true);
                 Looper.loop();
@@ -331,7 +350,7 @@
     public void testselectProfileForDataWithInActiveSub() {
         List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
         SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
-                "123", 1, null, "310", "210", "", false, null, "1");
+            "123", 1, null, "310", "210", "", false, null, "1");
         subscriptionInfoList.add(subscriptionInfo);
         mReady = false;
         doReturn(new ArrayList<>()).when(mSubscriptionManager).getOpportunisticSubscriptions();
@@ -340,9 +359,10 @@
             public void run() {
                 Looper.prepare();
                 mONSProfileSelector = new MyONSProfileSelector(mContext,
-                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
-                            public void onProfileSelectionDone() {}
-                        });
+                    new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                        public void onProfileSelectionDone() {
+                        }
+                    });
                 mLooper = Looper.myLooper();
                 setReady(true);
                 Looper.loop();
@@ -360,20 +380,21 @@
     public void testselectProfileForDataWithInvalidSubId() {
         List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
         SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
-                "123", 1, null, "310", "210", "", false, null, "1");
+            "123", 1, null, "310", "210", "", false, null, "1");
         subscriptionInfoList.add(subscriptionInfo);
         mReady = false;
         doReturn(subscriptionInfoList).when(mSubscriptionManager).getOpportunisticSubscriptions();
         doNothing().when(mSubscriptionManager).setPreferredDataSubscriptionId(
-                anyInt(), anyBoolean(), any(), any());
+            anyInt(), anyBoolean(), any(), any());
         new Thread(new Runnable() {
             @Override
             public void run() {
                 Looper.prepare();
                 mONSProfileSelector = new MyONSProfileSelector(mContext,
-                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
-                            public void onProfileSelectionDone() {}
-                        });
+                    new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                        public void onProfileSelectionDone() {
+                        }
+                    });
                 mLooper = Looper.myLooper();
                 setReady(true);
                 Looper.loop();
@@ -386,30 +407,31 @@
         // Testing selectProfileForData with INVALID_SUBSCRIPTION_ID and the function should
         // return true.
         mONSProfileSelector.selectProfileForData(
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID, false, null);
+            SubscriptionManager.INVALID_SUBSCRIPTION_ID, false, null);
     }
 
     @Test
     public void testselectProfileForDataWithValidSub() {
         List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
         SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
-                "123", 1, null, "310", "210", "", false, null, "1");
+            "123", 1, null, "310", "210", "", false, null, "1");
         subscriptionInfoList.add(subscriptionInfo);
         mReady = false;
         doReturn(subscriptionInfoList).when(mSubscriptionManager)
-                .getActiveSubscriptionInfoList();
+            .getActiveSubscriptionInfoList();
         doNothing().when(mSubscriptionManager).setPreferredDataSubscriptionId(
-                anyInt(), anyBoolean(), any(), any());
+            anyInt(), anyBoolean(), any(), any());
         new Thread(new Runnable() {
             @Override
             public void run() {
                 Looper.prepare();
                 doReturn(subscriptionInfoList).when(mSubscriptionManager)
-                        .getOpportunisticSubscriptions();
+                    .getOpportunisticSubscriptions();
                 mONSProfileSelector = new MyONSProfileSelector(mContext,
-                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
-                            public void onProfileSelectionDone() {}
-                        });
+                    new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                        public void onProfileSelectionDone() {
+                        }
+                    });
                 mONSProfileSelector.updateOppSubs();
                 mLooper = Looper.myLooper();
                 setReady(true);
@@ -424,4 +446,206 @@
         // return true.
         mONSProfileSelector.selectProfileForData(5, false, null);
     }
+
+    @Test
+    public void testStartProfileSelectionSuccessWithSameArgumentsAgain() {
+        List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
+        SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+            "123", 1, null, "310", "210", "", false, null, "1");
+        SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+            "123", 1, null, "310", "211", "", false, null, "1");
+        subscriptionInfoList.add(subscriptionInfo);
+
+        List<CellInfo> results2 = new ArrayList<CellInfo>();
+        CellIdentityLte cellIdentityLte = new CellIdentityLte(310, 210, 1, 1, 1);
+        CellInfoLte cellInfoLte = new CellInfoLte();
+        cellInfoLte.setCellIdentity(cellIdentityLte);
+        results2.add((CellInfo) cellInfoLte);
+        ArrayList<String> mccMncs = new ArrayList<>();
+        mccMncs.add("310210");
+        AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
+            new ArrayList<Integer>());
+        ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
+        availableNetworkInfos.add(availableNetworkInfo);
+
+        IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+            }
+        };
+
+        mResult = -1;
+        mReady = false;
+        mONSProfileSelector = new MyONSProfileSelector(mContext,
+            new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                public void onProfileSelectionDone() {
+                    setReady(true);
+                }
+            });
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                    .getOpportunisticSubscriptions();
+                doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
+                doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
+                    anyInt(), anyBoolean());
+
+                mONSProfileSelector.updateOppSubs();
+                mONSProfileSelector.startProfileSelection(availableNetworkInfos, mCallback);
+                mLooper = Looper.myLooper();
+                setReady(true);
+                Looper.loop();
+            }
+        }).start();
+
+        // Wait till initialization is complete.
+        waitUntilReady();
+        mReady = false;
+        mDataSubId = -1;
+
+        // Testing startProfileSelection with oppotunistic sub.
+        // On success onProfileSelectionDone must get invoked.
+        assertFalse(mReady);
+        waitForMs(500);
+        mONSProfileSelector.mNetworkAvailableCallBackCpy.onNetworkAvailability(results2);
+        Intent callbackIntent = new Intent(MyONSProfileSelector.ACTION_SUB_SWITCH);
+        callbackIntent.putExtra("sequenceId", 1);
+        callbackIntent.putExtra("subId", 5);
+        waitUntilReady();
+        assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS, mResult);
+        assertTrue(mReady);
+
+        mResult = -1;
+        mReady = false;
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                    .getOpportunisticSubscriptions();
+                doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
+                doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
+                    anyInt(), anyBoolean());
+                mONSProfileSelector.updateOppSubs();
+                mONSProfileSelector.startProfileSelection(availableNetworkInfos, mCallback);
+                mLooper = Looper.myLooper();
+                setReady(true);
+                Looper.loop();
+            }
+        }).start();
+
+        // Wait till initialization is complete.
+        waitUntilReady();
+        mReady = false;
+        mDataSubId = -1;
+
+        // Testing startProfileSelection with oppotunistic sub.
+        // On success onProfileSelectionDone must get invoked.
+        assertFalse(mReady);
+        waitForMs(500);
+        mONSProfileSelector.mNetworkAvailableCallBackCpy.onNetworkAvailability(results2);
+        waitUntilReady();
+        assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS, mResult);
+        assertTrue(mReady);
+    }
+
+    @Test
+    public void testStopProfileSelectionWithPreferredDataOnSame() {
+        List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
+        SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+                "123", 1, null, "310", "210", "", true, null, "1", true, null, 0, 0);
+        subscriptionInfoList.add(subscriptionInfo);
+
+        IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+            }
+        };
+
+        mResult = -1;
+        mReady = false;
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                        .getOpportunisticSubscriptions();
+                doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
+                doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
+                        anyInt(), anyBoolean());
+                doReturn(5).when(mSubscriptionManager).getPreferredDataSubscriptionId();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                        .getActiveSubscriptionInfoList(anyBoolean());
+
+                mONSProfileSelector = new MyONSProfileSelector(mContext,
+                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                            public void onProfileSelectionDone() {
+                                setReady(true);
+                            }
+                        });
+                mONSProfileSelector.updateOppSubs();
+                mONSProfileSelector.setCurrentPreferredData(5);
+                mONSProfileSelector.stopProfileSelection(null);
+                mLooper = Looper.myLooper();
+                setReady(true);
+                Looper.loop();
+            }
+        }).start();
+        waitUntilReady();
+        waitForMs(500);
+        assertEquals(mONSProfileSelector.getCurrentPreferredData(), SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+    }
+
+    @Test
+    public void testStopProfileSelectionWithPreferredDataOnDifferent() {
+        List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
+        SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+                "123", 1, null, "310", "210", "", true, null, "1", true, null, 0, 0);
+        subscriptionInfoList.add(subscriptionInfo);
+
+        IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+            }
+        };
+
+        mResult = -1;
+        mReady = false;
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                        .getOpportunisticSubscriptions();
+                doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
+                doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
+                        anyInt(), anyBoolean());
+                doReturn(4).when(mSubscriptionManager).getPreferredDataSubscriptionId();
+                doReturn(subscriptionInfoList).when(mSubscriptionManager)
+                        .getActiveSubscriptionInfoList(anyBoolean());
+
+                mONSProfileSelector = new MyONSProfileSelector(mContext,
+                        new MyONSProfileSelector.ONSProfileSelectionCallback() {
+                            public void onProfileSelectionDone() {
+                                setReady(true);
+                            }
+                        });
+                mONSProfileSelector.updateOppSubs();
+                mONSProfileSelector.setCurrentPreferredData(5);
+                mONSProfileSelector.stopProfileSelection(null);
+                mLooper = Looper.myLooper();
+                setReady(true);
+                Looper.loop();
+            }
+        }).start();
+        waitUntilReady();
+        waitForMs(500);
+        assertEquals(mONSProfileSelector.getCurrentPreferredData(), 5);
+    }
+
 }
diff --git a/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java b/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java
index 2a76668..ae28862 100644
--- a/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java
+++ b/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java
@@ -1,4 +1,4 @@
-/*
+  /*
  * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,10 +15,18 @@
  */
 package com.android.ons;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import android.content.Intent;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.AvailableNetworkInfo;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
@@ -26,36 +34,69 @@
 import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import static org.mockito.Mockito.any;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 
-import androidx.test.InstrumentationRegistry;
-import androidx.test.rule.ServiceTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
 @RunWith(AndroidJUnit4.class)
 public class OpportunisticNetworkServiceTest extends ONSBaseTest {
-    private String TAG = "ONSTest";
+    private static final String TAG = "ONSTest";
     private String pkgForDebug;
     private int mResult;
     private IOns iOpportunisticNetworkService;
+    private Looper mLooper;
+    private OpportunisticNetworkService mOpportunisticNetworkService;
+    private static final String CARRIER_APP_CONFIG_NAME = "carrierApp";
+    private static final String SYSTEM_APP_CONFIG_NAME = "systemApp";
 
-    @Rule
-    public final ServiceTestRule mServiceRule = new ServiceTestRule();
+    @Mock
+    private HashMap<String, ONSConfigInput> mockONSConfigInputHashMap;
 
     @Before
     public void setUp() throws Exception {
         super.setUp("ONSTest");
         pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
-        Intent serviceIntent =
-                new Intent(InstrumentationRegistry.getTargetContext(),
-                        OpportunisticNetworkService.class);
-        mServiceRule.startService(serviceIntent);
+        Intent intent = new Intent(mContext, OpportunisticNetworkService.class);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                mOpportunisticNetworkService = new OpportunisticNetworkService();
+                mContext.startService(intent);
+                mOpportunisticNetworkService.initialize(mContext);
+                mOpportunisticNetworkService.mContext = mContext;
+                mOpportunisticNetworkService.mSubscriptionManager = mSubscriptionManager;
+                mLooper = Looper.myLooper();
+                Looper.loop();
+            }
+        }).start();
         iOpportunisticNetworkService = getIOns();
+        for (int i = 0; i < 5; i++) {
+            if (iOpportunisticNetworkService == null) {
+                waitForMs(500);
+                iOpportunisticNetworkService = getIOns();
+            } else {
+                break;
+            }
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mOpportunisticNetworkService.onDestroy();
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper.getThread().join();
+        }
     }
 
     @Test
@@ -71,6 +112,95 @@
     }
 
     @Test
+    public void testHandleSimStateChange() {
+        mResult = -1;
+        ArrayList<String> mccMncs = new ArrayList<>();
+        mccMncs.add("310210");
+        AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
+                new ArrayList<Integer>());
+        ArrayList<AvailableNetworkInfo> availableNetworkInfos =
+                new ArrayList<AvailableNetworkInfo>();
+        availableNetworkInfos.add(availableNetworkInfo);
+        IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+                Log.d(TAG, "result: " + result);
+            }
+        };
+        ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback);
+        onsConfigInput.setPrimarySub(1);
+        onsConfigInput.setPreferredDataSub(availableNetworkInfos.get(0).getSubId());
+        ArrayList<SubscriptionInfo> subscriptionInfos = new ArrayList<SubscriptionInfo>();
+
+        // Case 1: There is no Carrier app using ONS.
+        doReturn(null).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
+        mOpportunisticNetworkService.mIsEnabled = true;
+        mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
+        mOpportunisticNetworkService.handleSimStateChange();
+        waitForMs(500);
+        verify(mockONSConfigInputHashMap, never()).get(SYSTEM_APP_CONFIG_NAME);
+
+        // Case 2: There is a Carrier app using ONS and no System app input.
+        doReturn(subscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList(false);
+        doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
+        doReturn(null).when(mockONSConfigInputHashMap).get(SYSTEM_APP_CONFIG_NAME);
+        mOpportunisticNetworkService.mIsEnabled = true;
+        mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
+        mOpportunisticNetworkService.handleSimStateChange();
+        waitForMs(50);
+        verify(mockONSConfigInputHashMap,times(1)).get(SYSTEM_APP_CONFIG_NAME);
+    }
+
+    @Test
+    public void testSystemPreferredDataWhileCarrierAppIsActive() {
+        mResult = -1;
+        ArrayList<String> mccMncs = new ArrayList<>();
+        mccMncs.add("310210");
+        AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(1, 1, mccMncs,
+            new ArrayList<Integer>());
+        ArrayList<AvailableNetworkInfo> availableNetworkInfos =
+            new ArrayList<AvailableNetworkInfo>();
+        availableNetworkInfos.add(availableNetworkInfo);
+        IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                mResult = result;
+                Log.d(TAG, "result: " + result);
+            }
+        };
+        ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworkInfos, mCallback);
+        onsConfigInput.setPrimarySub(1);
+        onsConfigInput.setPreferredDataSub(availableNetworkInfos.get(0).getSubId());
+        ArrayList<SubscriptionInfo> subscriptionInfos = new ArrayList<SubscriptionInfo>();
+
+        doReturn(subscriptionInfos).when(mSubscriptionManager).getActiveSubscriptionInfoList(false);
+        doReturn(onsConfigInput).when(mockONSConfigInputHashMap).get(CARRIER_APP_CONFIG_NAME);
+        mOpportunisticNetworkService.mIsEnabled = true;
+        mOpportunisticNetworkService.mONSConfigInputHashMap = mockONSConfigInputHashMap;
+
+        mResult = -1;
+        ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
+            @Override
+            public void onComplete(int result) {
+                Log.d(TAG, "callbackStub, mResult end:" + result);
+                mResult = result;
+            }
+        };
+
+        try {
+            IOns onsBinder = (IOns)mOpportunisticNetworkService.onBind(null);
+            onsBinder.setPreferredDataSubscriptionId(
+                    SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false, callbackStub,
+                    pkgForDebug);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "RemoteException", ex);
+        }
+        waitForMs(50);
+        assertEquals(TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED, mResult);
+    }
+
+    @Test
     public void testSetPreferredDataSubscriptionId() {
         mResult = -1;
         ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@@ -154,4 +284,12 @@
     private IOns getIOns() {
         return IOns.Stub.asInterface(ServiceManager.getService("ions"));
     }
+
+    public static void waitForMs(long ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+            Log.d(TAG, "InterruptedException while waiting: " + e);
+        }
+    }
 }