/*
 * 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.telephony.ims.cts;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;

import android.app.Activity;
import android.app.UiAutomation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PersistableBundle;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.cts.AsyncSmsMessageListener;
import android.telephony.cts.SmsReceiverHelper;
import android.telephony.ims.ImsException;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Base64;
import android.util.Pair;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.compatibility.common.util.ShellIdentityUtils;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * CTS tests for ImsService API.
 */
@RunWith(AndroidJUnit4.class)
public class ImsServiceTest {

    private static ImsServiceConnector sServiceConnector;

    private static final int RCS_CAP_NONE = RcsImsCapabilities.CAPABILITY_TYPE_NONE;
    private static final int RCS_CAP_OPTIONS = RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE;
    private static final int RCS_CAP_PRESENCE = RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;

    private static final String MSG_CONTENTS = "hi";
    private static final String EXPECTED_RECEIVED_MESSAGE = "foo5";
    private static final String DEST_NUMBER = "5555554567";
    private static final String SRC_NUMBER = "5555551234";
    private static final byte[] EXPECTED_PDU =
            new byte[]{1, 0, 10, -127, 85, 85, 85, 33, 67, 0, 0, 2, -24, 52};
    private static final String RECEIVED_MESSAGE = "B5EhYBMDIPgEC5FhBWKFkPEAAEGQQlGDUooE5ve7Bg==";
    private static final byte[] STATUS_REPORT_PDU =
            hexStringToByteArray("0006000681214365919061800000639190618000006300");

    private static int sTestSlot = 0;
    private static int sTestSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;

    private static final int TEST_CONFIG_KEY = 1000;
    private static final int TEST_CONFIG_VALUE_INT = 0xDEADBEEF;
    private static final String TEST_CONFIG_VALUE_STRING = "DEADBEEF";
    private static final String TEST_AUTOCONFIG_CONTENT = "<?xml version=\"1.0\"?>\n"
            + "<wap-provisioningdoc version=\"1.1\">\n"
            + "<characteristic type=\"VERS\">\n"
            + "<parm name=\"version\" value=\"1\"/>\n"
            + "<parm name=\"validity\" value=\"1728000\"/>\n"
            + "</characteristic>"
            + "</wap-provisioningdoc>";

    private static CarrierConfigReceiver sReceiver;

    private static class CarrierConfigReceiver extends BroadcastReceiver {
        private CountDownLatch mLatch = new CountDownLatch(1);
        private final int mSubId;

        CarrierConfigReceiver(int subId) {
            mSubId = subId;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
                int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1);
                if (mSubId == subId) {
                    mLatch.countDown();
                }
            }
        }

        void clearQueue() {
            mLatch = new CountDownLatch(1);
        }

        void waitForCarrierConfigChanged() throws Exception {
            mLatch.await(5000, TimeUnit.MILLISECONDS);
        }
    }

    @BeforeClass
    public static void beforeAllTests() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        TelephonyManager tm = (TelephonyManager) getContext()
                .getSystemService(Context.TELEPHONY_SERVICE);
        sTestSub = ImsUtils.getPreferredActiveSubId();
        sTestSlot = SubscriptionManager.getSlotIndex(sTestSub);
        if (tm.getSimState(sTestSlot) != TelephonyManager.SIM_STATE_READY) {
            return;
        }
        sServiceConnector = new ImsServiceConnector(InstrumentationRegistry.getInstrumentation());
        // Remove all live ImsServices until after these tests are done
        sServiceConnector.clearAllActiveImsServices(sTestSlot);
        // Configure SMS receiver based on the Android version.
        sServiceConnector.setDefaultSmsApp();

        sReceiver = new CarrierConfigReceiver(sTestSub);
        IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        // ACTION_CARRIER_CONFIG_CHANGED is sticky, so we will get a callback right away.
        InstrumentationRegistry.getInstrumentation().getContext()
                .registerReceiver(sReceiver, filter);
    }

    @AfterClass
    public static void afterAllTests() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Restore all ImsService configurations that existed before the test.
        if (sServiceConnector != null) {
            sServiceConnector.disconnectServices();
        }
        sServiceConnector = null;

        // Ensure there are no CarrierConfig overrides as well as reset the ImsResolver in case the
        // ImsService override changed in CarrierConfig while we were overriding it.
        overrideCarrierConfig(null);

        if (sReceiver != null) {
            InstrumentationRegistry.getInstrumentation().getContext().unregisterReceiver(sReceiver);
            sReceiver = null;
        }
    }

    @Before
    public void beforeTest() {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        TelephonyManager tm = (TelephonyManager) InstrumentationRegistry.getInstrumentation()
                .getContext().getSystemService(Context.TELEPHONY_SERVICE);
        if (tm.getSimState(sTestSlot) != TelephonyManager.SIM_STATE_READY) {
            fail("This test requires that there is a SIM in the device!");
        }
    }

    @After
    public void afterTest() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Unbind the GTS ImsService after the test completes.
        if (sServiceConnector != null) {
            sServiceConnector.disconnectCarrierImsService();
            sServiceConnector.disconnectDeviceImsService();
        }
    }

    @Test
    public void testCarrierImsServiceBindRcsFeature() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));
        // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_RCS);
        assertNotNull("ImsService created, but ImsService#createRcsFeature was not called!",
                sServiceConnector.getCarrierService().getRcsFeature());
    }

    @Test
    public void testCarrierImsServiceBindMmTelFeature() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the MmTel feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));
        // The MmTelFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL);
        assertNotNull("ImsService created, but ImsService#createMmTelFeature was not called!",
                sServiceConnector.getCarrierService().getMmTelFeature());
    }

    @Test
    public void testCarrierImsServiceBindRcsFeatureEnableDisableIms() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));
        // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_RCS));

        //Enable IMS and ensure that we receive the call to enable IMS in the ImsService.
        sServiceConnector.enableImsService(sTestSlot);
        // Wait for command in ImsService
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_ENABLE_IMS));
        assertTrue(sServiceConnector.getCarrierService().isEnabled());

        //Disable IMS and ensure that we receive the call to enable IMS in the ImsService.
        sServiceConnector.disableImsService(sTestSlot);
        // Wait for command in ImsService
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_DISABLE_IMS));
        assertFalse(sServiceConnector.getCarrierService().isEnabled());
    }

    @Test
    public void testCarrierImsServiceBindRcsChangeToMmtel() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));
        // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_RCS));

        // Change the supported feature to MMTEl
        sServiceConnector.getCarrierService().getImsService().onUpdateSupportedImsFeatures(
                new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL).build());

        // createMmTelFeature should be called.
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
    }

    @Test
    public void testCarrierImsServiceBindMmTelNoEmergency() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the MMTEL feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));
        // The MmTelFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
    }

    @Test
    public void testCarrierImsServiceBindMmTelEmergencyEnabled() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the MMTEL feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .addFeature(sTestSlot, ImsFeature.FEATURE_EMERGENCY_MMTEL)
                .build()));
        // The MmTelFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
    }

    @Test
    public void testDeviceImsServiceBindRcsFeature() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectDeviceImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));
        // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue(sServiceConnector.getExternalService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_RCS));
        // Make sure the RcsFeature was created in the test service.
        assertTrue("Device ImsService created, but TestDeviceImsService#createRcsFeature was not"
                        + "called!", sServiceConnector.getExternalService().isRcsFeatureCreated());
    }

    @Test
    public void testBindDeviceAndCarrierDifferentFeatures() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to Device the ImsService with the MMTEL/EMERGENCY_MMTEL feature.
        assertTrue(sServiceConnector.connectDeviceImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_EMERGENCY_MMTEL)
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));
        // Connect to Device the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));
        // The MmTelFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue(sServiceConnector.getExternalService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
        // Make sure the MmTelFeature was created in the test service.
        assertTrue("Device ImsService created, but TestDeviceImsService#createMmTelFeature was"
                + "not called!", sServiceConnector.getExternalService().isMmTelFeatureCreated());

        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_RCS));
        assertNotNull("ImsService created, but ImsService#createRcsFeature was not called!",
                sServiceConnector.getCarrierService().getRcsFeature());
    }

    @Test
    public void testBindDeviceAndCarrierSameFeature() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to Device the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectDeviceImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));

        //First MMTEL feature is created on device ImsService.
        assertTrue(sServiceConnector.getExternalService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
        assertTrue("Device ImsService created, but TestDeviceImsService#createMmTelFeature was "
                + "not called!", sServiceConnector.getExternalService().isMmTelFeatureCreated());

        // Connect to Device the ImsService with the MMTEL feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .addFeature(sTestSlot, ImsFeature.FEATURE_EMERGENCY_MMTEL)
                .build()));

        // Next MMTEL feature is created on carrier ImsService (and unbound on device)
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
        assertNotNull("ImsService created, but ImsService#createRcsFeature was not called!",
                sServiceConnector.getCarrierService().getMmTelFeature());

        // Ensure that the MmTelFeature was removed on the device ImsService.
        assertTrue(sServiceConnector.getExternalService().waitForLatchCountdown(
                TestImsService.LATCH_REMOVE_MMTEL));
        assertFalse("Device ImsService was never removed when carrier ImsService took MMTEL."
                + "feature.", sServiceConnector.getExternalService().isMmTelFeatureCreated());
    }

    @Test
    public void testBindDeviceAndCarrierUpdateToSameFeature() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // Connect to Device the ImsService with the MMTEL feature.
        assertTrue(sServiceConnector.connectDeviceImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));

        //First MMTEL feature is created on device ImsService.
        assertTrue(sServiceConnector.getExternalService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
        assertTrue("Device ImsService created, but TestDeviceImsService#createMmTelFeature was"
                + "not called!", sServiceConnector.getExternalService().isMmTelFeatureCreated());

        // Connect to Device the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));

        // Next Rcs feature is created on carrier ImsService
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_RCS));
        assertNotNull("ImsService created, but ImsService#createRcsFeature was not called!",
                sServiceConnector.getCarrierService().getRcsFeature());

        // Change the supported feature to MMTEl
        sServiceConnector.getCarrierService().getImsService().onUpdateSupportedImsFeatures(
                new ImsFeatureConfiguration.Builder()
                        .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                        .addFeature(sTestSlot, ImsFeature.FEATURE_EMERGENCY_MMTEL)
                        .build());

        // MMTEL feature is created on carrier ImsService
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
        assertNotNull("ImsService created, but ImsService#createMmTelFeature was not called!",
                sServiceConnector.getCarrierService().getMmTelFeature());

        // Ensure that the MmTelFeature was removed on the device ImsService.
        assertTrue(sServiceConnector.getExternalService().waitForLatchCountdown(
                TestImsService.LATCH_REMOVE_MMTEL));
        assertFalse("Device ImsService was never removed when carrier ImsService took MMTEL."
                + "feature.", sServiceConnector.getExternalService().isMmTelFeatureCreated());

        // Ensure that the RcsFeature was removed on the carrier ImsService.
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_REMOVE_RCS));
        assertNull(sServiceConnector.getCarrierService().getRcsFeature());
    }

    @Test
    public void testMmTelSendSms() throws Exception {
        if (!ImsUtils.shouldRunSmsImsTests(sTestSub)) {
            return;
        }

        setupImsServiceForSms();
        // Send Message with sent PendingIntent requested
        SmsManager.getSmsManagerForSubscriptionId(sTestSub).sendTextMessage(SRC_NUMBER,
                DEST_NUMBER, MSG_CONTENTS, SmsReceiverHelper.getMessageSentPendingIntent(
                        InstrumentationRegistry.getInstrumentation().getTargetContext()), null);
        assertTrue(sServiceConnector.getCarrierService().getMmTelFeature()
                .getSmsImplementation().waitForMessageSentLatch());

        // Wait for send PendingIntent
        Intent intent = AsyncSmsMessageListener.getInstance().waitForMessageSentIntent(
                ImsUtils.TEST_TIMEOUT_MS);
        assertNotNull("SMS send PendingIntent never received", intent);
        assertEquals("SMS send PendingIntent should have result RESULT_OK",
                Activity.RESULT_OK, intent.getIntExtra(SmsReceiverHelper.EXTRA_RESULT_CODE,
                        Activity.RESULT_CANCELED));

        // Ensure we receive correct PDU on the other side.
        Assert.assertArrayEquals(EXPECTED_PDU, sServiceConnector.getCarrierService()
                .getMmTelFeature().getSmsImplementation().sentPdu);
    }

    @Test
    public void testMmTelSendSmsDeliveryReportQCompat() throws Exception {
        if (!ImsUtils.shouldRunSmsImsTests(sTestSub)) {
            return;
        }

        setupImsServiceForSms();
        // Send Message with sent PendingIntent requested
        SmsManager.getSmsManagerForSubscriptionId(sTestSub).sendTextMessage(SRC_NUMBER,
                DEST_NUMBER, MSG_CONTENTS, null, SmsReceiverHelper.getMessageDeliveredPendingIntent(
                        InstrumentationRegistry.getInstrumentation().getTargetContext()));
        assertTrue(sServiceConnector.getCarrierService().getMmTelFeature()
                .getSmsImplementation().waitForMessageSentLatch());

        // Ensure we receive correct PDU on the other side.
        // Set TP-Status-Report-Request bit as well for this case.
        byte[] pduWithStatusReport = EXPECTED_PDU.clone();
        pduWithStatusReport[0] |= 0x20;
        Assert.assertArrayEquals(pduWithStatusReport, sServiceConnector.getCarrierService()
                .getMmTelFeature().getSmsImplementation().sentPdu);

        // Ensure the API works on Q as well as in R+, where it was deprecated.
        sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                .sendReportWaitForAcknowledgeSmsReportPQ(0, SmsMessage.FORMAT_3GPP,
                        STATUS_REPORT_PDU);

        // Wait for delivered PendingIntent
        Intent intent = AsyncSmsMessageListener.getInstance().waitForMessageDeliveredIntent(
                ImsUtils.TEST_TIMEOUT_MS);
        assertNotNull("SMS delivered PendingIntent never received", intent);
        assertEquals("SMS delivered PendingIntent should have result RESULT_OK",
                Activity.RESULT_OK, intent.getIntExtra(SmsReceiverHelper.EXTRA_RESULT_CODE,
                        Activity.RESULT_CANCELED));
    }

    @Test
    public void testMmTelSendSmsDeliveryReportR() throws Exception {
        if (!ImsUtils.shouldRunSmsImsTests(sTestSub)) {
            return;
        }

        setupImsServiceForSms();
        // Send Message with sent PendingIntent requested
        SmsManager.getSmsManagerForSubscriptionId(sTestSub).sendTextMessage(SRC_NUMBER,
                DEST_NUMBER, MSG_CONTENTS, null, SmsReceiverHelper.getMessageDeliveredPendingIntent(
                        InstrumentationRegistry.getInstrumentation().getTargetContext()));
        assertTrue(sServiceConnector.getCarrierService().getMmTelFeature()
                .getSmsImplementation().waitForMessageSentLatch());

        // Ensure we receive correct PDU on the other side.
        // Set TP-Status-Report-Request bit as well for this case.
        byte[] pduWithStatusReport = EXPECTED_PDU.clone();
        pduWithStatusReport[0] |= 0x20;
        Assert.assertArrayEquals(pduWithStatusReport, sServiceConnector.getCarrierService()
                .getMmTelFeature().getSmsImplementation().sentPdu);

        sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                .sendReportWaitForAcknowledgeSmsReportR(123456789, SmsMessage.FORMAT_3GPP,
                        STATUS_REPORT_PDU);

        // Wait for delivered PendingIntent
        Intent intent = AsyncSmsMessageListener.getInstance().waitForMessageDeliveredIntent(
                ImsUtils.TEST_TIMEOUT_MS);
        assertNotNull("SMS delivered PendingIntent never received", intent);
        assertEquals("SMS delivered PendingIntent should have result RESULT_OK",
                Activity.RESULT_OK, intent.getIntExtra(SmsReceiverHelper.EXTRA_RESULT_CODE,
                        Activity.RESULT_CANCELED));
    }

    @Test
    public void testMmTelSendSmsRSuccess() throws Exception {
        if (!ImsUtils.shouldRunSmsImsTests(sTestSub)) {
            return;
        }

        setupImsServiceForSms();

        // Send Message
        SmsManager.getSmsManagerForSubscriptionId(sTestSub).sendTextMessage(SRC_NUMBER,
                DEST_NUMBER, MSG_CONTENTS, SmsReceiverHelper.getMessageSentPendingIntent(
                        InstrumentationRegistry.getInstrumentation().getTargetContext()), null);
        // Use R specific API for sending SMS result
        assertTrue(sServiceConnector.getCarrierService().getMmTelFeature()
                .getSmsImplementation().waitForMessageSentLatchSuccess());
        Intent intent = AsyncSmsMessageListener.getInstance().waitForMessageSentIntent(
                ImsUtils.TEST_TIMEOUT_MS);
        assertNotNull(intent);
        assertEquals(Activity.RESULT_OK, intent.getIntExtra(SmsReceiverHelper.EXTRA_RESULT_CODE,
                    Activity.RESULT_CANCELED));

        // Ensure we receive correct PDU on the other side.
        Assert.assertArrayEquals(EXPECTED_PDU, sServiceConnector.getCarrierService()
                .getMmTelFeature().getSmsImplementation().sentPdu);
    }

    @Test
    public void testMmTelSendSmsNetworkError() throws Exception {
        if (!ImsUtils.shouldRunSmsImsTests(sTestSub)) {
            return;
        }

        setupImsServiceForSms();

        // Send Message
        SmsManager.getSmsManagerForSubscriptionId(sTestSub).sendTextMessage(SRC_NUMBER,
                DEST_NUMBER, MSG_CONTENTS, SmsReceiverHelper.getMessageSentPendingIntent(
                        InstrumentationRegistry.getInstrumentation().getContext()), null);
        assertTrue(sServiceConnector.getCarrierService().getMmTelFeature()
                .getSmsImplementation().waitForMessageSentLatchError(
                        SmsManager.RESULT_ERROR_GENERIC_FAILURE, 41));
        Intent intent = AsyncSmsMessageListener.getInstance().waitForMessageSentIntent(
                ImsUtils.TEST_TIMEOUT_MS);
        assertNotNull(intent);
        // In the case of error, the PendingIntent result will not report OK
        assertNotEquals(Activity.RESULT_OK, intent.getIntExtra(SmsReceiverHelper.EXTRA_RESULT_CODE,
                Activity.RESULT_OK));
        // make sure the "errorCode" extra contains the network error code returned by the
        // ImsService.
        assertEquals(41, intent.getIntExtra("errorCode", 0));

        // Ensure we receive correct PDU on the other side.
        Assert.assertArrayEquals(EXPECTED_PDU, sServiceConnector.getCarrierService()
                .getMmTelFeature().getSmsImplementation().sentPdu);
    }

    @Test
    public void testMmTelReceiveSms() throws Exception {
        if (!ImsUtils.shouldRunSmsImsTests(sTestSub)) {
            return;
        }

        setupImsServiceForSms();

        // Message received
        sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                .receiveSmsWaitForAcknowledge(123456789, SmsMessage.FORMAT_3GPP,
                        Base64.decode(RECEIVED_MESSAGE, Base64.DEFAULT));

        // Wait for SMS received intent and ensure it is correct.
        String receivedMessage = AsyncSmsMessageListener.getInstance()
                .waitForSmsMessage(ImsUtils.TEST_TIMEOUT_MS);
        assertEquals(EXPECTED_RECEIVED_MESSAGE, receivedMessage);
    }

    @Test
    public void testGetFeatureState() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        // This will set feature state to ready
        triggerFrameworkConnectToCarrierImsService();

        Integer result = getFeatureState();
        assertNotNull(result);
        assertEquals("ImsService state should be STATE_READY",
                sServiceConnector.getCarrierService().getMmTelFeature().getFeatureState(),
                ImsFeature.STATE_READY);
        assertTrue("ImsService state is ready, but STATE_READY is not reported.",
                ImsUtils.retryUntilTrue(() -> (getFeatureState() == ImsFeature.STATE_READY)));

        sServiceConnector.getCarrierService().getMmTelFeature().setFeatureState(
                ImsFeature.STATE_INITIALIZING);
        result = getFeatureState();
        assertNotNull(result);
        assertEquals("ImsService state should be STATE_INITIALIZING",
                sServiceConnector.getCarrierService().getMmTelFeature().getFeatureState(),
                ImsFeature.STATE_INITIALIZING);
        assertTrue("ImsService state is initializing, but STATE_INITIALIZING is not reported.",
                ImsUtils.retryUntilTrue(
                        () -> (getFeatureState() == ImsFeature.STATE_INITIALIZING)));

        sServiceConnector.getCarrierService().getMmTelFeature().setFeatureState(
                ImsFeature.STATE_UNAVAILABLE);
        result = getFeatureState();
        assertNotNull(result);
        assertEquals("ImsService state should be STATE_UNAVAILABLE",
                sServiceConnector.getCarrierService().getMmTelFeature().getFeatureState(),
                ImsFeature.STATE_UNAVAILABLE);
        assertTrue("ImsService state is unavailable, but STATE_UNAVAILABLE is not reported.",
                ImsUtils.retryUntilTrue(
                        () -> (getFeatureState() == ImsFeature.STATE_UNAVAILABLE)));
    }

    private Integer getFeatureState() throws Exception {
        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
        LinkedBlockingQueue<Integer> state = new LinkedBlockingQueue<>(1);
        ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mmTelManager,
                (m) -> m.getFeatureState(Runnable::run, state::offer), ImsException.class);
        return state.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
    }

    @Test
    public void testMmTelManagerRegistrationCallback() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        triggerFrameworkConnectToCarrierImsService();

        // Start deregistered
        sServiceConnector.getCarrierService().getImsRegistration().onDeregistered(
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));

        // This is a little bit gross looking, but on P devices, I can not define classes that
        // extend ImsMmTelManager.RegistrationCallback (because it doesn't exist), so this has to
        // happen as an anon class here.
        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        // Deprecated in R, see testMmTelManagerRegistrationCallbackR below.
        ImsMmTelManager.RegistrationCallback callback = new ImsMmTelManager.RegistrationCallback() {
            @Override
            public void onRegistered(int imsTransportType) {
                mQueue.offer(imsTransportType);
            }

            @Override
            public void onRegistering(int imsTransportType) {
                mQueue.offer(imsTransportType);
            }

            @Override
            public void onUnregistered(ImsReasonInfo info) {
                mQueue.offer(info.getCode());
            }

            @Override
            public void onTechnologyChangeFailed(int imsTransportType, ImsReasonInfo info) {
                mQueue.offer(imsTransportType);
                mQueue.offer(info.getCode());
            }
        };

        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        try {
            // First try without the correct permissions.
            ImsManager imsManager = getContext().getSystemService(ImsManager.class);
            ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
            mmTelManager.registerImsRegistrationCallback(getContext().getMainExecutor(), callback);
            fail("registerImsRegistrationCallback requires READ_PRECISE_PHONE_STATE permission.");
        } catch (SecurityException e) {
            //expected
        }

        // Latch will count down here (we callback on the state during registration).
        try {
            automan.adoptShellPermissionIdentity();
            ImsManager imsManager = getContext().getSystemService(ImsManager.class);
            ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
            mmTelManager.registerImsRegistrationCallback(getContext().getMainExecutor(), callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }
        assertEquals(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, waitForIntResult(mQueue));


        // Start registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));

        // Complete registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));

        // Fail handover to IWLAN
        sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        assertEquals(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE, waitForIntResult(mQueue));

        // Ensure null ImsReasonInfo still results in non-null callback value.
        sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, null);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        assertEquals(ImsReasonInfo.CODE_UNSPECIFIED, waitForIntResult(mQueue));

        // Ensure null ImsReasonInfo still results in non-null callback.
        sServiceConnector.getCarrierService().getImsRegistration().onDeregistered(null);
        assertEquals(ImsReasonInfo.CODE_UNSPECIFIED, waitForIntResult(mQueue));

        try {
            automan.adoptShellPermissionIdentity();
            ImsManager imsManager = getContext().getSystemService(ImsManager.class);
            ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
            mmTelManager.unregisterImsRegistrationCallback(callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }

        try {
            ImsManager imsManager = getContext().getSystemService(ImsManager.class);
            ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
            mmTelManager.unregisterImsRegistrationCallback(callback);
            fail("unregisterImsRegistrationCallback requires READ_PRECISE_PHONE_STATE permission.");
        } catch (SecurityException e) {
            //expected
        }
    }

    @Ignore("RCS APIs not public yet")
    @Test
    public void testRcsManagerRegistrationCallback() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        if (imsManager == null) {
            fail("Cannot find IMS service");
        }

        // Connect to device ImsService with RcsFeature
        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
        ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(sTestSub);

        // Wait for the framework to set the capabilities on the ImsService
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_RCS_CAP_SET);

        // Start de-registered
        sServiceConnector.getCarrierService().getImsRegistration().onDeregistered(
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));

        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        RegistrationManager.RegistrationCallback callback =
                new RegistrationManager.RegistrationCallback() {
                    @Override
                    public void onRegistered(int imsTransportType) {
                        mQueue.offer(imsTransportType);
                    }

                    @Override
                    public void onRegistering(int imsTransportType) {
                        mQueue.offer(imsTransportType);
                    }

                    @Override
                    public void onUnregistered(ImsReasonInfo info) {
                        mQueue.offer(info.getCode());
                    }

                    @Override
                    public void onTechnologyChangeFailed(int imsTransportType, ImsReasonInfo info) {
                        mQueue.offer(imsTransportType);
                        mQueue.offer(info.getCode());
                    }
                };

        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        try {
            automan.adoptShellPermissionIdentity();
            imsRcsManager.registerImsRegistrationCallback(getContext().getMainExecutor(), callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }
        // Verify it's not registered
        assertEquals(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, waitForIntResult(mQueue));

        // Start registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));

        // Complete registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));

        // Fail handover to IWLAN
        sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        assertEquals(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE, waitForIntResult(mQueue));

        try {
            automan.adoptShellPermissionIdentity();
            imsRcsManager.unregisterImsRegistrationCallback(callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }
    }

    @Test
    public void testMmTelManagerRegistrationStateR() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }
        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        RegistrationManager regManager = imsManager.getImsMmTelManager(sTestSub);
        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();

        triggerFrameworkConnectToCarrierImsService();

        // Start deregistered
        sServiceConnector.getCarrierService().getImsRegistration().onDeregistered(
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));

        RegistrationManager.RegistrationCallback callback =
                new RegistrationManager.RegistrationCallback() {
                    @Override
                    public void onRegistered(int imsTransportType) {
                        mQueue.offer(imsTransportType);
                    }

                    @Override
                    public void onRegistering(int imsTransportType) {
                        mQueue.offer(imsTransportType);
                    }

                    @Override
                    public void onUnregistered(ImsReasonInfo info) {
                        mQueue.offer(info.getCode());
                    }

                    @Override
                    public void onTechnologyChangeFailed(int imsTransportType, ImsReasonInfo info) {
                        mQueue.offer(imsTransportType);
                        mQueue.offer(info.getCode());
                    }
                };

        ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
        ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(mmTelManager,
                (m) -> m.registerImsRegistrationCallback(getContext().getMainExecutor(), callback),
                ImsException.class);
        assertEquals(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, waitForIntResult(mQueue));

        // Ensure that the Framework reports Deregistered correctly
        verifyRegistrationState(regManager, RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
        verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_INVALID);

        // Start registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
        verifyRegistrationState(regManager, RegistrationManager.REGISTRATION_STATE_REGISTERING);
        verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);

        // Complete registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
        verifyRegistrationState(regManager, RegistrationManager.REGISTRATION_STATE_REGISTERED);
        verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);


        // Fail handover to IWLAN
        sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        assertEquals(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE, waitForIntResult(mQueue));
        verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);

        // handover to IWLAN
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);

        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mmTelManager,
                (m) -> m.unregisterImsRegistrationCallback(callback));
    }

    @Ignore("RCS APIs not public yet")
    @Test
    public void testRcsManagerRegistrationState() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        if (imsManager == null) {
            fail("Cannot find IMS service");
        }

        // Connect to device ImsService with RcsFeature
        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_RCS_CAP_SET);

        // Start de-registered
        sServiceConnector.getCarrierService().getImsRegistration().onDeregistered(
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));

        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        RegistrationManager.RegistrationCallback callback =
                new RegistrationManager.RegistrationCallback() {
                    @Override
                    public void onRegistered(int imsTransportType) {
                        mQueue.offer(imsTransportType);
                    }

                    @Override
                    public void onRegistering(int imsTransportType) {
                        mQueue.offer(imsTransportType);
                    }

                    @Override
                    public void onUnregistered(ImsReasonInfo info) {
                        mQueue.offer(info.getCode());
                    }

                    @Override
                    public void onTechnologyChangeFailed(int imsTransportType, ImsReasonInfo info) {
                        mQueue.offer(imsTransportType);
                        mQueue.offer(info.getCode());
                    }
                };

        ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(sTestSub);
        ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(imsRcsManager,
                (m) -> m.registerImsRegistrationCallback(getContext().getMainExecutor(), callback),
                ImsException.class);
        assertEquals(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, waitForIntResult(mQueue));

        // Ensure that the Framework reports Deregistered correctly
        verifyRegistrationState(imsRcsManager,
                RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
        verifyRegistrationTransportType(imsRcsManager,
                AccessNetworkConstants.TRANSPORT_TYPE_INVALID);

        // Start registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
        verifyRegistrationState(imsRcsManager, RegistrationManager.REGISTRATION_STATE_REGISTERING);
        verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);

        // Complete registration
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
        verifyRegistrationState(imsRcsManager, RegistrationManager.REGISTRATION_STATE_REGISTERED);
        verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);

        // Fail handover to IWLAN
        sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
                new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
                        ImsReasonInfo.CODE_UNSPECIFIED, ""));
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        assertEquals(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE, waitForIntResult(mQueue));
        verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);

        // handover to IWLAN
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
        assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
        verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(imsRcsManager,
                (m) -> m.unregisterImsRegistrationCallback(callback));
    }

    @Test
    public void testCapabilityStatusCallback() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);

        triggerFrameworkConnectToCarrierImsService();

        // Wait for the framework to set the capabilities on the ImsService
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_MMTEL_CAP_SET);
        MmTelFeature.MmTelCapabilities fwCaps = sServiceConnector.getCarrierService()
                .getMmTelFeature().getCapabilities();
        // Make sure we start off with every capability unavailable
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        sServiceConnector.getCarrierService().getMmTelFeature()
                .notifyCapabilitiesStatusChanged(new MmTelFeature.MmTelCapabilities());

        // Make sure the capabilities match the API getter for capabilities
        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        // Latch will count down here (we callback on the state during registration).
        try {
            automan.adoptShellPermissionIdentity();
            // Make sure we are tracking voice capability over LTE properly.
            assertEquals(fwCaps.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE),
                    mmTelManager.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
                            ImsRegistrationImplBase.REGISTRATION_TECH_LTE));
        } finally {
            automan.dropShellPermissionIdentity();
        }

        // This is a little bit gross looking, but on P devices, I can not define classes that
        // extend ImsMmTelManager.CapabilityCallback (because it doesn't exist), so this has to
        // happen as an anon class here.
        LinkedBlockingQueue<MmTelFeature.MmTelCapabilities> mQueue = new LinkedBlockingQueue<>();
        ImsMmTelManager.CapabilityCallback callback = new ImsMmTelManager.CapabilityCallback() {

            @Override
            public void onCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities capabilities) {
                mQueue.offer(capabilities);
            }
        };

        // Latch will count down here (we callback on the state during registration).
        try {
            automan.adoptShellPermissionIdentity();
            mmTelManager.registerMmTelCapabilityCallback(getContext().getMainExecutor(), callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }

        try {
            mmTelManager.registerMmTelCapabilityCallback(getContext().getMainExecutor(), callback);
            fail("registerMmTelCapabilityCallback requires READ_PRECISE_PHONE_STATE permission.");
        } catch (SecurityException e) {
            //expected
        }

        // We should not have voice availability here, we notified the framework earlier.
        MmTelFeature.MmTelCapabilities capCb = waitForResult(mQueue);
        assertNotNull(capCb);
        assertFalse(capCb.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE));

        // Now enable voice availability
        sServiceConnector.getCarrierService().getMmTelFeature()
                .notifyCapabilitiesStatusChanged(new MmTelFeature.MmTelCapabilities(
                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE));
        capCb = waitForResult(mQueue);
        assertNotNull(capCb);
        assertTrue(capCb.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE));

        try {
            automan.adoptShellPermissionIdentity();
            assertTrue(ImsUtils.retryUntilTrue(() -> mmTelManager.isAvailable(
                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE)));

            mmTelManager.unregisterMmTelCapabilityCallback(callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }

        try {
            mmTelManager.unregisterMmTelCapabilityCallback(callback);
            fail("unregisterMmTelCapabilityCallback requires READ_PRECISE_PHONE_STATE permission.");
        } catch (SecurityException e) {
            //expected
        }
    }

    /**
     * We are specifically testing a race case here such that IsAvailable returns the correct
     * capability status during the callback.
     */
    @Test
    public void testCapabilityStatusWithIsAvailableDuringCallback() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);

        triggerFrameworkConnectToCarrierImsService();

        // Wait for the framework to set the capabilities on the ImsService
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_MMTEL_CAP_SET);


        // Make sure we start off with every capability unavailable
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        MmTelFeature.MmTelCapabilities stdCapabilities = new MmTelFeature.MmTelCapabilities();
        sServiceConnector.getCarrierService().getMmTelFeature()
                .notifyCapabilitiesStatusChanged(stdCapabilities);


        // Make sure the capabilities match the API getter for capabilities
        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();

        //This lock is to keep the shell permissions from being dropped on a different thread
        //causing a permission error.
        Object lockObj = new Object();

        synchronized (lockObj) {
            try {
                automan.adoptShellPermissionIdentity();
                boolean isAvailableBeforeStatusChange = mmTelManager.isAvailable(
                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
                        ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
                assertFalse(isAvailableBeforeStatusChange);
            } finally {
                automan.dropShellPermissionIdentity();
            }
        }

        LinkedBlockingQueue<Boolean> voiceIsAvailable = new LinkedBlockingQueue<>();
        ImsMmTelManager.CapabilityCallback verifyCapabilityStatusCallaback =
                new ImsMmTelManager.CapabilityCallback() {
            @Override
            public void onCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities capabilities) {
                synchronized (lockObj) {
                    try {
                        automan.adoptShellPermissionIdentity();
                        boolean isVoiceAvailable = mmTelManager
                                .isAvailable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
                                        ImsRegistrationImplBase.REGISTRATION_TECH_LTE);

                        voiceIsAvailable.offer(isVoiceAvailable);
                    } finally {
                        automan.dropShellPermissionIdentity();
                    }
                }
            }
        };

        synchronized (lockObj) {
            // Latch will count down here (we callback on the state during registration).
            try {
                automan.adoptShellPermissionIdentity();
                mmTelManager.registerMmTelCapabilityCallback(getContext().getMainExecutor(),
                        verifyCapabilityStatusCallaback);
            } finally {
                automan.dropShellPermissionIdentity();
            }
        }

        // Now enable voice availability
        Boolean isAvailableDuringRegister = waitForResult(voiceIsAvailable);
        assertNotNull(isAvailableDuringRegister);
        assertFalse(isAvailableDuringRegister);
        sServiceConnector.getCarrierService().getMmTelFeature()
                .notifyCapabilitiesStatusChanged(new MmTelFeature.MmTelCapabilities(
                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE));
        Boolean isAvailableAfterStatusChange = waitForResult(voiceIsAvailable);
        assertNotNull(isAvailableAfterStatusChange);
        assertTrue(isAvailableAfterStatusChange);

        synchronized (lockObj) {
            try {
                automan.adoptShellPermissionIdentity();
                mmTelManager.unregisterMmTelCapabilityCallback(verifyCapabilityStatusCallaback);
            } finally {
                automan.dropShellPermissionIdentity();
            }
        }
    }

    @Test
    public void testProvisioningManagerNotifyAutoConfig() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        // Trigger carrier config changed
        PersistableBundle bundle = new PersistableBundle();
        bundle.putBoolean(CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, true);
        bundle.putBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true);
        overrideCarrierConfig(bundle);

        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();

        ProvisioningManager provisioningManager =
                ProvisioningManager.createForSubscriptionId(sTestSub);

        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        try {
            automan.adoptShellPermissionIdentity();
            provisioningManager.notifyRcsAutoConfigurationReceived(
                    TEST_AUTOCONFIG_CONTENT.getBytes(), false);
            ImsConfigImplBase config = sServiceConnector.getCarrierService().getConfig();
            Assert.assertNotNull(config);
            assertEquals(TEST_AUTOCONFIG_CONTENT,
                    config.getConfigString(ImsUtils.ITEM_NON_COMPRESSED));

            provisioningManager.notifyRcsAutoConfigurationReceived(
                    TEST_AUTOCONFIG_CONTENT.getBytes(), true);
            assertEquals(TEST_AUTOCONFIG_CONTENT,
                    config.getConfigString(ImsUtils.ITEM_COMPRESSED));
        } finally {
            automan.dropShellPermissionIdentity();
        }
    }

    @Ignore("RCS APIs not public yet")
    @Test
    public void testRcsCapabilityStatusCallback() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
        if (imsManager == null) {
            fail("Cannot find IMS service");
        }

        // Connect to device ImsService with RcsFeature
        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();

        int registrationTech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
        ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(sTestSub);

        // Wait for the framework to set the capabilities on the ImsService
        sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_RCS_CAP_SET);
        // Make sure we start off with none-capability
        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
        RcsImsCapabilities noCapabilities = new RcsImsCapabilities(RCS_CAP_NONE);
        sServiceConnector.getCarrierService().getRcsFeature()
                .notifyCapabilitiesStatusChanged(noCapabilities);

        // Make sure the capabilities match the API getter for capabilities
        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        // Latch will count down here (we callback on the state during registration).
        try {
            automan.adoptShellPermissionIdentity();
            // Make sure we are tracking voice capability over LTE properly.
            RcsImsCapabilities availability = sServiceConnector.getCarrierService()
                    .getRcsFeature().queryCapabilityStatus();
            assertEquals(availability.isCapable(RCS_CAP_PRESENCE),
                    imsRcsManager.isAvailable(RCS_CAP_PRESENCE));
        } finally {
            automan.dropShellPermissionIdentity();
        }

        // Trigger carrier config changed
        PersistableBundle bundle = new PersistableBundle();
        bundle.putBoolean(CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, true);
        bundle.putBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true);
        overrideCarrierConfig(bundle);

        // The carrier config changed should trigger RcsFeature#changeEnabledCapabilities
        try {
            automan.adoptShellPermissionIdentity();
            // Checked by isCapable api to make sure RcsFeature#changeEnabledCapabilities is called
            assertTrue(ImsUtils.retryUntilTrue(() ->
                    imsRcsManager.isCapable(RCS_CAP_OPTIONS, registrationTech)));
            assertTrue(ImsUtils.retryUntilTrue(() ->
                    imsRcsManager.isCapable(RCS_CAP_PRESENCE, registrationTech)));
        } finally {
            automan.dropShellPermissionIdentity();
        }

        // A queue to receive capability changed
        LinkedBlockingQueue<RcsImsCapabilities> mQueue = new LinkedBlockingQueue<>();
        ImsRcsManager.AvailabilityCallback callback = new ImsRcsManager.AvailabilityCallback() {
            @Override
            public void onAvailabilityChanged(RcsImsCapabilities capabilities) {
                mQueue.offer(capabilities);
            }
        };

        // Latch will count down here (we callback on the state during registration).
        try {
            automan.adoptShellPermissionIdentity();
            imsRcsManager.registerRcsAvailabilityCallback(getContext().getMainExecutor(), callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }

        // We should not have any availabilities here, we notified the framework earlier.
        RcsImsCapabilities capCb = waitForResult(mQueue);

        // The SIP OPTIONS capability from onAvailabilityChanged should be disabled.
        // Moreover, ImsRcsManager#isAvailable also return FALSE with SIP OPTIONS
        assertTrue(capCb.isCapable(RCS_CAP_NONE));
        try {
            automan.adoptShellPermissionIdentity();
            assertFalse(imsRcsManager.isAvailable(RCS_CAP_OPTIONS));
        } finally {
            automan.dropShellPermissionIdentity();
        }

        // Notify the SIP OPTIONS capability status changed
        RcsImsCapabilities optionsCap = new RcsImsCapabilities(RCS_CAP_OPTIONS);
        sServiceConnector.getCarrierService().getRcsFeature()
                .notifyCapabilitiesStatusChanged(optionsCap);
        capCb = waitForResult(mQueue);

        // The SIP OPTIONS capability from onAvailabilityChanged should be enabled.
        // Verify ImsRcsManager#isAvailable also return true with SIP OPTIONS
        assertTrue(capCb.isCapable(RCS_CAP_OPTIONS));
        try {
            automan.adoptShellPermissionIdentity();
            assertTrue(imsRcsManager.isAvailable(RCS_CAP_OPTIONS));
        } finally {
            automan.dropShellPermissionIdentity();
        }

        overrideCarrierConfig(null);
    }

    @Test
    public void testProvisioningManagerSetConfig() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        triggerFrameworkConnectToCarrierImsService();

        ProvisioningManager provisioningManager =
                ProvisioningManager.createForSubscriptionId(sTestSub);

        // This is a little bit gross looking, but on P devices, I can not define classes that
        // extend ProvisioningManager.Callback (because it doesn't exist), so this has to
        // happen as an anon class here.
        LinkedBlockingQueue<Pair<Integer, Integer>> mIntQueue = new LinkedBlockingQueue<>();
        LinkedBlockingQueue<Pair<Integer, String>> mStringQueue = new LinkedBlockingQueue<>();
        ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {
            @Override
            public void onProvisioningIntChanged(int item, int value) {
                mIntQueue.offer(new Pair<>(item, value));
            }

            @Override
            public void onProvisioningStringChanged(int item, String value) {
                mStringQueue.offer(new Pair<>(item, value));
            }
        };

        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        try {
            automan.adoptShellPermissionIdentity();
            provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
                    callback);

            provisioningManager.setProvisioningIntValue(TEST_CONFIG_KEY, TEST_CONFIG_VALUE_INT);
            assertTrue(waitForParam(mIntQueue, new Pair<>(TEST_CONFIG_KEY, TEST_CONFIG_VALUE_INT)));
            assertEquals(TEST_CONFIG_VALUE_INT,
                    provisioningManager.getProvisioningIntValue(TEST_CONFIG_KEY));

            provisioningManager.setProvisioningStringValue(TEST_CONFIG_KEY,
                    TEST_CONFIG_VALUE_STRING);
            assertTrue(waitForParam(mStringQueue,
                    new Pair<>(TEST_CONFIG_KEY, TEST_CONFIG_VALUE_STRING)));
            assertEquals(TEST_CONFIG_VALUE_STRING,
                    provisioningManager.getProvisioningStringValue(TEST_CONFIG_KEY));

            automan.adoptShellPermissionIdentity();
            provisioningManager.unregisterProvisioningChangedCallback(callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }
    }

    @Ignore("The ProvisioningManager constants were moved back to @hide for now, don't want to "
            + "completely remove test.")
    @Test
    public void testProvisioningManagerConstants() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        triggerFrameworkConnectToCarrierImsService();

        ProvisioningManager provisioningManager =
                ProvisioningManager.createForSubscriptionId(sTestSub);

        // This is a little bit gross looking, but on P devices, I can not define classes that
        // extend ProvisioningManager.Callback (because it doesn't exist), so this has to
        // happen as an anon class here.
        LinkedBlockingQueue<Pair<Integer, Integer>> mIntQueue = new LinkedBlockingQueue<>();
        LinkedBlockingQueue<Pair<Integer, String>> mStringQueue = new LinkedBlockingQueue<>();
        ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {
            @Override
            public void onProvisioningIntChanged(int item, int value) {
                mIntQueue.offer(new Pair<>(item, value));
            }

            @Override
            public void onProvisioningStringChanged(int item, String value) {
                mStringQueue.offer(new Pair<>(item, value));
            }
        };

        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        try {
            automan.adoptShellPermissionIdentity();
            provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
                    callback);

            verifyStringKey(provisioningManager, mStringQueue,
                    ProvisioningManager.KEY_AMR_CODEC_MODE_SET_VALUES, "1,2");
            verifyStringKey(provisioningManager, mStringQueue,
                    ProvisioningManager.KEY_AMR_WB_CODEC_MODE_SET_VALUES, "1,2");
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_SESSION_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_MINIMUM_SIP_SESSION_EXPIRATION_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_INVITE_CANCELLATION_TIMER_MS, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_TRANSITION_TO_LTE_DELAY_MS, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_ENABLE_SILENT_REDIAL, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_T1_TIMER_VALUE_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_T2_TIMER_VALUE_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_TF_TIMER_VALUE_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VT_PROVISIONING_STATUS, 0);
            verifyStringKey(provisioningManager, mStringQueue,
                    ProvisioningManager.KEY_REGISTRATION_DOMAIN_NAME, "test.com");
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SMS_FORMAT, ProvisioningManager.SMS_FORMAT_3GPP);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SMS_FORMAT, ProvisioningManager.SMS_FORMAT_3GPP2);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SMS_OVER_IP_ENABLED, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_PUBLISH_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_CAPABILITY_DISCOVERY_ENABLED, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_AVAILABILITY_CACHE_EXPIRATION_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_CAPABILITIES_POLL_INTERVAL_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS, 1000);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_MAX_NUM_ENTRIES_IN_RCL, 50);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_USE_GZIP_FOR_LIST_SUBSCRIPTION, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_EAB_PROVISIONING_STATUS, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_MOBILE_DATA_ENABLED, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VOLTE_USER_OPT_IN_STATUS, 0);
            verifyStringKey(provisioningManager, mStringQueue,
                    ProvisioningManager.KEY_LOCAL_BREAKOUT_PCSCF_ADDRESS, "local.fun.com");
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_KEEP_ALIVE_ENABLED, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_REGISTRATION_RETRY_BASE_TIME_SEC, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_REGISTRATION_RETRY_MAX_TIME_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RTP_SPEECH_START_PORT, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RTP_SPEECH_END_PORT, 600);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_INVITE_REQUEST_TRANSMIT_INTERVAL_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_INVITE_ACK_WAIT_TIME_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_INVITE_RESPONSE_RETRANSMIT_WAIT_TIME_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_NON_INVITE_TRANSACTION_TIMEOUT_TIMER_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_INVITE_RESPONSE_RETRANSMIT_INTERVAL_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_ACK_RECEIPT_WAIT_TIME_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_ACK_RETRANSMIT_WAIT_TIME_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_NON_INVITE_REQUEST_RETRANSMISSION_WAIT_TIME_MS, 500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SIP_NON_INVITE_RESPONSE_RETRANSMISSION_WAIT_TIME_MS,
                    500);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_AMR_WB_OCTET_ALIGNED_PAYLOAD_TYPE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_AMR_WB_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_AMR_OCTET_ALIGNED_PAYLOAD_TYPE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_AMR_BANDWIDTH_EFFICIENT_PAYLOAD_TYPE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_DTMF_WB_PAYLOAD_TYPE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_DTMF_NB_PAYLOAD_TYPE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_AMR_DEFAULT_ENCODING_MODE, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_SMS_PUBLIC_SERVICE_IDENTITY, 0);
            verifyStringKey(provisioningManager, mStringQueue,
                    ProvisioningManager.KEY_SMS_PUBLIC_SERVICE_IDENTITY, "local.fun.com");
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VIDEO_QUALITY, ProvisioningManager.VIDEO_QUALITY_HIGH);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_VIDEO_QUALITY, ProvisioningManager.VIDEO_QUALITY_LOW);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_LTE_THRESHOLD_1, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_LTE_THRESHOLD_2, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_LTE_THRESHOLD_3, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_1X_THRESHOLD, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_WIFI_THRESHOLD_A, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_WIFI_THRESHOLD_B, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_1X_EPDG_TIMER_SEC, 5);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_MULTIENDPOINT_ENABLED, 0);
            verifyIntKey(provisioningManager, mIntQueue,
                    ProvisioningManager.KEY_RTT_ENABLED, 0);

            automan.adoptShellPermissionIdentity();
            provisioningManager.unregisterProvisioningChangedCallback(callback);
        } finally {
            automan.dropShellPermissionIdentity();
        }
    }

    @Test
    public void testProvisioningManagerProvisioningCaps() throws Exception {
        if (!ImsUtils.shouldTestImsService()) {
            return;
        }

        triggerFrameworkConnectToCarrierImsService();

        PersistableBundle bundle = new PersistableBundle();
        bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, true);
        bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL, true);
        overrideCarrierConfig(bundle);

        ProvisioningManager provisioningManager =
                ProvisioningManager.createForSubscriptionId(sTestSub);

        final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
        try {
            automan.adoptShellPermissionIdentity();
            boolean provisioningStatus = provisioningManager.getProvisioningStatusForCapability(
                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
            provisioningManager.setProvisioningStatusForCapability(
                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE, !provisioningStatus);
            // Make sure the change in provisioning status is correctly returned.
            assertEquals(!provisioningStatus,
                    provisioningManager.getProvisioningStatusForCapability(
                            MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
                            ImsRegistrationImplBase.REGISTRATION_TECH_LTE));
            // TODO: Enhance test to make sure the provisioning change is also sent to the
            // ImsService

            // set back to current status
            provisioningManager.setProvisioningStatusForCapability(
                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE, provisioningStatus);
        } finally {
            automan.dropShellPermissionIdentity();
        }

        overrideCarrierConfig(null);
    }

    private void verifyIntKey(ProvisioningManager pm,
            LinkedBlockingQueue<Pair<Integer, Integer>> intQueue, int key, int value)
            throws Exception {
        pm.setProvisioningIntValue(key, value);
        assertTrue(waitForParam(intQueue, new Pair<>(key, value)));
        assertEquals(value, pm.getProvisioningIntValue(key));
    }

    private void verifyStringKey(ProvisioningManager pm,
            LinkedBlockingQueue<Pair<Integer, String>> strQueue, int key, String value)
            throws Exception {
        pm.setProvisioningStringValue(key, value);
        assertTrue(waitForParam(strQueue, new Pair<>(key, value)));
        assertEquals(value, pm.getProvisioningStringValue(key));
    }

    private void setupImsServiceForSms() throws Exception {
        MmTelFeature.MmTelCapabilities capabilities = new MmTelFeature.MmTelCapabilities(
                MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS);
        // Set up MMTEL
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));
        // Wait until MMTEL is created and onFeatureReady is called
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_CREATE_MMTEL));
        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
                TestImsService.LATCH_MMTEL_READY));
        int serviceSlot = sServiceConnector.getCarrierService().getMmTelFeature().getSlotIndex();
        assertEquals("The slot specified for the test (" + sTestSlot + ") does not match the "
                        + "assigned slot (" + serviceSlot + "+ for the associated MmTelFeature",
                sTestSlot, serviceSlot);
        // Wait until ImsSmsDispatcher connects and calls onReady.
        assertTrue(sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                .waitForOnReadyLatch());
        // Set Registered and SMS capable
        sServiceConnector.getCarrierService().getMmTelFeature().setCapabilities(capabilities);
        sServiceConnector.getCarrierService().getImsService().getRegistration(0).onRegistered(1);
        sServiceConnector.getCarrierService().getMmTelFeature()
                .notifyCapabilitiesStatusChanged(capabilities);

        // Wait a second for the notifyCapabilitiesStatusChanged indication to be processed on the
        // main telephony thread - currently no better way of knowing that telephony has processed
        // this command. SmsManager#isImsSmsSupported() is @hide and must be updated to use new API.
        Thread.sleep(1000);
    }

    private void triggerFrameworkConnectToLocalImsServiceBindRcsFeature() throws Exception {
        // Connect to the ImsService with the RCS feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
                .build()));
        // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue("Did not receive createRcsFeature", sServiceConnector.getCarrierService()
                .waitForLatchCountdown(TestImsService.LATCH_CREATE_RCS));
        assertTrue("Did not receive RcsFeature#onReady", sServiceConnector.getCarrierService()
                .waitForLatchCountdown(TestImsService.LATCH_RCS_READY));
        // Make sure the RcsFeature was created in the test service.
        assertNotNull("Device ImsService created, but TestDeviceImsService#createRcsFeature was not"
                + "called!", sServiceConnector.getCarrierService().getRcsFeature());
        int serviceSlot = sServiceConnector.getCarrierService().getRcsFeature().getSlotIndex();
        assertEquals("The slot specified for the test (" + sTestSlot + ") does not match the "
                        + "assigned slot (" + serviceSlot + "+ for the associated RcsFeature",
                sTestSlot, serviceSlot);
    }

    private void triggerFrameworkConnectToCarrierImsService() throws Exception {
        // Connect to the ImsService with the MmTel feature.
        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
                .build()));
        // The MmTelFeature is created when the ImsService is bound. If it wasn't created, then the
        // Framework did not call it.
        assertTrue("Did not receive createMmTelFeature", sServiceConnector.getCarrierService()
                .waitForLatchCountdown(TestImsService.LATCH_CREATE_MMTEL));
        assertTrue("Did not receive MmTelFeature#onReady", sServiceConnector.getCarrierService()
                .waitForLatchCountdown(TestImsService.LATCH_MMTEL_READY));
        assertNotNull("ImsService created, but ImsService#createMmTelFeature was not called!",
                sServiceConnector.getCarrierService().getMmTelFeature());
        int serviceSlot = sServiceConnector.getCarrierService().getMmTelFeature().getSlotIndex();
        assertEquals("The slot specified for the test (" + sTestSlot + ") does not match the "
                        + "assigned slot (" + serviceSlot + "+ for the associated MmTelFeature",
                sTestSlot, serviceSlot);
    }

    // Waiting for ImsRcsManager to become public before implementing RegistrationManager,
    // Duplicate these methods for now.
    private void verifyRegistrationState(ImsRcsManager regManager, int expectedState)
            throws Exception {
        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        assertTrue(ImsUtils.retryUntilTrue(() -> {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(regManager,
                    (m) -> m.getRegistrationState(getContext().getMainExecutor(), mQueue::offer));
            return waitForIntResult(mQueue) == expectedState;
        }));
    }

    // Waiting for ImsRcsManager to become public before implementing RegistrationManager,
    // Duplicate these methods for now.
    private void verifyRegistrationTransportType(ImsRcsManager regManager,
            int expectedTransportType) throws Exception {
        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(regManager,
                (m) -> m.getRegistrationTransportType(getContext().getMainExecutor(),
                        mQueue::offer));
        assertEquals(expectedTransportType, waitForIntResult(mQueue));
    }

    private void verifyRegistrationState(RegistrationManager regManager, int expectedState)
            throws Exception {
        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        assertTrue(ImsUtils.retryUntilTrue(() -> {
            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(regManager,
                    (m) -> m.getRegistrationState(getContext().getMainExecutor(), mQueue::offer));
            return waitForIntResult(mQueue) == expectedState;
        }));
    }

    private void verifyRegistrationTransportType(RegistrationManager regManager,
            int expectedTransportType) throws Exception {
        LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(regManager,
                (m) -> m.getRegistrationTransportType(getContext().getMainExecutor(),
                        mQueue::offer));
        assertEquals(expectedTransportType, waitForIntResult(mQueue));
    }

    private <T> boolean waitForParam(LinkedBlockingQueue<T> queue, T waitParam) throws Exception {
        T result;
        while ((result = waitForResult(queue)) != null) {
            if (waitParam.equals(result)) {
                return true;
            }
        }
        return false;
    }

    private <T> T waitForResult(LinkedBlockingQueue<T> queue) throws Exception {
        return queue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
    }

    private int waitForIntResult(LinkedBlockingQueue<Integer> queue) throws Exception {
        Integer result = queue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        return result != null ? result : Integer.MAX_VALUE;
    }

    private static void overrideCarrierConfig(PersistableBundle bundle) throws Exception {
        CarrierConfigManager carrierConfigManager = InstrumentationRegistry.getInstrumentation()
                .getContext().getSystemService(CarrierConfigManager.class);
        sReceiver.clearQueue();
        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(carrierConfigManager,
                (m) -> m.overrideConfig(sTestSub, bundle));
        sReceiver.waitForCarrierConfigChanged();
    }

    private static Context getContext() {
        return InstrumentationRegistry.getInstrumentation().getContext();
    }

    // Copied from com.android.internal.util.HexDump
    private static byte[] hexStringToByteArray(String hexString) {
        int length = hexString.length();
        byte[] buffer = new byte[length / 2];

        for (int i = 0; i < length; i += 2) {
            buffer[i / 2] =
                    (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1)));
        }

        return buffer;
    }

    // Copied from com.android.internal.util.HexDump
    private static int toByte(char c) {
        if (c >= '0' && c <= '9') return (c - '0');
        if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
        if (c >= 'a' && c <= 'f') return (c - 'a' + 10);

        throw new RuntimeException("Invalid hex char '" + c + "'");
    }
}
