Merge "Make window manager cts apps debuggable"
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 9806359..2e2c775 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -449,6 +449,7 @@
                 self._hidden_physical_id, self._camera_id)
             assert self._hidden_physical_id in physical_ids, e_msg
             props = self.get_camera_properties_by_id(self._hidden_physical_id)
+            self.props = props
         return props
 
     def get_camera_properties(self):
diff --git a/apps/CameraITS/tools/validate_scene.py b/apps/CameraITS/tools/validate_scene.py
index 890cf12..e641718 100644
--- a/apps/CameraITS/tools/validate_scene.py
+++ b/apps/CameraITS/tools/validate_scene.py
@@ -50,6 +50,7 @@
                 "\nThe scene setup should be: " + scene_desc )
         # Converge 3A prior to capture.
         props = cam.get_camera_properties()
+        props = cam.override_with_hidden_physical_camera_props(props)
         cam.do_3a(do_af=do_af, lock_ae=its.caps.ae_lock(props),
                   lock_awb=its.caps.awb_lock(props))
         req = its.objects.fastest_auto_capture_request(props)
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java
index b7e0fb1..6563e7e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java
@@ -19,6 +19,7 @@
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.res.Resources;
 import android.hardware.biometrics.BiometricManager;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
@@ -246,8 +247,9 @@
     }
 
     static boolean deviceConfigContains(Context context, int authenticator) {
-        final String config[] = context.getResources()
-                .getStringArray(com.android.internal.R.array.config_biometric_sensors);
+        final Resources res = context.getResources();
+        final int resId = res.getIdentifier("config_biometric_sensors", "array", "android");
+        final String config[] = res.getStringArray(resId);
         for (String s : config) {
             Log.d(TAG, s);
             final String[] elems = s.split(":");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
index 08581f6..3059821 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppDataIsolationTests.java
@@ -189,6 +189,10 @@
 
     @Test
     public void testDirectBootModeWorks() throws Exception {
+        if (!"file".equals(getDevice().getProperty("ro.crypto.type"))) {
+            LogUtil.CLog.d("Device is NOT encrypted with file-based encryption. skipping test");
+            return;
+        }
         assumeTrue("Screen lock is not supported so skip direct boot test",
                 hasDeviceFeature("android.software.secure_lock_screen"));
         // Install AppA and verify no data stored
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/BaseBlobStoreDeviceTest.java b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/BaseBlobStoreDeviceTest.java
index 81cd918..aa9f439 100644
--- a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/BaseBlobStoreDeviceTest.java
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/BaseBlobStoreDeviceTest.java
@@ -38,7 +38,7 @@
 
     protected static final long PARTIAL_FILE_LENGTH_BYTES = 2002;
     protected static final long TIMEOUT_WAIT_FOR_IDLE_MS = 2_000;
-    protected static final long TIMEOUT_COMMIT_CALLBACK_MS = 10_000;
+    protected static final long TIMEOUT_COMMIT_CALLBACK_MS = 30_000;
 
     protected Context mContext;
     protected Instrumentation mInstrumentation;
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
index 891bd72..7e4cd3d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
@@ -63,14 +63,14 @@
         mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT, DISALLOW_AUTOFILL);
 
         // Must try a couple times because it will be disabled asynchronously.
-        for (int i = 1; i <= 5; i++) {
+        for (int i = 1; i <= 15; i++) {
             final boolean disabledAfter = !launchActivityAndGetEnabled();
             if (disabledAfter) {
                 return;
             }
             Thread.sleep(100);
         }
-        fail("Not disabled after 2.5s");
+        fail("Not disabled after a period of time");
     }
 
     private boolean launchActivityAndGetEnabled() throws Exception {
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java
index 5fb2187..e6bd499 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemInformationTest.java
@@ -23,6 +23,7 @@
 import android.hdmicec.cts.CecClientMessage;
 import android.hdmicec.cts.CecMessage;
 import android.hdmicec.cts.CecOperand;
+import android.hdmicec.cts.LogicalAddress;
 
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
@@ -31,6 +32,9 @@
 import org.junit.rules.RuleChain;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+import java.util.List;
+
 /** HDMI CEC system information tests (Section 11.2.6) */
 @RunWith(DeviceJUnit4ClassRunner.class)
 public final class HdmiCecSystemInformationTest extends BaseHdmiCecCtsTest {
@@ -60,18 +64,33 @@
     }
 
     /**
-     * Test 11.2.6-2
-     * Tests that the device sends a {@code <Report Physical Address>} in response to a
-     * {@code <Give Physical Address>}
+     * Tests 11.2.6-2, 10.1.1.1-1
+     *
+     * <p>Tests that the device sends a {@code <Report Physical Address>} in response to a {@code
+     * <Give Physical Address>}
      */
     @Test
     public void cect_11_2_6_2_GivePhysicalAddress() throws Exception {
-        hdmiCecClient.sendCecMessage(CecOperand.GIVE_PHYSICAL_ADDRESS);
-        String message = hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
-        /* Check that the physical address taken is valid. */
-        CecMessage.assertPhysicalAddressValid(message, getDumpsysPhysicalAddress());
-        int receivedParams = CecMessage.getParams(message);
-        assertThat(receivedParams & 0xFF).isEqualTo(mDutLogicalAddress.getDeviceType());
+        List<LogicalAddress> testDevices =
+                Arrays.asList(
+                        LogicalAddress.TV,
+                        LogicalAddress.RECORDER_1,
+                        LogicalAddress.TUNER_1,
+                        LogicalAddress.PLAYBACK_1,
+                        LogicalAddress.AUDIO_SYSTEM,
+                        LogicalAddress.BROADCAST);
+        for (LogicalAddress testDevice : testDevices) {
+            if (testDevice == mDutLogicalAddress) {
+                /* Skip the DUT logical address */
+                continue;
+            }
+            hdmiCecClient.sendCecMessage(testDevice, CecOperand.GIVE_PHYSICAL_ADDRESS);
+            String message = hdmiCecClient.checkExpectedOutput(CecOperand.REPORT_PHYSICAL_ADDRESS);
+            /* Check that the physical address taken is valid. */
+            CecMessage.assertPhysicalAddressValid(message, getDumpsysPhysicalAddress());
+            int receivedParams = CecMessage.getParams(message);
+            assertThat(receivedParams & 0xFF).isEqualTo(mDutLogicalAddress.getDeviceType());
+        }
     }
 
     /**
diff --git a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
index 6741b82..6de6044 100644
--- a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
+++ b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
@@ -262,6 +262,8 @@
         put("SDM429", null);
         put("SDM439", null);
         put("QM215", null);
+        put("ATOLL", null);
+        put("ATOLL-AB", null);
         put("BENGAL", new String[]{"CONFIG_HARDEN_BRANCH_PREDICTOR=y"});
         put("DEFAULT", new String[]{"CONFIG_HARDEN_BRANCH_PREDICTOR=y",
             "CONFIG_UNMAP_KERNEL_AT_EL0=y"});
diff --git a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
index 0c1d2ed..685d188 100644
--- a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
+++ b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
@@ -83,7 +83,7 @@
 @RunWith(BlobStoreTestRunner.class)
 public class BlobStoreManagerTest {
 
-    private static final long TIMEOUT_COMMIT_CALLBACK_SEC = 10;
+    private static final long TIMEOUT_COMMIT_CALLBACK_SEC = 30;
 
     private static final long TIMEOUT_BIND_SERVICE_SEC = 2;
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultiScreenDifferentActivitiesTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultiScreenDifferentActivitiesTest.java
index 122cfc5..7d8d4be 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultiScreenDifferentActivitiesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultiScreenDifferentActivitiesTest.java
@@ -140,5 +140,8 @@
         assertTextAndValue(findNodeByResourceId(structure2, ID_INPUT), "ID");
         final ComponentName component2 = structure2.getActivityComponent();
         assertThat(component2).isEqualTo(activity2.getComponentName());
+        activity2.syncRunOnUiThread(() -> {
+            activity2.mInput.setFocusable(false);
+        });
     }
 }
diff --git a/tests/tests/os/OWNERS b/tests/tests/os/OWNERS
new file mode 100644
index 0000000..3429892
--- /dev/null
+++ b/tests/tests/os/OWNERS
@@ -0,0 +1,4 @@
+per-file *AutoRevoke* = eugenesusla@google.com
+per-file *Companion* = eugenesusla@google.com
+per-file *AndroidManifest.xml = eugenesusla@google.com
+per-file *CtsOsTestCases.xml = eugenesusla@google.com
diff --git a/tests/tests/os/src/android/os/cts/FileObserverLegacyPathTest.java b/tests/tests/os/src/android/os/cts/FileObserverLegacyPathTest.java
index a0a3e85..e83b54a 100644
--- a/tests/tests/os/src/android/os/cts/FileObserverLegacyPathTest.java
+++ b/tests/tests/os/src/android/os/cts/FileObserverLegacyPathTest.java
@@ -56,7 +56,7 @@
      * MODIFY events on that file, ensuring that, in the case of a FUSE mounted
      * file system, changes applied to the lower file system will be detected
      * by a monitored FUSE folder.
-     * Instead of checking if the set of generated events if exactly the same
+     * Instead of checking if the set of generated events is exactly the same
      * as the set of expected events, the test checks if the set of generated
      * events contains CREATE, OPEN and MODIFY. This because there may be other
      * services (e.g., file indexing) that may access the newly created file,
@@ -84,15 +84,16 @@
         os.write("TEST".getBytes("UTF-8"));
         os.close();
 
-        /* Wait for for the inotify events to be catched. A timeout occurs
-         * after 2 seconds. */
+        /* Wait for for the inotify events to be caught. A timeout occurs after
+         * 2 seconds. */
         mCond.block(2000);
 
         int detectedEvents = fileObserver.getEvents().getOrDefault(imageName, 0);
 
         /* Verify if the received events correspond to the ones that were requested */
-        assertEquals("Uncatched some of the events", PathFileObserver.eventsToSet(eventsMask),
-                PathFileObserver.eventsToSet(detectedEvents & eventsMask));
+        assertEquals("Expected and received inotify events do not match",
+            PathFileObserver.eventsToSet(eventsMask),
+            PathFileObserver.eventsToSet(detectedEvents & eventsMask));
 
         fileObserver.stopWatching();
     }
@@ -127,7 +128,7 @@
                     path, filteredEvent | mGeneratedEventsMap.getOrDefault(path, 0));
 
             /* Release the condition variable only if at least all the matching
-             * events have been catched for every monitored file. */
+             * events have been caught for every monitored file. */
             for (String file : mMonitoredEventsMap.keySet()) {
                 int monitoredEvents = mMonitoredEventsMap.getOrDefault(file, 0);
                 int generatedEvents = mGeneratedEventsMap.getOrDefault(file, 0);
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/PhoneNumberUtilsTest.java b/tests/tests/telephony/current/src/android/telephony/cts/PhoneNumberUtilsTest.java
index 49558d1..38873cf 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/PhoneNumberUtilsTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/PhoneNumberUtilsTest.java
@@ -387,12 +387,65 @@
 
     @Test
     public void testFormatNumberToE164() {
-        assertNull(PhoneNumberUtils.formatNumber("invalid#", "US"));
-        assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
+        assertNull(PhoneNumberUtils.formatNumber("invalid#", "us"));
+        assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "us"));
 
-        assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
-        assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
-        assertEquals("+12023458246", PhoneNumberUtils.formatNumberToE164("(202)345-8246", "US"));
-        assertEquals("+812023458246", PhoneNumberUtils.formatNumberToE164("202-345-8246", "JP"));
+        assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "us"));
+        assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "us"));
+        assertEquals("+12023458246", PhoneNumberUtils.formatNumberToE164("(202)345-8246", "us"));
+        assertEquals("+812023458246", PhoneNumberUtils.formatNumberToE164("202-345-8246", "jp"));
+    }
+
+    @Test
+    public void testAreSamePhoneNumber() {
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("abcd", "bcde", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("1-800-flowers", "800-flowers", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("1-800-flowers", "1-800-abcdefg", "us"));
+
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("999", "999", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("123456789", "923456789", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("123456789", "0123456789", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("650-253-0000", "650 253 0000", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("650-253-0000", "1-650-253-0000", "us"));
+
+        //TODO: Change the expected result to false after libphonenumber improvement
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("650-253-0000", "11-650-253-0000", "us"));
+
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("650-253-0000", "0-650-253-0000", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("555-4141", "+1-700-555-4141", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("+1650-253-0000", "6502530000", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("001650-253-0000", "6502530000", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("0111650-253-0000", "6502530000", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("+19012345678", "+819012345678", "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("008001231234", "8001231234", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("+66811234567", "166811234567", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("080-1234-5678", "+819012345678", "us"));
+
+        //TODO: Change the expected result to false after libphonenumber improvement
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("011 11 7005554141", "+17005554141", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("+44 207 792 3490", "00 207 792 3490",
+                "us"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("16610001234", "6610001234", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("550-450-3605", "+14504503605", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("550-450-3605", "+15404503605", "us"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("550-450-3605", "+15514503605", "us"));
+
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("+31771234567", "0771234567", "jp"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("090-1234-5678", "+819012345678", "jp"));
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("090-1234-5678", "90-1234-5678", "jp"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("090-1234-5678", "080-1234-5678", "jp"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("090-1234-5678", "190-1234-5678", "jp"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("090-1234-5678", "890-1234-5678", "jp"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("080-1234-5678", "+819012345678", "jp"));
+        assertFalse(PhoneNumberUtils.areSamePhoneNumber("290-1234-5678", "+819012345678", "jp"));
+
+        //TODO: Change the expected result to false after libphonenumber improvement
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("+79161234567", "89161234567", "ru"));
+
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("+33123456789", "0123456789", "fr"));
+
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("+31771234567", "0771234567", "nl"));
+
+        assertTrue(PhoneNumberUtils.areSamePhoneNumber("+593(800)123-1234", "8001231234", "ec"));
     }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
index 92f5e44..a4e4f7e 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -23,8 +23,10 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.os.Handler;
@@ -37,6 +39,7 @@
 import android.telephony.CellInfo;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
+import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
@@ -45,6 +48,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.DataEnabledReason;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.util.Log;
@@ -94,6 +98,8 @@
     private boolean mSecurityExceptionThrown;
     private boolean mOnRegistrationFailedCalled;
     private boolean mOnTelephonyDisplayInfoChanged;
+    private boolean mOnPhysicalChannelConfigCalled;
+    private boolean mOnDataEnabledChangedCalled;
     @RadioPowerState private int mRadioPowerState;
     @SimActivationState private int mVoiceActivationState;
     private BarringInfo mBarringInfo;
@@ -166,6 +172,64 @@
         new PhoneStateListener();
     }
 
+    private void registerPhoneStateListenerWithPermission(@NonNull PhoneStateListener listener) {
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+                (tm) -> tm.registerPhoneStateListener(mSimpleExecutor, listener));
+    }
+
+    private void registerPhoneStateListener(@NonNull PhoneStateListener listener) {
+        mTelephonyManager.registerPhoneStateListener(mSimpleExecutor, listener);
+    }
+
+    private void unRegisterPhoneStateListener(boolean condition,
+            @NonNull PhoneStateListener listener) throws Exception {
+        synchronized (mLock) {
+            condition = false;
+            mTelephonyManager.unregisterPhoneStateListener(listener);
+            mLock.wait(WAIT_TIME);
+
+            assertFalse(condition);
+        }
+    }
+
+    private ServiceStateChangedListener mServiceStateChangedListener;
+
+    private class ServiceStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.ServiceStateChangedListener {
+        @Override
+        public void onServiceStateChanged(ServiceState serviceState) {
+            synchronized (mLock) {
+                mOnServiceStateChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnServiceStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        assertFalse(mOnServiceStateChangedCalled);
+
+        mHandler.post(() -> {
+            mServiceStateChangedListener = new ServiceStateChangedListener();
+            registerPhoneStateListener(mServiceStateChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnServiceStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnServiceStateChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnServiceStateChangedCalled, mServiceStateChangedListener);
+    }
+
     @Test
     public void testOnServiceStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -197,6 +261,55 @@
     }
 
     @Test
+    public void testOnUnRegisterFollowedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        assertFalse(mOnServiceStateChangedCalled);
+
+        mHandler.post(() -> {
+            mServiceStateChangedListener = new ServiceStateChangedListener();
+            registerPhoneStateListener(mServiceStateChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnServiceStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnServiceStateChangedCalled);
+
+        // reset and un-register
+        mOnServiceStateChangedCalled = false;
+        if (mServiceStateChangedListener != null) {
+            // un-register the listener
+            mTelephonyManager.unregisterPhoneStateListener(mServiceStateChangedListener);
+        }
+        synchronized (mLock) {
+            if (!mOnServiceStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        assertFalse(mOnServiceStateChangedCalled);
+
+        // re-register the listener
+        registerPhoneStateListener(mServiceStateChangedListener);
+        synchronized (mLock) {
+            if (!mOnServiceStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnServiceStateChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnServiceStateChangedCalled, mServiceStateChangedListener);
+    }
+
+
+    @Test
     public void testOnUnRegisterFollowedByRegister() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
             Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
@@ -374,6 +487,57 @@
     }
     */
 
+    private SignalStrengthsChangedListener mSignalStrengthsChangedListener;
+
+    private class SignalStrengthsChangedListener extends PhoneStateListener
+            implements PhoneStateListener.SignalStrengthsChangedListener {
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            synchronized (mLock) {
+                mSignalStrength = signalStrength;
+                mLock.notify();
+            }
+        }
+    }
+
+    private void getSignalStrength() {
+        mSignalStrength.getCdmaDbm();
+        mSignalStrength.getCdmaEcio();
+        mSignalStrength.getEvdoDbm();
+        mSignalStrength.getEvdoEcio();
+        mSignalStrength.getEvdoSnr();
+        mSignalStrength.getGsmBitErrorRate();
+        mSignalStrength.getGsmSignalStrength();
+        mSignalStrength.isGsm();
+        mSignalStrength.getLevel();
+    }
+
+    @Test
+    public void testOnSignalStrengthsChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertTrue(mSignalStrength == null);
+
+        mHandler.post(() -> {
+            mSignalStrengthsChangedListener = new SignalStrengthsChangedListener();
+            registerPhoneStateListener(mSignalStrengthsChangedListener);
+        });
+        synchronized (mLock) {
+            if (mSignalStrength == null) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mSignalStrength != null);
+        // Call SignalStrength methods to make sure they do not throw any exceptions
+        getSignalStrength();
+
+        // Test unregister
+        unRegisterPhoneStateListener(mSignalStrength == null, mSignalStrengthsChangedListener);
+    }
+
     @Test
     public void testOnSignalStrengthsChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -402,15 +566,46 @@
 
         assertTrue(mSignalStrength != null);
         // Call SignalStrength methods to make sure they do not throw any exceptions
-        mSignalStrength.getCdmaDbm();
-        mSignalStrength.getCdmaEcio();
-        mSignalStrength.getEvdoDbm();
-        mSignalStrength.getEvdoEcio();
-        mSignalStrength.getEvdoSnr();
-        mSignalStrength.getGsmBitErrorRate();
-        mSignalStrength.getGsmSignalStrength();
-        mSignalStrength.isGsm();
-        mSignalStrength.getLevel();
+        getSignalStrength();
+    }
+
+    private MessageWaitingIndicatorChangedListener mMessageWaitingIndicatorChangedListener;
+
+    private class MessageWaitingIndicatorChangedListener extends PhoneStateListener
+            implements PhoneStateListener.MessageWaitingIndicatorChangedListener {
+        @Override
+        public void onMessageWaitingIndicatorChanged(boolean mwi) {
+            synchronized (mLock) {
+                mOnMessageWaitingIndicatorChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnMessageWaitingIndicatorChangedByRegisterPhoneStateListener()
+            throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnMessageWaitingIndicatorChangedCalled);
+
+        mHandler.post(() -> {
+            mMessageWaitingIndicatorChangedListener = new MessageWaitingIndicatorChangedListener();
+            registerPhoneStateListener(mMessageWaitingIndicatorChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnMessageWaitingIndicatorChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnMessageWaitingIndicatorChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnMessageWaitingIndicatorChangedCalled,
+                mMessageWaitingIndicatorChangedListener);
     }
 
     @Test
@@ -443,6 +638,50 @@
         assertTrue(mOnMessageWaitingIndicatorChangedCalled);
     }
 
+    private PreciseCallStateChangedListener mPreciseCallStateChangedListener;
+
+    private class PreciseCallStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.PreciseCallStateChangedListener {
+        @Override
+        public void onPreciseCallStateChanged(PreciseCallState preciseCallState) {
+            synchronized (mLock) {
+                mOnPreciseCallStateChangedCalled = true;
+                mPreciseCallState = preciseCallState;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnPreciseCallStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mOnPreciseCallStateChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mPreciseCallStateChangedListener = new PreciseCallStateChangedListener();
+            registerPhoneStateListenerWithPermission(mPreciseCallStateChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnPreciseCallStateChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        Log.d(TAG, "testOnPreciseCallStateChangedByRegisterPhoneStateListener: "
+                + mOnPreciseCallStateChangedCalled);
+
+        assertThat(mOnPreciseCallStateChangedCalled).isTrue();
+        assertThat(mPreciseCallState.getForegroundCallState()).isIn(PRECISE_CALL_STATE);
+        assertThat(mPreciseCallState.getBackgroundCallState()).isIn(PRECISE_CALL_STATE);
+        assertThat(mPreciseCallState.getRingingCallState()).isIn(PRECISE_CALL_STATE);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnPreciseCallStateChangedCalled,
+                mPreciseCallStateChangedListener);
+    }
+
     @Test
     public void testOnPreciseCallStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -478,6 +717,46 @@
         assertThat(mPreciseCallState.getRingingCallState()).isIn(PRECISE_CALL_STATE);
     }
 
+    private CallDisconnectCauseChangedListener mCallDisconnectCauseChangedListener;
+
+    private class CallDisconnectCauseChangedListener extends PhoneStateListener
+            implements PhoneStateListener.CallDisconnectCauseChangedListener {
+        @Override
+        public void onCallDisconnectCauseChanged(int disconnectCause,
+                                                 int preciseDisconnectCause) {
+            synchronized (mLock) {
+                mOnCallDisconnectCauseChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnCallDisconnectCauseChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mCallDisconnectCauseChangedListener = new CallDisconnectCauseChangedListener();
+            registerPhoneStateListenerWithPermission(mCallDisconnectCauseChangedListener);
+
+        });
+        synchronized (mLock) {
+            if (!mOnCallDisconnectCauseChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertThat(mOnCallDisconnectCauseChangedCalled).isTrue();
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnCallDisconnectCauseChangedCalled,
+                mCallDisconnectCauseChangedListener);
+    }
+
     @Test
     public void testOnCallDisconnectCauseChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -510,6 +789,45 @@
         assertThat(mOnCallDisconnectCauseChangedCalled).isTrue();
     }
 
+    private ImsCallDisconnectCauseChangedListener mImsCallDisconnectCauseChangedListener;
+
+    private class ImsCallDisconnectCauseChangedListener extends PhoneStateListener
+            implements PhoneStateListener.ImsCallDisconnectCauseChangedListener {
+        @Override
+        public void onImsCallDisconnectCauseChanged(ImsReasonInfo imsReason) {
+            synchronized (mLock) {
+                mOnImsCallDisconnectCauseChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnImsCallDisconnectCauseChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mOnImsCallDisconnectCauseChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mImsCallDisconnectCauseChangedListener = new ImsCallDisconnectCauseChangedListener();
+            registerPhoneStateListenerWithPermission(mImsCallDisconnectCauseChangedListener);
+
+        });
+        synchronized (mLock) {
+            if (!mOnImsCallDisconnectCauseChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertThat(mOnImsCallDisconnectCauseChangedCalled).isTrue();
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnImsCallDisconnectCauseChangedCalled,
+                mImsCallDisconnectCauseChangedListener);
+    }
+
     @Test
     public void testOnImsCallDisconnectCauseChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -541,6 +859,45 @@
         assertThat(mOnImsCallDisconnectCauseChangedCalled).isTrue();
     }
 
+    private SrvccStateChangedListener mSrvccStateChangedListener;
+
+    private class SrvccStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.SrvccStateChangedListener {
+        @Override
+        public void onSrvccStateChanged(int state) {
+            synchronized (mLock) {
+                mSrvccStateChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOSrvccStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mSrvccStateChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mSrvccStateChangedListener = new SrvccStateChangedListener();
+            registerPhoneStateListenerWithPermission(mSrvccStateChangedListener);
+
+        });
+        synchronized (mLock) {
+            if (!mSrvccStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        Log.d(TAG, "testOSrvccStateChangedByRegisterPhoneStateListener");
+
+        assertThat(mSrvccStateChangedCalled).isTrue();
+
+        // Test unregister
+        unRegisterPhoneStateListener(mSrvccStateChangedCalled, mSrvccStateChangedListener);
+    }
+
     @Test
     public void testOnPhoneStateListenerExecutorWithSrvccChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -573,6 +930,47 @@
         assertThat(mSrvccStateChangedCalled).isTrue();
     }
 
+    private RadioPowerStateChangedListener mRadioPowerStateChangedListener;
+
+    private class RadioPowerStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.RadioPowerStateChangedListener {
+        @Override
+        public void onRadioPowerStateChanged(int state) {
+            synchronized (mLock) {
+                mRadioPowerState = state;
+                mOnRadioPowerStateChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnRadioPowerStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mOnRadioPowerStateChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mRadioPowerStateChangedListener = new RadioPowerStateChangedListener();
+            registerPhoneStateListenerWithPermission(mRadioPowerStateChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnRadioPowerStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        Log.d(TAG, "testOnRadioPowerStateChangedByRegisterPhoneStateListener: "
+                + mRadioPowerState);
+
+        assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(mRadioPowerState);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnRadioPowerStateChangedCalled,
+                mRadioPowerStateChangedListener);
+    }
+
     @Test
     public void testOnRadioPowerStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -606,6 +1004,50 @@
         assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(mRadioPowerState);
     }
 
+    private VoiceActivationStateChangedListener mVoiceActivationStateChangedListener;
+
+    private class VoiceActivationStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.VoiceActivationStateChangedListener {
+        @Override
+        public void onVoiceActivationStateChanged(int state) {
+            synchronized (mLock) {
+                mVoiceActivationState = state;
+                mVoiceActivationStateChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnVoiceActivationStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mVoiceActivationStateChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mVoiceActivationStateChangedListener = new VoiceActivationStateChangedListener();
+            registerPhoneStateListenerWithPermission(mVoiceActivationStateChangedListener);
+
+        });
+        synchronized (mLock) {
+            if (!mVoiceActivationStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        Log.d(TAG, "testOnVoiceActivationStateChangedByRegisterPhoneStateListener: "
+                + mVoiceActivationState);
+        int state = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
+                (tm) -> tm.getVoiceActivationState());
+
+        assertEquals(state, mVoiceActivationState);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mVoiceActivationStateChangedCalled,
+                mVoiceActivationStateChangedListener);
+    }
+
     @Test
     public void testOnVoiceActivationStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -641,6 +1083,73 @@
         assertEquals(state, mVoiceActivationState);
     }
 
+    private PreciseDataConnectionStateChangedListener mPreciseDataConnectionStateChangedListener;
+
+    private class PreciseDataConnectionStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.PreciseDataConnectionStateChangedListener {
+        @Override
+        public void onPreciseDataConnectionStateChanged(
+                PreciseDataConnectionState state) {
+            synchronized (mLock) {
+                mOnPreciseDataConnectionStateChanged = true;
+                mPreciseDataConnectionState = state;
+                mLock.notify();
+            }
+        }
+    }
+
+    private void getPreciseDataConnectionState() {
+        // Ensure that no exceptions are thrown
+        mPreciseDataConnectionState.getNetworkType();
+        mPreciseDataConnectionState.getLinkProperties();
+        mPreciseDataConnectionState.getLastCauseCode();
+        mPreciseDataConnectionState.getLinkProperties();
+        mPreciseDataConnectionState.getApnSetting();
+        mPreciseDataConnectionState.getTransportType();
+        mPreciseDataConnectionState.getId();
+
+        // Deprecated in R
+        assertEquals(mPreciseDataConnectionState.getDataConnectionState(),
+                mPreciseDataConnectionState.getState());
+        assertEquals(mPreciseDataConnectionState.getDataConnectionFailCause(),
+                mPreciseDataConnectionState.getLastCauseCode());
+
+        // Superseded in R by getApnSetting()
+        mPreciseDataConnectionState.getDataConnectionApnTypeBitMask();
+        mPreciseDataConnectionState.getDataConnectionApn();
+    }
+
+    @Test
+    public void testOnPreciseDataConnectionStateChangedByRegisterPhoneStateListener()
+            throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
+
+        mHandler.post(() -> {
+            mPreciseDataConnectionStateChangedListener =
+                    new PreciseDataConnectionStateChangedListener();
+            registerPhoneStateListenerWithPermission(mPreciseDataConnectionStateChangedListener);
+
+        });
+        synchronized (mLock) {
+            if (!mOnPreciseDataConnectionStateChanged){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertThat(mOnPreciseDataConnectionStateChanged).isTrue();
+        assertThat(mPreciseDataConnectionState.getState())
+                .isIn(DATA_CONNECTION_STATE);
+
+        getPreciseDataConnectionState();
+        // Test unregister
+        unRegisterPhoneStateListener(mOnPreciseDataConnectionStateChanged,
+                mPreciseDataConnectionStateChangedListener);
+    }
+
     @Test
     public void testOnPreciseDataConnectionStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -675,24 +1184,44 @@
         assertThat(mPreciseDataConnectionState.getState())
                 .isIn(DATA_CONNECTION_STATE);
 
-        // Ensure that no exceptions are thrown
-        mPreciseDataConnectionState.getNetworkType();
-        mPreciseDataConnectionState.getLinkProperties();
-        mPreciseDataConnectionState.getLastCauseCode();
-        mPreciseDataConnectionState.getLinkProperties();
-        mPreciseDataConnectionState.getApnSetting();
-        mPreciseDataConnectionState.getTransportType();
-        mPreciseDataConnectionState.getId();
+        getPreciseDataConnectionState();
+    }
 
-        // Deprecated in R
-        assertEquals(mPreciseDataConnectionState.getDataConnectionState(),
-                mPreciseDataConnectionState.getState());
-        assertEquals(mPreciseDataConnectionState.getDataConnectionFailCause(),
-                mPreciseDataConnectionState.getLastCauseCode());
+    private DisplayInfoChangedListener mDisplayInfoChangedListener;
 
-        // Superseded in R by getApnSetting()
-        mPreciseDataConnectionState.getDataConnectionApnTypeBitMask();
-        mPreciseDataConnectionState.getDataConnectionApn();
+    private class DisplayInfoChangedListener extends PhoneStateListener
+            implements PhoneStateListener.DisplayInfoChangedListener {
+        @Override
+        public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
+            synchronized (mLock) {
+                mOnTelephonyDisplayInfoChanged = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnDisplayInfoChangedByRegisterPhoneStateListener() throws Exception {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertThat(mOnTelephonyDisplayInfoChanged).isFalse();
+
+        mHandler.post(() -> {
+            mDisplayInfoChangedListener = new DisplayInfoChangedListener();
+            registerPhoneStateListener(mDisplayInfoChangedListener);
+        });
+
+        synchronized (mLock) {
+            if (!mOnTelephonyDisplayInfoChanged) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        assertTrue(mOnTelephonyDisplayInfoChanged);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnTelephonyDisplayInfoChanged, mDisplayInfoChangedListener);
     }
 
     @Test
@@ -726,6 +1255,47 @@
         assertTrue(mOnTelephonyDisplayInfoChanged);
     }
 
+    private CallForwardingIndicatorChangedListener mCallForwardingIndicatorChangedListener;
+
+    private class CallForwardingIndicatorChangedListener extends PhoneStateListener
+            implements PhoneStateListener.CallForwardingIndicatorChangedListener {
+        @Override
+        public void onCallForwardingIndicatorChanged(boolean cfi) {
+            synchronized (mLock) {
+                mOnCallForwardingIndicatorChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnCallForwardingIndicatorChangedByRegisterPhoneStateListener()
+            throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnCallForwardingIndicatorChangedCalled);
+
+        mHandler.post(() -> {
+            mCallForwardingIndicatorChangedListener =
+                    new CallForwardingIndicatorChangedListener();
+            registerPhoneStateListener(mCallForwardingIndicatorChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnCallForwardingIndicatorChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnCallForwardingIndicatorChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnCallForwardingIndicatorChangedCalled,
+                mCallForwardingIndicatorChangedListener);
+    }
+
+
     @Test
     public void testOnCallForwardingIndicatorChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -756,6 +1326,44 @@
         assertTrue(mOnCallForwardingIndicatorChangedCalled);
     }
 
+    private CellLocationChangedListener mCellLocationChangedListener;
+
+    private class CellLocationChangedListener extends PhoneStateListener
+            implements PhoneStateListener.CellLocationChangedListener {
+        @Override
+        public void onCellLocationChanged(CellLocation location) {
+            synchronized (mLock) {
+                mOnCellLocationChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnCellLocationChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnCellLocationChangedCalled);
+
+        TelephonyManagerTest.grantLocationPermissions();
+        mHandler.post(() -> {
+            mCellLocationChangedListener = new CellLocationChangedListener();
+            registerPhoneStateListener(mCellLocationChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnCellLocationChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnCellLocationChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnCellLocationChangedCalled, mCellLocationChangedListener);
+    }
+
     @Test
     public void testOnCellLocationChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -786,6 +1394,43 @@
         assertTrue(mOnCellLocationChangedCalled);
     }
 
+    private CallStateChangedListener mCallStateChangedListener;
+
+    private class CallStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.CallStateChangedListener {
+        @Override
+        public void onCallStateChanged(int state, String incomingNumber) {
+            synchronized (mLock) {
+                mOnCallStateChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnCallStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnCallStateChangedCalled);
+
+        mHandler.post(() -> {
+            mCallStateChangedListener = new CallStateChangedListener();
+            registerPhoneStateListener(mCallStateChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnCallStateChangedCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnCallStateChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnCallStateChangedCalled, mCallStateChangedListener);
+    }
+
     @Test
     public void testOnCallStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -815,6 +1460,53 @@
         assertTrue(mOnCallStateChangedCalled);
     }
 
+
+    private DataConnectionStateChangedListener mDataConnectionStateChangedListener;
+
+    private class DataConnectionStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.DataConnectionStateChangedListener {
+        @Override
+        public void onDataConnectionStateChanged(int state, int networkType) {
+            synchronized (mLock) {
+                mOnDataConnectionStateChangedCalled = true;
+                mOnDataConnectionStateChangedWithNetworkTypeCalled = true;
+                if (mOnDataConnectionStateChangedCalled
+                        && mOnDataConnectionStateChangedWithNetworkTypeCalled) {
+                    mLock.notify();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testOnDataConnectionStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnDataConnectionStateChangedCalled);
+        assertFalse(mOnDataConnectionStateChangedWithNetworkTypeCalled);
+
+        mHandler.post(() -> {
+            mDataConnectionStateChangedListener = new DataConnectionStateChangedListener();
+            registerPhoneStateListener(mDataConnectionStateChangedListener);
+
+        });
+        synchronized (mLock) {
+            if (!mOnDataConnectionStateChangedCalled ||
+                    !mOnDataConnectionStateChangedWithNetworkTypeCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnDataConnectionStateChangedCalled);
+        assertTrue(mOnDataConnectionStateChangedWithNetworkTypeCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnDataConnectionStateChangedCalled,
+                mDataConnectionStateChangedListener);
+    }
+
     @Test
     public void testOnDataConnectionStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -861,6 +1553,45 @@
         assertTrue(mOnDataConnectionStateChangedWithNetworkTypeCalled);
     }
 
+
+    private DataActivityListener mDataActivityListener;
+
+    private class DataActivityListener extends PhoneStateListener
+            implements PhoneStateListener.DataActivityListener {
+        @Override
+        public void onDataActivity(int direction) {
+            synchronized (mLock) {
+                mOnDataActivityCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnDataActivityByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnDataActivityCalled);
+
+        mHandler.post(() -> {
+            mDataActivityListener =  new DataActivityListener();
+            registerPhoneStateListener(mDataActivityListener);
+
+        });
+        synchronized (mLock) {
+            if (!mOnDataActivityCalled){
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnDataActivityCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnDataActivityCalled, mDataActivityListener);
+    }
+
     @Test
     public void testOnDataActivity() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -890,6 +1621,44 @@
         assertTrue(mOnDataActivityCalled);
     }
 
+    private CellInfoChangedListener mCellInfoChangedListener;
+
+    private class CellInfoChangedListener extends PhoneStateListener
+            implements PhoneStateListener.CellInfoChangedListener {
+        @Override
+        public void onCellInfoChanged(List<CellInfo> cellInfo) {
+            synchronized (mLock) {
+                mOnCellInfoChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnCellInfoChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnDataActivityCalled);
+
+        TelephonyManagerTest.grantLocationPermissions();
+        mHandler.post(() -> {
+            mCellInfoChangedListener = new CellInfoChangedListener();
+            registerPhoneStateListener(mCellInfoChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnCellInfoChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnCellInfoChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnCellInfoChangedCalled, mCellInfoChangedListener);
+    }
+
     @Test
     public void testOnCellInfoChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -920,6 +1689,45 @@
         assertTrue(mOnCellInfoChangedCalled);
     }
 
+
+    private UserMobileDataStateChangedListener mUserMobileDataStateChangedListener;
+
+    private class UserMobileDataStateChangedListener extends PhoneStateListener
+            implements PhoneStateListener.UserMobileDataStateChangedListener {
+        @Override
+        public void onUserMobileDataStateChanged(boolean state) {
+            synchronized (mLock) {
+                mOnUserMobileDataStateChanged = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnUserMobileDataStateChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnUserMobileDataStateChanged);
+
+        mHandler.post(() -> {
+            mUserMobileDataStateChangedListener = new UserMobileDataStateChangedListener();
+            registerPhoneStateListener(mUserMobileDataStateChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnUserMobileDataStateChanged) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnUserMobileDataStateChanged);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnUserMobileDataStateChanged,
+                mUserMobileDataStateChangedListener);
+    }
+
     @Test
     public void testOnUserMobileDataStateChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -950,6 +1758,63 @@
         assertTrue(mOnUserMobileDataStateChanged);
     }
 
+    private OutgoingEmergencySmsListener mOutgoingEmergencySmsListener;
+
+    private class OutgoingEmergencySmsListener extends PhoneStateListener
+            implements PhoneStateListener.OutgoingEmergencySmsListener {
+        @Override
+        public void onOutgoingEmergencySms(EmergencyNumber emergencyNumber) {
+            synchronized (mLock) {
+                Log.i(TAG, "onOutgoingEmergencySms: emergencyNumber=" + emergencyNumber);
+                mOnOutgoingSmsEmergencyNumberChanged = emergencyNumber;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnOutgoingSmsEmergencyNumberChangedByRegisterPhoneStateListener()
+            throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        TelephonyUtils.addTestEmergencyNumber(
+                InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
+
+        assertNull(mOnOutgoingSmsEmergencyNumberChanged);
+
+        mHandler.post(() -> {
+            mOutgoingEmergencySmsListener = new OutgoingEmergencySmsListener();
+            registerPhoneStateListenerWithPermission(mOutgoingEmergencySmsListener);
+            SmsManager.getDefault().sendTextMessage(
+                    TEST_EMERGENCY_NUMBER, null,
+                    "testOutgoingSmsListenerCtsByRegisterPhoneStateListener",
+                    null, null);
+        });
+
+        try {
+            synchronized (mLock) {
+                if (mOnOutgoingSmsEmergencyNumberChanged == null) {
+                    mLock.wait(WAIT_TIME);
+                }
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Operation interrupted.");
+        } finally {
+            TelephonyUtils.removeTestEmergencyNumber(
+                    InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
+        }
+
+        assertNotNull(mOnOutgoingSmsEmergencyNumberChanged);
+        assertEquals(mOnOutgoingSmsEmergencyNumberChanged.getNumber(), TEST_EMERGENCY_NUMBER);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnOutgoingSmsEmergencyNumberChanged == null,
+                mOutgoingEmergencySmsListener);
+    }
+
     @Test
     public void testOnOutgoingSmsEmergencyNumberChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -960,17 +1825,16 @@
         TelephonyUtils.addTestEmergencyNumber(
                 InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
 
-        LinkedBlockingQueue<Pair<EmergencyNumber, Integer>> smsCallbackQueue =
-                new LinkedBlockingQueue<>(1);
+        assertNull(mOnOutgoingSmsEmergencyNumberChanged);
 
         mHandler.post(() -> {
             mListener = new PhoneStateListener() {
                 @Override
-                public void onOutgoingEmergencySms(EmergencyNumber emergencyNumber,
-                        int subscriptionId) {
+                public void onOutgoingEmergencySms(EmergencyNumber emergencyNumber) {
                     synchronized (mLock) {
                         Log.i(TAG, "onOutgoingEmergencySms: emergencyNumber=" + emergencyNumber);
-                        smsCallbackQueue.offer(Pair.create(emergencyNumber, subscriptionId));
+                        mOnOutgoingSmsEmergencyNumberChanged = emergencyNumber;
+                        mLock.notify();
                     }
                 }
             };
@@ -982,12 +1846,11 @@
         });
 
         try {
-            Pair<EmergencyNumber, Integer> emergencySmsInfo =
-                    smsCallbackQueue.poll(WAIT_TIME, TimeUnit.MILLISECONDS);
-            assertNotNull("Never got emergency sms callback", emergencySmsInfo);
-            assertEquals(TEST_EMERGENCY_NUMBER, emergencySmsInfo.first.getNumber());
-            assertEquals(SubscriptionManager.getDefaultSmsSubscriptionId(),
-                    emergencySmsInfo.second.intValue());
+            synchronized (mLock) {
+                if (mOnOutgoingSmsEmergencyNumberChanged == null) {
+                    mLock.wait(WAIT_TIME);
+                }
+            }
         } catch (InterruptedException e) {
             Log.e(TAG, "Operation interrupted.");
         } finally {
@@ -995,6 +1858,48 @@
                     InstrumentationRegistry.getInstrumentation(), TEST_EMERGENCY_NUMBER);
         }
 
+        assertNotNull(mOnOutgoingSmsEmergencyNumberChanged);
+        assertEquals(mOnOutgoingSmsEmergencyNumberChanged.getNumber(), TEST_EMERGENCY_NUMBER);
+    }
+
+    private ActiveDataSubscriptionIdChangedListener mActiveDataSubscriptionIdChangedListener;
+
+    private class ActiveDataSubscriptionIdChangedListener extends PhoneStateListener
+            implements PhoneStateListener.ActiveDataSubscriptionIdChangedListener {
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            synchronized (mLock) {
+                mOnActiveDataSubscriptionIdChanged = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnActiveDataSubscriptionIdChangedByRegisterPhoneStateListener()
+            throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        assertFalse(mOnActiveDataSubscriptionIdChanged);
+
+        mHandler.post(() -> {
+            mActiveDataSubscriptionIdChangedListener =
+                    new ActiveDataSubscriptionIdChangedListener();
+            registerPhoneStateListener(mActiveDataSubscriptionIdChangedListener);
+        });
+        synchronized (mLock) {
+            if (!mOnActiveDataSubscriptionIdChanged) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        assertTrue(mOnActiveDataSubscriptionIdChanged);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnActiveDataSubscriptionIdChanged,
+                mActiveDataSubscriptionIdChangedListener);
     }
 
     @Test
@@ -1027,6 +1932,46 @@
         assertTrue(mOnActiveDataSubscriptionIdChanged);
     }
 
+    private BarringInfoChangedListener mBarringInfoChangedListener;
+
+    private class BarringInfoChangedListener extends PhoneStateListener
+            implements PhoneStateListener.BarringInfoChangedListener {
+        @Override
+        public void onBarringInfoChanged(BarringInfo barringInfo) {
+            synchronized (mLock) {
+                mOnBarringInfoChangedCalled = true;
+                mBarringInfo = barringInfo;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnBarringInfoChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        assertFalse(mOnBarringInfoChangedCalled);
+        mHandler.post(() -> {
+            mBarringInfoChangedListener = new BarringInfoChangedListener();
+            registerPhoneStateListenerWithPermission(mBarringInfoChangedListener);
+        });
+
+        synchronized (mLock) {
+            if (!mOnBarringInfoChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        assertTrue(mOnBarringInfoChangedCalled);
+
+        assertBarringInfoSane(mBarringInfo);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnBarringInfoChangedCalled, mBarringInfoChangedListener);
+    }
+
     @Test
     public void testOnBarringInfoChanged() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -1129,6 +2074,53 @@
         assertNotEquals(hasBarringTypeUnknown, hasBarringTypeKnown);
     }
 
+    private RegistrationFailedListener mRegistrationFailedListener;
+
+    private class RegistrationFailedListener extends PhoneStateListener
+            implements PhoneStateListener.RegistrationFailedListener {
+        @Override
+        public void onRegistrationFailed(CellIdentity cid, String chosenPlmn,
+                                         int domain, int causeCode, int additionalCauseCode) {
+            synchronized (mLock) {
+                mOnRegistrationFailedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnRegistrationFailedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        assertFalse(mOnBarringInfoChangedCalled);
+        mHandler.post(() -> {
+            mRegistrationFailedListener = new RegistrationFailedListener();
+            registerPhoneStateListenerWithPermission(mRegistrationFailedListener);
+
+        });
+
+        synchronized (mLock) {
+            if (!mOnBarringInfoChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+
+        // Assert that in the WAIT_TIME interval, the listener wasn't invoked. While this is
+        // **technically** a flaky test, in practice this flake should happen approximately never
+        // as it would mean that a registered phone is failing to reselect during CTS at this
+        // exact moment.
+        //
+        // What the test is verifying is that there is no "auto" callback for registration
+        // failure because unlike other PSL registrants, this one is not called upon registration.
+        assertFalse(mOnRegistrationFailedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnRegistrationFailedCalled, mRegistrationFailedListener);
+    }
+
     @Test
     public void testOnRegistrationFailed() throws Throwable {
         if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -1168,4 +2160,83 @@
         // failure because unlike other PSL registrants, this one is not called upon registration.
         assertFalse(mOnRegistrationFailedCalled);
     }
+
+    private PhysicalChannelConfigChangedListener mPhysicalChannelConfigChangedListener;
+
+    private class PhysicalChannelConfigChangedListener extends PhoneStateListener
+            implements PhoneStateListener.PhysicalChannelConfigChangedListener {
+        @Override
+        public void onPhysicalChannelConfigChanged(
+                @NonNull List<PhysicalChannelConfig> configs) {
+            synchronized (mLock) {
+                mOnPhysicalChannelConfigCalled = true;
+                Log.d(TAG, "MockPhoneStateListener PhysicalChannelConfig");
+                Log.d(TAG, "MockPhoneStateListener configs = " + configs);
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnPhysicalChannelConfigChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        assertFalse(mOnPhysicalChannelConfigCalled);
+        mHandler.post(() -> {
+            mPhysicalChannelConfigChangedListener =
+                    new PhysicalChannelConfigChangedListener();
+            registerPhoneStateListenerWithPermission(mPhysicalChannelConfigChangedListener);
+        });
+
+        synchronized (mLock) {
+            while (!mOnPhysicalChannelConfigCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        assertTrue(mOnPhysicalChannelConfigCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnPhysicalChannelConfigCalled,
+                mPhysicalChannelConfigChangedListener);
+    }
+
+    private DataEnabledChangedListener mDataEnabledChangedListener;
+
+    private class DataEnabledChangedListener extends PhoneStateListener
+            implements PhoneStateListener.DataEnabledChangedListener {
+        @Override
+        public void onDataEnabledChanged(boolean enabled, @DataEnabledReason int reason) {
+            synchronized (mLock) {
+                mOnDataEnabledChangedCalled = true;
+                mLock.notify();
+            }
+        }
+    }
+
+    @Test
+    public void testOnDataEnabledChangedByRegisterPhoneStateListener() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        assertFalse(mOnDataEnabledChangedCalled);
+        mHandler.post(() -> {
+            mDataEnabledChangedListener = new DataEnabledChangedListener();
+            registerPhoneStateListenerWithPermission(mDataEnabledChangedListener);
+        });
+
+        synchronized (mLock) {
+            while (!mOnDataEnabledChangedCalled) {
+                mLock.wait(WAIT_TIME);
+            }
+        }
+        assertTrue(mOnDataEnabledChangedCalled);
+
+        // Test unregister
+        unRegisterPhoneStateListener(mOnDataEnabledChangedCalled, mDataEnabledChangedListener);
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SignalThresholdInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SignalThresholdInfoTest.java
new file mode 100644
index 0000000..e60ff53
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SignalThresholdInfoTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2021 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.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.pm.PackageManager;
+import android.os.Parcel;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.SignalThresholdInfo;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Test SignalThresholdInfo to make sure the object can only constructed with only valid data.
+ */
+public class SignalThresholdInfoTest {
+    private static final String TAG = "SignalThresholdInfo";
+
+    // A sample of valid (RAN, SignalMeasurementType, threshold value) arrays. Threshold value will
+    // used to construct thresholds array during test.
+    private static final int[][] VALID_PARAMS = {
+            {AccessNetworkConstants.AccessNetworkType.GERAN,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI, -100},
+            {AccessNetworkConstants.AccessNetworkType.CDMA2000,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI,
+                    -100},
+            {AccessNetworkConstants.AccessNetworkType.UTRAN,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP, -100},
+            {AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP,
+                    -100},
+            {AccessNetworkConstants.AccessNetworkType.NGRAN,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP,
+                    -100},
+    };
+
+    // Map of SignalMeasurementType to invalid thresholds edge values.
+    // Each invalid value will be constructed with a thresholds array to test separately.
+    private static final Map<Integer, List<Integer>> INVALID_THRESHOLDS_MAP = Map.of(
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI,
+            List.of(SignalThresholdInfo.SIGNAL_RSSI_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_RSSI_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP,
+            List.of(SignalThresholdInfo.SIGNAL_RSCP_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_RSCP_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP,
+            List.of(SignalThresholdInfo.SIGNAL_RSRP_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_RSRP_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ,
+            List.of(SignalThresholdInfo.SIGNAL_RSRQ_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_RSRQ_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR,
+            List.of(SignalThresholdInfo.SIGNAL_RSSNR_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_RSSNR_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP,
+            List.of(SignalThresholdInfo.SIGNAL_SSRSRP_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_SSRSRP_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ,
+            List.of(SignalThresholdInfo.SIGNAL_SSRSRQ_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_SSRSRQ_MAX_VALUE + 1),
+            SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR,
+            List.of(SignalThresholdInfo.SIGNAL_SSSINR_MIN_VALUE - 1,
+                    SignalThresholdInfo.SIGNAL_SSSINR_MAX_VALUE + 1)
+    );
+
+    // Map of RAN to allowed SignalMeasurementType set.
+    // RAN/TYPE pair will be used to verify the validation of the combo
+    private static final Map<Integer, Set<Integer>> VALID_RAN_TO_MEASUREMENT_TYPE_MAP = Map.of(
+            AccessNetworkConstants.AccessNetworkType.GERAN,
+            Set.of(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI),
+            AccessNetworkConstants.AccessNetworkType.CDMA2000,
+            Set.of(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI),
+            AccessNetworkConstants.AccessNetworkType.UTRAN,
+            Set.of(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP),
+            AccessNetworkConstants.AccessNetworkType.EUTRAN,
+            Set.of(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR),
+            AccessNetworkConstants.AccessNetworkType.NGRAN,
+            Set.of(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ,
+                    SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR)
+    );
+
+    @Before
+    public void setUp() throws Exception {
+        assumeTrue(InstrumentationRegistry.getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+    }
+
+    @Test
+    public void testConstructor_validParams() {
+        for (int[] params : VALID_PARAMS) {
+            final int ran = params[0];
+            final int signalMeasurementType = params[1];
+            final int[] thresholds = new int[]{params[2]};
+
+            SignalThresholdInfo sti = new SignalThresholdInfo.Builder()
+                    .setRadioAccessNetworkType(ran)
+                    .setSignalMeasurementType(signalMeasurementType)
+                    .setThresholds(thresholds)
+                    .build();
+
+            assertEquals(ran, sti.getRadioAccessNetworkType());
+            assertEquals(signalMeasurementType, sti.getSignalMeasurementType());
+            assertThat(thresholds).isEqualTo(sti.getThresholds());
+        }
+    }
+
+    @Test
+    public void testConstructor_invalidSignalMeasurementType() {
+        final int[] invalidSignalMeasurementTypes = new int[]{-1, 0, 9};
+        for (int signalMeasurementType : invalidSignalMeasurementTypes) {
+            buildWithInvalidParameterThrowException(
+                    AccessNetworkConstants.AccessNetworkType.GERAN, signalMeasurementType,
+                    new int[]{-1});
+        }
+    }
+
+    @Test
+    public void testConstructor_nullThresholds() {
+        buildWithInvalidParameterThrowException(
+                AccessNetworkConstants.AccessNetworkType.GERAN,
+                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI, null);
+    }
+
+    @Test
+    public void testConstructor_invalidRanMeasurementTypeCombo() {
+        for (int ran : VALID_RAN_TO_MEASUREMENT_TYPE_MAP.keySet()) {
+            Set validTypes = VALID_RAN_TO_MEASUREMENT_TYPE_MAP.get(ran);
+            for (int type = SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI;
+                    type <= SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR; type++) {
+                if (!validTypes.contains(type)) {
+                    buildWithInvalidParameterThrowException(ran, type, new int[]{-1});
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testConstructor_thresholdsOutOfRange() {
+        for (int signalMeasurementType : INVALID_THRESHOLDS_MAP.keySet()) {
+            List<Integer> invalidThresholds = INVALID_THRESHOLDS_MAP.get(signalMeasurementType);
+            for (int threshold : invalidThresholds) {
+                buildWithInvalidParameterThrowException(getValidRan(signalMeasurementType),
+                        signalMeasurementType, new int[]{threshold});
+            }
+        }
+    }
+
+    @Test
+    public void testParcel() {
+        for (int[] params : VALID_PARAMS) {
+            final int ran = params[0];
+            final int signalMeasurementType = params[1];
+            final int[] thresholds = new int[]{params[2]};
+
+            SignalThresholdInfo sti = new SignalThresholdInfo.Builder()
+                    .setRadioAccessNetworkType(ran)
+                    .setSignalMeasurementType(signalMeasurementType)
+                    .setThresholds(thresholds)
+                    .build();
+            Parcel p = Parcel.obtain();
+            sti.writeToParcel(p, 0);
+            p.setDataPosition(0);
+
+            SignalThresholdInfo newSt = SignalThresholdInfo.CREATOR.createFromParcel(p);
+            assertThat(newSt).isEqualTo(sti);
+        }
+
+    }
+
+    @Test
+    public void testEquals() {
+        final int[] dummyThresholds = new int[]{-100, -90, -70, -60};
+        final int[] dummyThresholdsDisordered = new int[]{-60, -90, -100, -70};
+
+        SignalThresholdInfo sti1 = new SignalThresholdInfo.Builder()
+                .setRadioAccessNetworkType(AccessNetworkConstants.AccessNetworkType.GERAN)
+                .setSignalMeasurementType(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
+                .setThresholds(dummyThresholds)
+                .build();
+
+        SignalThresholdInfo sti2 = new SignalThresholdInfo.Builder()
+                .setRadioAccessNetworkType(AccessNetworkConstants.AccessNetworkType.CDMA2000)
+                .setSignalMeasurementType(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
+                .setThresholds(dummyThresholds)
+                .build();
+
+        SignalThresholdInfo sti3 = new SignalThresholdInfo.Builder()
+                .setRadioAccessNetworkType(AccessNetworkConstants.AccessNetworkType.GERAN)
+                .setSignalMeasurementType(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
+                .setThresholds(dummyThresholds)
+                .build();
+
+        SignalThresholdInfo sti4 = new SignalThresholdInfo.Builder()
+                .setRadioAccessNetworkType(AccessNetworkConstants.AccessNetworkType.GERAN)
+                .setSignalMeasurementType(SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
+                .setThresholds(dummyThresholdsDisordered)
+                .build();
+
+        assertTrue(sti1.equals(sti1));
+        assertFalse(sti1.equals(sti2));
+        assertTrue(sti1.equals(sti3));
+        assertTrue(sti1.equals(sti4));
+        assertFalse(sti1.equals("sti1"));
+    }
+
+    private void buildWithInvalidParameterThrowException(int ran, int signalMeasurementType,
+            int[] thresholds) {
+        try {
+            new SignalThresholdInfo.Builder()
+                    .setRadioAccessNetworkType(ran)
+                    .setSignalMeasurementType(signalMeasurementType)
+                    .setThresholds(thresholds)
+                    .build();
+            fail("Exception expected");
+        } catch (IllegalArgumentException | NullPointerException expected) {
+        }
+    }
+
+    /**
+     * Return a possible valid RAN value for the measurement type. This is used to prevent the
+     * invalid ran/type causing IllegalArgumentException when testing other invalid input cases.
+     */
+    private static int getValidRan(@SignalThresholdInfo.SignalMeasurementType int type) {
+        switch (type) {
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI:
+                return AccessNetworkConstants.AccessNetworkType.GERAN;
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP:
+                return AccessNetworkConstants.AccessNetworkType.UTRAN;
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP:
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ:
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR:
+                return AccessNetworkConstants.AccessNetworkType.EUTRAN;
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP:
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
+            case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR:
+                return AccessNetworkConstants.AccessNetworkType.NGRAN;
+            default:
+                return AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+        }
+    }
+}
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 fbb9793..e457218 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -29,6 +29,7 @@
 import static org.junit.Assert.fail;
 
 import android.Manifest.permission;
+import android.annotation.NonNull;
 import android.app.UiAutomation;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
@@ -57,6 +58,7 @@
 import android.telephony.CallQuality;
 import android.telephony.CarrierBandwidth;
 import android.telephony.CarrierConfigManager;
+import android.telephony.CellInfo;
 import android.telephony.CellLocation;
 import android.telephony.DataThrottlingRequest;
 import android.telephony.NetworkRegistrationInfo;
@@ -65,6 +67,7 @@
 import android.telephony.PreciseCallState;
 import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -121,6 +124,8 @@
     private SubscriptionManager mSubscriptionManager;
     private PackageManager mPackageManager;
     private boolean mOnCellLocationChangedCalled = false;
+    private boolean mOnCellInfoChanged = false;
+    private boolean mOnSignalStrengthsChanged = false;
     private boolean mServiceStateChangedCalled = false;
     private boolean mRadioRebootTriggered = false;
     private boolean mHasRadioPowerOff = false;
@@ -256,7 +261,7 @@
 
     @After
     public void tearDown() throws Exception {
-        if (mListener != null) {
+        if (mListener != null && mListener.isExecutorSet()) {
             // unregister the listener
             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
         }
@@ -384,6 +389,25 @@
             // expected
         }
     }
+
+    @Test
+    public void testListenFailWithNonLooper() throws Throwable {
+        if (!InstrumentationRegistry.getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            Log.d(TAG, "Skipping test that requires PackageManager.FEATURE_TELEPHONY");
+            return;
+        }
+
+        mListener = new PhoneStateListener();
+        try {
+            // .listen generates an onCellLocationChanged event
+            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
+            fail("PhoneStateListener created from a thread without looper should " +
+                    "trigger IllegalStateException.");
+        } catch (IllegalStateException e) {
+        }
+    }
+
     @Test
     public void testListen() throws Throwable {
         if (!InstrumentationRegistry.getContext().getPackageManager()
@@ -415,7 +439,7 @@
                 };
 
                 synchronized (mLock) {
-                    mLock.notify(); // mListener is ready
+                    mLock.notify(); // listener is ready
                 }
 
                 Looper.loop();
@@ -429,8 +453,8 @@
 
         // Test register
         synchronized (mLock) {
-            // .listen generates an onCellLocationChanged event
-            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
+            // .registerPhoneStateListener generates an onCellLocationChanged event
+            mTelephonyManager.registerPhoneStateListener(mSimpleExecutor, mMockPhoneStateListener);
             mLock.wait(TOLERANCE);
 
             assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
@@ -449,19 +473,19 @@
         }
 
         // unregister the listener
-        mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
+        mTelephonyManager.unregisterPhoneStateListener(mMockPhoneStateListener);
         Thread.sleep(TOLERANCE);
 
         // Test unregister
         synchronized (mLock) {
-            mOnCellLocationChangedCalled = false;
+            mOnCellInfoChanged = false;
             // unregister again, to make sure doing so does not call the listener
-            mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
+            mTelephonyManager.unregisterPhoneStateListener(mMockPhoneStateListener);
             CellLocation.requestLocationUpdate();
             mLock.wait(TOLERANCE);
 
             assertFalse("Test unregister, mOnCellLocationChangedCalled should be false.",
-                    mOnCellLocationChangedCalled);
+                    mOnCellInfoChanged);
         }
     }
 
@@ -2151,6 +2175,13 @@
             assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_OFF);
 
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+                    tm -> tm.setCallComposerStatus(
+                            TelephonyManager.CALL_COMPOSER_STATUS_ON_NO_PICTURES));
+            status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
+                    tm -> tm.getCallComposerStatus());
+            assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_ON_NO_PICTURES);
+
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                     tm -> tm.setCallComposerStatus(TelephonyManager.CALL_COMPOSER_STATUS_ON));
             status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                     tm -> tm.getCallComposerStatus());
@@ -2167,6 +2198,13 @@
             status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                     tm -> tm.getCallComposerStatus());
             assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_OFF);
+
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
+                    tm -> tm.setCallComposerStatus(
+                            TelephonyManager.CALL_COMPOSER_STATUS_ON_NO_PICTURES));
+            status = ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
+                    tm -> tm.getCallComposerStatus());
+            assertThat(status).isEqualTo(TelephonyManager.CALL_COMPOSER_STATUS_OFF);
         }
     }
 
@@ -3552,5 +3590,159 @@
         if (major < 0 || minor < 0) return 0;
         return major * 100 + minor;
     }
+
+    private Executor mSimpleExecutor = new Executor() {
+        @Override
+        public void execute(Runnable r) {
+            r.run();
+        }
+    };
+
+    private static MockSignalStrengthsPhoneStateListener mMockSignalStrengthsPhoneStateListener;
+
+    private class MockSignalStrengthsPhoneStateListener extends PhoneStateListener
+            implements PhoneStateListener.SignalStrengthsChangedListener {
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            if (!mOnSignalStrengthsChanged) {
+                synchronized (mLock) {
+                    mOnSignalStrengthsChanged = true;
+                    mLock.notify();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testRegisterPhoneStateListenerWithNonLooper() throws Throwable {
+        if (!InstrumentationRegistry.getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            Log.d(TAG, "Skipping test that requires PackageManager.FEATURE_TELEPHONY");
+            return;
+        }
+
+        mMockSignalStrengthsPhoneStateListener = new MockSignalStrengthsPhoneStateListener();
+
+        // Test register, generates an mOnSignalStrengthsChanged event
+        mTelephonyManager.registerPhoneStateListener(mSimpleExecutor,
+                mMockSignalStrengthsPhoneStateListener);
+
+        synchronized (mLock) {
+            if (!mOnSignalStrengthsChanged) {
+                mLock.wait(TOLERANCE);
+            }
+        }
+        assertTrue("Test register, mOnSignalStrengthsChanged should be true.",
+                mOnSignalStrengthsChanged);
+
+        // Test unregister
+        mOnSignalStrengthsChanged = false;
+        // unregister again, to make sure doing so does not call the listener
+        mTelephonyManager.unregisterPhoneStateListener(mMockSignalStrengthsPhoneStateListener);
+
+        assertFalse("Test unregister, mOnSignalStrengthsChanged should be false.",
+                mOnSignalStrengthsChanged);
+    }
+
+    private static MockPhoneStateListener mMockPhoneStateListener;
+
+    private class MockPhoneStateListener extends PhoneStateListener
+            implements PhoneStateListener.CellInfoChangedListener {
+        @Override
+        public void onCellInfoChanged(@NonNull List<CellInfo> cellInfo) {
+            if (!mOnCellInfoChanged) {
+                synchronized (mLock) {
+                    mOnCellInfoChanged = true;
+                    mLock.notify();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testRegisterPhoneStateListener() throws Throwable {
+        if (!InstrumentationRegistry.getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            Log.d(TAG, "Skipping test that requires PackageManager.FEATURE_TELEPHONY");
+            return;
+        }
+
+        if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+            // TODO: temp workaround, need to adjust test to for CDMA
+            return;
+        }
+        grantLocationPermissions();
+
+        TestThread t = new TestThread(new Runnable() {
+            public void run() {
+                Looper.prepare();
+                mMockPhoneStateListener = new MockPhoneStateListener();
+                synchronized (mLock) {
+                    mLock.notify(); // listener is ready
+                }
+
+                Looper.loop();
+            }
+        });
+
+        synchronized (mLock) {
+            t.start();
+            mLock.wait(TOLERANCE); // wait for mListener
+        }
+
+        // Test register
+        synchronized (mLock) {
+            // .registerPhoneStateListener generates an onCellLocationChanged event
+            mTelephonyManager.registerPhoneStateListener(getContext().getMainExecutor(),
+                    mMockPhoneStateListener);
+            mLock.wait(TOLERANCE);
+
+            assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
+                    mOnCellInfoChanged);
+        }
+
+        synchronized (mLock) {
+            mOnCellInfoChanged = false;
+
+            CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback();
+            mTelephonyManager.requestCellInfoUpdate(getContext().getMainExecutor(), resultsCallback);
+            mLock.wait(TOLERANCE);
+
+            assertTrue("Test register, mOnCellLocationChangedCalled should be true.",
+                    mOnCellInfoChanged);
+        }
+
+        // unregister the listener
+        mTelephonyManager.unregisterPhoneStateListener(mMockPhoneStateListener);
+        Thread.sleep(TOLERANCE);
+
+        // Test unregister
+        synchronized (mLock) {
+            mOnCellInfoChanged = false;
+            // unregister again, to make sure doing so does not call the listener
+            mTelephonyManager.unregisterPhoneStateListener(mMockPhoneStateListener);
+            CellLocation.requestLocationUpdate();
+            mLock.wait(TOLERANCE);
+
+            assertFalse("Test unregister, mOnCellLocationChangedCalled should be false.",
+                    mOnCellInfoChanged);
+        }
+    }
+
+    private class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback {
+        public List<CellInfo> cellInfo;
+
+        @Override
+        public synchronized void onCellInfo(List<CellInfo> cellInfo) {
+            this.cellInfo = cellInfo;
+            notifyAll();
+        }
+
+        public synchronized void wait(int millis) throws InterruptedException {
+            if (cellInfo == null) {
+                super.wait(millis);
+            }
+        }
+    }
 }
 
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index ae64ec4..2a7595d 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -2009,7 +2009,7 @@
             return;
         }
 
-        triggerFrameworkConnectToCarrierImsServiceBindMmtelRcsFeature();
+        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
 
         final int errorCode = 403;
         final String errorString = "Forbidden";
@@ -2094,7 +2094,7 @@
             return;
         }
 
-        triggerFrameworkConnectToCarrierImsServiceBindMmtelRcsFeature();
+        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
 
         final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         LinkedBlockingQueue<Integer> clientQueue = new LinkedBlockingQueue<>();
@@ -2156,7 +2156,7 @@
             return;
         }
 
-        triggerFrameworkConnectToCarrierImsServiceBindMmtelRcsFeature();
+        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
 
         final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         LinkedBlockingQueue<Integer> clientQueue = new LinkedBlockingQueue<>();
@@ -2193,7 +2193,7 @@
         }
         RcsClientConfiguration rcc = new RcsClientConfiguration(
                 "1.0", "UP_1.0", "Android", "RCSAndrd-1.0");
-        triggerFrameworkConnectToCarrierImsServiceBindMmtelRcsFeature();
+        triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
 
         final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         LinkedBlockingQueue<Integer> actionQueue = new LinkedBlockingQueue<>();
@@ -2377,33 +2377,6 @@
                 sTestSlot, serviceSlot);
     }
 
-    private void triggerFrameworkConnectToCarrierImsServiceBindMmtelRcsFeature() throws Exception {
-        // Connect to the ImsService with the MmTel feature.
-        assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
-                .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
-                .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("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());
-        // 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));
-        // 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().getMmTelFeature().getSlotIndex();
-        assertEquals("The slot specified for the test (" + sTestSlot + ") does not match the "
-                        + "assigned slot (" + serviceSlot + "+ for the associated MmTelFeature",
-                sTestSlot, serviceSlot);
-    }
-
     private ProvisioningManager.RcsProvisioningCallback buildRcsProvisioningCallback(
             LinkedBlockingQueue<Integer> actionQueue,
             LinkedBlockingQueue<RcsProvisioningCallbackParams> paramQueue) {