Merge "[DO NOT MERGE] Skip SystemUpdatePolicy Tests"
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 4d46518..166eb89 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -54,6 +54,7 @@
     <uses-feature android:name="android.hardware.vr.high_performance" android:required="false"/>
     <uses-feature android:name="android.software.companion_device_setup" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
index 636dc2b..24e273c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.audio;
 
+import android.content.Context;
 import android.media.*;
 import android.media.audiofx.AcousticEchoCanceler;
 import android.os.Bundle;
@@ -61,8 +62,10 @@
     private final int CORRELATION_DURATION_MS = TEST_DURATION_MS - 3000;
     private final int SHOT_COUNT_CORRELATION = CORRELATION_DURATION_MS/SHOT_FREQUENCY_MS;
     private final int SHOT_COUNT = TEST_DURATION_MS/SHOT_FREQUENCY_MS;
+    private final float MIN_RMS_DB = -60.0f; //dB
+    private final float MIN_RMS_VAL = (float)Math.pow(10,(MIN_RMS_DB/20));
 
-    private final double TEST_THRESHOLD_AEC_ON = 0.4; //From SoloTester
+    private final double TEST_THRESHOLD_AEC_ON = 0.5;
     private final double TEST_THRESHOLD_AEC_OFF = 0.6;
     private RmsHelper mRMSRecorder1 = new RmsHelper(mBlockSizeSamples, SHOT_COUNT);
     private RmsHelper mRMSRecorder2 = new RmsHelper(mBlockSizeSamples, SHOT_COUNT);
@@ -131,6 +134,9 @@
                         count++;
                     }
                     float rms = count > 0 ? (float)Math.sqrt(rmsTempSum / count) : 0f;
+                    if (rms < MIN_RMS_VAL) {
+                        rms = MIN_RMS_VAL;
+                    }
 
                     double alpha = 0.9;
                     double total_rms = rms * alpha + mRmsCurrent * (1.0f - alpha);
@@ -162,9 +168,10 @@
             DspBufferDouble crossCorr = new DspBufferDouble(actualLen);
 
             for (int i = firstShot, index = 0; i <= lastShot; ++i, ++index) {
-                double valPlayerdB = Math.max(20 * Math.log10(buffRmsPlayer.mData[i]), -120);
+                double valPlayerdB = Math.max(20 * Math.log10(buffRmsPlayer.mData[i]), MIN_RMS_DB);
                 rmsPlayerdB.setValue(index, valPlayerdB);
-                double valRecorderdB = Math.max(20 * Math.log10(buffRmsRecorder.mData[i]), -120);
+                double valRecorderdB = Math.max(20 * Math.log10(buffRmsRecorder.mData[i]),
+                        MIN_RMS_DB);
                 rmsRecorderdB.setValue(index, valRecorderdB);
             }
 
@@ -288,20 +295,37 @@
                     return;
                 }
 
-                int playbackStreamType = AudioManager.STREAM_MUSIC;
+                 //Step 0. Prepare system
+                AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+                int targetMode = AudioManager.MODE_IN_COMMUNICATION;
+                int originalMode = am.getMode();
+                am.setMode(targetMode);
+
+                if (am.getMode() != targetMode) {
+                    sendMessage(AudioTestRunner.TEST_ENDED_ERROR,
+                            "Couldn't set mode to MODE_IN_COMMUNICATION.");
+                    return;
+                }
+
+                int playbackStreamType = AudioManager.STREAM_VOICE_CALL;
                 int maxLevel = getMaxLevelForStream(playbackStreamType);
                 int desiredLevel = maxLevel - 1;
                 setLevelForStream(playbackStreamType, desiredLevel);
 
                 int currentLevel = getLevelForStream(playbackStreamType);
                 if (currentLevel != desiredLevel) {
+                    am.setMode(originalMode);
                     sendMessage(AudioTestRunner.TEST_ENDED_ERROR,
-                            "Couldn't set level for STREAM_MUSIC. Expected " +
+                            "Couldn't set level for STREAM_VOICE_CALL. Expected " +
                                     desiredLevel +" got: " + currentLevel);
                     return;
                 }
 
+                boolean originalSpeakerPhone = am.isSpeakerphoneOn();
+                am.setSpeakerphoneOn(true);
+
                 //Step 1. With AEC (on by Default when using VOICE_COMMUNICATION audio source).
+                mSPlayer.setStreamType(playbackStreamType);
                 mSPlayer.setSoundWithResId(getApplicationContext(), R.raw.speech);
                 mSRecorder.startRecording();
 
@@ -316,16 +340,20 @@
                 } catch (Exception e) {
                     mSRecorder.stopRecording();
                     String msg = "Could not create AEC Effect. " + e.toString();
-                    sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
                     recordTestResults(mMandatory, 0, 0, msg);
+                    am.setSpeakerphoneOn(originalSpeakerPhone);
+                    am.setMode(originalMode);
+                    sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
                     return;
                 }
 
                 if (mAec == null) {
                     mSRecorder.stopRecording();
                     String msg = "Could not create AEC Effect (AEC Null)";
-                    sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
                     recordTestResults(mMandatory,0, 0, msg);
+                    am.setSpeakerphoneOn(originalSpeakerPhone);
+                    am.setMode(originalMode);
+                    sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
                     return;
                 }
 
@@ -333,8 +361,10 @@
                     String msg = "AEC is not enabled by default.";
                     if (mMandatory) {
                         mSRecorder.stopRecording();
-                        sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
                         recordTestResults(mMandatory,0, 0, msg);
+                        am.setSpeakerphoneOn(originalSpeakerPhone);
+                        am.setMode(originalMode);
+                        sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
                         return;
                     } else {
                         sb.append("Warning. " + msg + "\n");
@@ -358,9 +388,9 @@
                                     20 * Math.log10(mRMSPlayer1.getRmsCurrent())));
                 }
 
-                mSPlayer.play(false);
                 mRMSPlayer1.setRunning(false);
                 mRMSRecorder1.setRunning(false);
+                mSPlayer.play(false);
 
                 int lastShot = SHOT_COUNT - 1;
                 int firstShot = SHOT_COUNT - SHOT_COUNT_CORRELATION;
@@ -397,10 +427,13 @@
                                     20 * Math.log10(mRMSPlayer2.getRmsCurrent())));
                 }
 
-                mSRecorder.stopRecording();
-                mSPlayer.play(false);
                 mRMSPlayer2.setRunning(false);
                 mRMSRecorder2.setRunning(false);
+                mSRecorder.stopRecording();
+                mSPlayer.play(false);
+
+                am.setSpeakerphoneOn(originalSpeakerPhone);
+                am.setMode(originalMode);
 
                 double maxNoAEC = computeAcousticCouplingFactor(mRMSPlayer2.getRmsSnapshots(),
                         mRMSRecorder2.getRmsSnapshots(), firstShot, lastShot);
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java b/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
index 2d09a0d..6369470 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
@@ -53,6 +53,7 @@
         plugInUsb();
     }
 
+    /*
     public void testConnectivityStateChange() throws Exception {
         if (!hasFeature(FEATURE_WIFI, true)) return;
         if (!hasFeature(FEATURE_WATCH, false)) return;
@@ -77,6 +78,7 @@
         assertEquals(batterystatsProto.getSystem().getMisc().getNumConnectivityChanges(),
                 countMetricData.get(0).getBucketInfo(0).getCount());
     }
+    */
 
     public void testPowerUse() throws Exception {
         if (statsdDisabled()) {
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index dafaed6..6b10df9 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -17,6 +17,7 @@
 package android.content.cts;
 
 import android.app.AppOpsManager;
+import android.app.WallpaperManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -778,6 +779,8 @@
     }
 
     public void testAccessWallpaper() throws IOException, InterruptedException {
+        if (!isWallpaperSupported()) return;
+
         // set Wallpaper by context#setWallpaper(Bitmap)
         Bitmap bitmap = Bitmap.createBitmap(20, 30, Bitmap.Config.RGB_565);
         // Test getWallpaper
@@ -1004,6 +1007,8 @@
     }
 
     public void testGetWallpaperDesiredMinimumHeightAndWidth() {
+        if (!isWallpaperSupported()) return;
+
         int height = mContext.getWallpaperDesiredMinimumHeight();
         int width = mContext.getWallpaperDesiredMinimumWidth();
 
@@ -1524,4 +1529,7 @@
         }
     }
 
+    private boolean isWallpaperSupported() {
+        return WallpaperManager.getInstance(mContext).isWallpaperSupported();
+    }
 }
diff --git a/tests/tests/net/src/android/net/cts/MacAddressTest.java b/tests/tests/net/src/android/net/cts/MacAddressTest.java
index af1e760..4d25e62 100644
--- a/tests/tests/net/src/android/net/cts/MacAddressTest.java
+++ b/tests/tests/net/src/android/net/cts/MacAddressTest.java
@@ -20,6 +20,11 @@
 import static android.net.MacAddress.TYPE_MULTICAST;
 import static android.net.MacAddress.TYPE_UNICAST;
 
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.net.MacAddress;
@@ -30,6 +35,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.Inet6Address;
 import java.util.Arrays;
 
 @SmallTest
@@ -161,4 +167,57 @@
         } catch (NullPointerException excepted) {
         }
     }
+
+    @Test
+    public void testMatches() {
+        // match 4 bytes prefix
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:00:00"),
+                MacAddress.fromString("ff:ff:ff:ff:00:00")));
+
+        // match bytes 0,1,2 and 5
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:00:00:11"),
+                MacAddress.fromString("ff:ff:ff:00:00:ff")));
+
+        // match 34 bit prefix
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:c0:00"),
+                MacAddress.fromString("ff:ff:ff:ff:c0:00")));
+
+        // fail to match 36 bit prefix
+        assertFalse(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:40:00"),
+                MacAddress.fromString("ff:ff:ff:ff:f0:00")));
+
+        // match all 6 bytes
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:ee:11"),
+                MacAddress.fromString("ff:ff:ff:ff:ff:ff")));
+
+        // match none of 6 bytes
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("00:00:00:00:00:00"),
+                MacAddress.fromString("00:00:00:00:00:00")));
+    }
+
+    /**
+     * Tests that link-local address generation from MAC is valid.
+     */
+    @Test
+    public void testLinkLocalFromMacGeneration() {
+        final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
+        final byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+                0x74, (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f};
+        final Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac();
+        assertTrue(llv6.isLinkLocalAddress());
+        assertArrayEquals(inet6ll, llv6.getAddress());
+    }
+
+    @Test
+    public void testParcelMacAddress() {
+        final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
+
+        assertParcelSane(mac, 1);
+    }
 }
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml b/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml
index c0b4673..7428130 100644
--- a/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml
@@ -33,5 +33,12 @@
                 <action android:name="android.telecom.cts.screeningtestapp.ACTION_CONTROL_CALL_SCREENING_SERVICE" />
             </intent-filter>
         </service>
+        <activity android:name=".CtsPostCallActivity"
+                  android:label="CtsPostCallActivity">
+            <intent-filter>
+                <action android:name="android.telecom.action.POST_CALL" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl b/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl
index 8da8769..9e7cc2c 100644
--- a/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl
@@ -26,4 +26,10 @@
             boolean shouldSkipCall, boolean shouldSkipCallLog, boolean shouldSkipNotification);
 
     boolean waitForBind();
+
+    boolean waitForActivity();
+
+    String getCachedHandle();
+
+    int getCachedDisconnectCause();
 }
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java
index 954d9af..96f4173 100644
--- a/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java
@@ -52,6 +52,7 @@
                             .setSkipNotification(false)
                             .build();
                     mBindingLatch = new CountDownLatch(1);
+                    CtsPostCallActivity.resetPostCallActivity();
                 }
 
                 @Override
@@ -78,6 +79,21 @@
                         return false;
                     }
                 }
+
+                @Override
+                public boolean waitForActivity() {
+                    return CtsPostCallActivity.waitForActivity();
+                }
+
+                @Override
+                public String getCachedHandle() {
+                    return CtsPostCallActivity.getCachedHandle().getSchemeSpecificPart();
+                }
+
+                @Override
+                public int getCachedDisconnectCause() {
+                    return CtsPostCallActivity.getCachedDisconnectCause();
+                }
             };
 
     private CallScreeningService.CallResponse mCallResponse =
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CtsPostCallActivity.java b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CtsPostCallActivity.java
new file mode 100644
index 0000000..ac5ce01
--- /dev/null
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CtsPostCallActivity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts.screeningtestapp;
+
+import static android.telecom.TelecomManager.EXTRA_DISCONNECT_CAUSE;
+import static android.telecom.TelecomManager.EXTRA_HANDLE;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class CtsPostCallActivity extends Activity {
+    private static final String ACTION_POST_CALL = "android.telecom.action.POST_CALL";
+    private static final int DEFAULT_DISCONNECT_CAUSE = -1;
+    private static final long TEST_TIMEOUT = 5000;
+
+    private static Uri cachedHandle;
+    private static int cachedDisconnectCause;
+    private static CountDownLatch sLatch = new CountDownLatch(1);
+
+    @Override
+    protected void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+        final Intent intent = getIntent();
+        final String action = intent != null ? intent.getAction() : null;
+        if (ACTION_POST_CALL.equals(action)) {
+            cachedHandle = intent.getParcelableExtra(EXTRA_HANDLE);
+            cachedDisconnectCause = intent
+                    .getIntExtra(EXTRA_DISCONNECT_CAUSE, DEFAULT_DISCONNECT_CAUSE);
+            sLatch.countDown();
+        }
+    }
+
+    public static Uri getCachedHandle() {
+        return cachedHandle;
+    }
+
+    public static int getCachedDisconnectCause() {
+        return cachedDisconnectCause;
+    }
+
+    public static void resetPostCallActivity() {
+        sLatch = new CountDownLatch(1);
+        cachedHandle = null;
+        cachedDisconnectCause = DEFAULT_DISCONNECT_CAUSE;
+    }
+
+    public static boolean waitForActivity() {
+        try {
+            return sLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            return false;
+        }
+    }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java
index 532c69e..76c7c72 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java
@@ -273,6 +273,32 @@
         assertFalse(mCallScreeningControl.waitForBind());
     }
 
+    public void testNoPostCallActivityWithoutRole() throws Exception {
+        if (!shouldTestTelecom(mContext)) {
+            return;
+        }
+
+        removeRoleHolder(ROLE_CALL_SCREENING, CtsCallScreeningService.class.getPackage().getName());
+        addIncomingAndVerifyAllowed(false);
+        assertFalse(mCallScreeningControl.waitForActivity());
+    }
+
+    public void testAllowCall() throws Exception {
+        mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */,
+                false /* shouldRejectCall */, false /* shouldSilenceCall */,
+                false /* shouldSkipCallLog */, false /* shouldSkipNotification */);
+        addIncomingAndVerifyAllowed(false /* addContact */);
+        assertTrue(mCallScreeningControl.waitForActivity());
+    }
+
+    public void testNoPostCallActivityWhenBlocked() throws Exception {
+        mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */,
+                true /* shouldRejectCall */, false /* shouldSilenceCall */,
+                false /* shouldSkipCallLog */, true /* shouldSkipNotification */);
+        addIncomingAndVerifyBlocked(false /* addContact */);
+        assertFalse(mCallScreeningControl.waitForActivity());
+    }
+
     private void placeOutgoingCall(boolean addContact) throws Exception {
         // Setup content observer to notify us when we call log entry is added.
         CountDownLatch callLogEntryLatch = getCallLogEntryLatch();
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 6a0156b..baf2c81 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1706,8 +1706,9 @@
         assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
     }
 
-    private static void assertSetOpportunisticInvalidParameter(int value) {
-        assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+    private static void assertSetOpportunisticNoOpportunisticSub(int value) {
+        assertThat(value).isEqualTo(
+                TelephonyManager.SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE);
     }
 
     /**
@@ -1742,18 +1743,17 @@
                 ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager,
                         (tm) -> tm.getOpportunisticSubscriptions());
         Consumer<Integer> callbackSuccess = TelephonyManagerTest::assertSetOpportunisticSubSuccess;
-        Consumer<Integer> callbackFailure =
-                TelephonyManagerTest::assertSetOpportunisticInvalidParameter;
+        Consumer<Integer> callbackNoOpSub =
+                TelephonyManagerTest::assertSetOpportunisticNoOpportunisticSub;
         if (subscriptionInfoList == null || subscriptionInfoList.size() == 0) {
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                     (tm) -> tm.setPreferredOpportunisticDataSubscription(randomSubId, false,
-                            AsyncTask.SERIAL_EXECUTOR, callbackFailure));
+                            AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
             // wait for the data change to take effect
             waitForMs(500);
             subId = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                     (tm) -> tm.getPreferredOpportunisticDataSubscription());
             assertThat(subId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
-
         } else {
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                     (tm) -> tm.setPreferredOpportunisticDataSubscription(
@@ -1785,6 +1785,11 @@
         assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
     }
 
+    private static void assertUpdateAvailableNetworkNoOpportunisticSub(int value) {
+        assertThat(value).isEqualTo(
+                TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE);
+    }
+
     private static boolean checkIfEmergencyNumberListHasSpecificAddress(
             List<EmergencyNumber> emergencyNumberList, String address) {
         for (EmergencyNumber emergencyNumber : emergencyNumberList) {
@@ -1845,9 +1850,15 @@
         int randomSubId = 1;
         int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
+        boolean isOpportunisticNetworkEnabled = ShellIdentityUtils.invokeMethodWithShellPermissions(
+                mTelephonyManager, (tm) -> tm.isOpportunisticNetworkEnabled());
+
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             return;
         }
+        if (!isOpportunisticNetworkEnabled) {
+            return;
+        }
         if (mTelephonyManager.getPhoneCount() == 1) {
             return;
         }
@@ -1865,6 +1876,8 @@
                 TelephonyManagerTest::assertUpdateAvailableNetworkSuccess;
         Consumer<Integer> callbackFailure =
                 TelephonyManagerTest::assertUpdateAvailableNetworkInvalidArguments;
+        Consumer<Integer> callbackNoOpSub =
+                TelephonyManagerTest::assertUpdateAvailableNetworkNoOpportunisticSub;
         if (subscriptionInfoList == null || subscriptionInfoList.size() == 0
                 || !mSubscriptionManager.isActiveSubscriptionId(
                 subscriptionInfoList.get(0).getSubscriptionId())) {
@@ -1873,7 +1886,7 @@
             availableNetworkInfos.add(availableNetworkInfo);
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                     (tm) -> tm.updateAvailableNetworks(availableNetworkInfos,
-                            AsyncTask.SERIAL_EXECUTOR, callbackFailure));
+                            AsyncTask.SERIAL_EXECUTOR, callbackNoOpSub));
             // wait for the data change to take effect
             waitForMs(500);
             // clear all the operations at the end of test.
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
index 9215672..dcc0f9a 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
@@ -26,6 +26,7 @@
 import android.telephony.cts.TelephonyUtils;
 import android.telephony.cts.externalimsservice.ITestExternalImsService;
 import android.telephony.cts.externalimsservice.TestExternalImsService;
+import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.stub.ImsFeatureConfiguration;
 import android.util.Log;
 
@@ -56,6 +57,7 @@
     private static final String COMMAND_CARRIER_SERVICE_IDENTIFIER = "-c ";
     private static final String COMMAND_DEVICE_SERVICE_IDENTIFIER = "-d ";
     private static final String COMMAND_SLOT_IDENTIFIER = "-s ";
+    private static final String COMMAND_FEATURE_IDENTIFIER = "-f ";
     private static final String COMMAND_ENABLE_IMS = "ims enable ";
     private static final String COMMAND_DISABLE_IMS = "ims disable ";
 
@@ -106,7 +108,9 @@
         private static final int CONNECTION_TYPE_DEFAULT_SMS_APP = 3;
 
         private boolean mIsServiceOverridden = false;
-        private String mOrigServicePackage;
+        private String mOrigMmTelServicePackage;
+        private String mOrigRcsServicePackage;
+        private String mOrigSmsPackage;
         private int mConnectionType;
         private int mSlotId;
         Connection(int connectionType, int slotId) {
@@ -118,7 +122,7 @@
             mIsServiceOverridden = true;
             switch (mConnectionType) {
                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
-                    setCarrierImsService("");
+                    setCarrierImsService("none");
                     break;
                 }
                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
@@ -152,21 +156,28 @@
             if (!mIsServiceOverridden) {
                 return;
             }
-            if (mOrigServicePackage == null) {
-                mOrigServicePackage = "";
+
+            if (mOrigRcsServicePackage == null) {
+                mOrigRcsServicePackage = "";
+            }
+
+            if (mOrigMmTelServicePackage == null) {
+                mOrigMmTelServicePackage = "";
             }
 
             switch (mConnectionType) {
                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
-                    setCarrierImsService(mOrigServicePackage);
+                    setCarrierImsService(mOrigMmTelServicePackage, ImsFeature.FEATURE_MMTEL);
+                    setCarrierImsService(mOrigRcsServicePackage, ImsFeature.FEATURE_RCS);
                     break;
                 }
                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
-                    setDeviceImsService(mOrigServicePackage);
+                    setDeviceImsService(mOrigMmTelServicePackage, ImsFeature.FEATURE_MMTEL);
+                    setDeviceImsService(mOrigRcsServicePackage, ImsFeature.FEATURE_RCS);
                     break;
                 }
                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
-                    setDefaultSmsApp(mOrigServicePackage);
+                    setDefaultSmsApp(mOrigSmsPackage);
                     break;
                 }
             }
@@ -175,15 +186,17 @@
         private void storeOriginalPackage() throws Exception {
             switch (mConnectionType) {
                 case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
-                    mOrigServicePackage = getOriginalCarrierService();
+                    mOrigMmTelServicePackage = getOriginalMmTelCarrierService();
+                    mOrigRcsServicePackage = getOriginalRcsCarrierService();
                     break;
                 }
                 case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
-                    mOrigServicePackage = getOriginalDeviceService();
+                    mOrigMmTelServicePackage = getOriginalMmTelDeviceService();
+                    mOrigRcsServicePackage = getOriginalRcsDeviceService();
                     break;
                 }
                 case CONNECTION_TYPE_DEFAULT_SMS_APP: {
-                    mOrigServicePackage = getDefaultSmsApp();
+                    mOrigSmsPackage = getDefaultSmsApp();
                     break;
                 }
             }
@@ -191,18 +204,40 @@
 
         private boolean setDeviceImsService(String packageName) throws Exception {
             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
-                    constructSetImsServiceOverrideCommand(false, packageName));
+                    constructSetImsServiceOverrideCommand(false, packageName, new int[] {
+                            ImsFeature.FEATURE_MMTEL, ImsFeature.FEATURE_RCS}));
             if (ImsUtils.VDBG) {
-                Log.d(TAG, "setDeviceImsService result: " + result);
+                Log.d(TAG, "setDeviceMmTelImsService result: " + result);
             }
             return "true".equals(result);
         }
 
         private boolean setCarrierImsService(String packageName) throws Exception {
             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
-                    constructSetImsServiceOverrideCommand(true, packageName));
+                    constructSetImsServiceOverrideCommand(true, packageName, new int[] {
+                            ImsFeature.FEATURE_MMTEL, ImsFeature.FEATURE_RCS}));
             if (ImsUtils.VDBG) {
-                Log.d(TAG, "setCarrierImsService result: " + result);
+                Log.d(TAG, "setCarrierMmTelImsService result: " + result);
+            }
+            return "true".equals(result);
+        }
+
+        private boolean setDeviceImsService(String packageName, int featureType) throws Exception {
+            String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+                    constructSetImsServiceOverrideCommand(false, packageName,
+                            new int[]{featureType}));
+            if (ImsUtils.VDBG) {
+                Log.d(TAG, "setDeviceMmTelImsService result: " + result);
+            }
+            return "true".equals(result);
+        }
+
+        private boolean setCarrierImsService(String packageName, int featureType) throws Exception {
+            String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+                    constructSetImsServiceOverrideCommand(true, packageName,
+                            new int[]{featureType}));
+            if (ImsUtils.VDBG) {
+                Log.d(TAG, "setCarrierMmTelImsService result: " + result);
             }
             return "true".equals(result);
         }
@@ -249,36 +284,67 @@
                     TestImsService.LATCH_FEATURES_READY);
         }
 
-        private String getOriginalCarrierService() throws Exception {
+        private String getOriginalMmTelCarrierService() throws Exception {
             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
-                    constructGetImsServiceCommand(true));
+                    constructGetImsServiceCommand(true, ImsFeature.FEATURE_MMTEL));
             if (ImsUtils.VDBG) {
-                Log.d(TAG, "getOriginalCarrierService result: " + result);
+                Log.d(TAG, "getOriginalMmTelCarrierService result: " + result);
             }
             return result;
         }
 
-        private String getOriginalDeviceService() throws Exception {
+        private String getOriginalRcsCarrierService() throws Exception {
             String result = TelephonyUtils.executeShellCommand(mInstrumentation,
-                    constructGetImsServiceCommand(false));
+                    constructGetImsServiceCommand(true, ImsFeature.FEATURE_RCS));
             if (ImsUtils.VDBG) {
-                Log.d(TAG, "getOriginalDeviceService result: " + result);
+                Log.d(TAG, "getOriginalRcsCarrierService result: " + result);
+            }
+            return result;
+        }
+
+        private String getOriginalMmTelDeviceService() throws Exception {
+            String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+                    constructGetImsServiceCommand(false, ImsFeature.FEATURE_MMTEL));
+            if (ImsUtils.VDBG) {
+                Log.d(TAG, "getOriginalMmTelDeviceService result: " + result);
+            }
+            return result;
+        }
+
+        private String getOriginalRcsDeviceService() throws Exception {
+            String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+                    constructGetImsServiceCommand(false, ImsFeature.FEATURE_RCS));
+            if (ImsUtils.VDBG) {
+                Log.d(TAG, "getOriginalRcsDeviceService result: " + result);
             }
             return result;
         }
 
         private String constructSetImsServiceOverrideCommand(boolean isCarrierService,
-                String packageName) {
+                String packageName, int[] featureTypes) {
             return COMMAND_BASE + COMMAND_SET_IMS_SERVICE + COMMAND_SLOT_IDENTIFIER + mSlotId + " "
                     + (isCarrierService
                         ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER)
+                    + COMMAND_FEATURE_IDENTIFIER + getFeatureTypesString(featureTypes) + " "
                     + packageName;
         }
 
-        private String constructGetImsServiceCommand(boolean isCarrierService) {
+        private String constructGetImsServiceCommand(boolean isCarrierService, int featureType) {
             return COMMAND_BASE + COMMAND_GET_IMS_SERVICE + COMMAND_SLOT_IDENTIFIER + mSlotId + " "
                     + (isCarrierService
-                        ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER);
+                        ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER)
+                    + COMMAND_FEATURE_IDENTIFIER + featureType;
+        }
+
+        private String getFeatureTypesString(int[] featureTypes) {
+            if (featureTypes.length == 0) return "";
+            StringBuilder builder = new StringBuilder();
+            builder.append(featureTypes[0]);
+            for (int i = 1; i < featureTypes.length; i++) {
+                builder.append(",");
+                builder.append(featureTypes[i]);
+            }
+            return builder.toString();
         }
     }
 
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
index 406d61a..6562d01 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
@@ -33,7 +33,6 @@
 import java.util.concurrent.Callable;
 
 public class ImsUtils {
-    public static final String TAG = "GtsImsServiceTests";
     public static final boolean VDBG = false;
 
     // ImsService rebind has an exponential backoff capping at 64 seconds. Wait for 70 seconds to