Merge "Clear some random compile warnings."
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
index 9f3ad2f..2f4c6e4 100644
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
@@ -99,20 +99,20 @@
     public void testAllocSpi() throws Exception {
         for (InetAddress addr : GOOGLE_DNS_LIST) {
             IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
-            randomSpi = mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, addr);
+            randomSpi = mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, addr);
             assertTrue(
                     "Failed to receive a valid SPI",
                     randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
 
             droidSpi =
-                    mISM.reserveSecurityParameterIndex(
+                    mISM.allocateSecurityParameterIndex(
                             IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
             assertTrue(
                     "Failed to allocate specified SPI, " + DROID_SPI,
                     droidSpi.getSpi() == DROID_SPI);
 
             try {
-                mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
+                mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
                 fail("Duplicate SPI was allowed to be created");
             } catch (IpSecManager.SpiUnavailableException expected) {
                 // This is a success case because we expect a dupe SPI to throw
@@ -239,10 +239,10 @@
     public void testCreateTransform() throws Exception {
         InetAddress local = LOOPBACK_4;
         IpSecManager.SecurityParameterIndex outSpi =
-                mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
+                mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
 
         IpSecManager.SecurityParameterIndex inSpi =
-                mISM.reserveSecurityParameterIndex(
+                mISM.allocateSecurityParameterIndex(
                         IpSecTransform.DIRECTION_IN, local, outSpi.getSpi());
 
         IpSecTransform transform =
@@ -293,10 +293,10 @@
         InetAddress local = InetAddress.getByName(localAddress);
 
         IpSecManager.SecurityParameterIndex outSpi =
-                mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
+                mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
 
         IpSecManager.SecurityParameterIndex inSpi =
-                mISM.reserveSecurityParameterIndex(
+                mISM.allocateSecurityParameterIndex(
                         IpSecTransform.DIRECTION_IN, local, outSpi.getSpi());
 
         IpSecTransform transform =
@@ -505,9 +505,9 @@
         // Create SPIs, UDP encap socket
         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
                 IpSecManager.SecurityParameterIndex outSpi =
-                        mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
+                        mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
                 IpSecManager.SecurityParameterIndex inSpi =
-                        mISM.reserveSecurityParameterIndex(
+                        mISM.allocateSecurityParameterIndex(
                                 IpSecTransform.DIRECTION_IN, local, outSpi.getSpi());
                 IpSecTransform transform =
                         buildIpSecTransform(mContext, inSpi, outSpi, encapSocket, local)) {
@@ -564,9 +564,9 @@
         // separate sockets for inbound and outbound)
         try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
                 IpSecManager.SecurityParameterIndex outSpi =
-                        mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
+                        mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
                 IpSecManager.SecurityParameterIndex inSpi =
-                        mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, local);
+                        mISM.allocateSecurityParameterIndex(IpSecTransform.DIRECTION_IN, local);
                 IpSecTransform transform =
                         buildIpSecTransform(mContext, inSpi, outSpi, encapSocket, local)) {
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 93e4c65..ea29552 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -15,18 +15,21 @@
  */
 
 package android.telecom.cts;
+
 import static android.telecom.cts.TestUtils.PACKAGE;
 import static android.telecom.cts.TestUtils.TAG;
 import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
 
-import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertThat;
 
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.telecom.Call;
 import android.telecom.CallAudioState;
 import android.telecom.Conference;
@@ -37,13 +40,18 @@
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telecom.cts.MockInCallService.InCallServiceCallbacks;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
 import android.test.InstrumentationTestCase;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -59,6 +67,7 @@
 
     Context mContext;
     TelecomManager mTelecomManager;
+    TelephonyManager mTelephonyManager;
 
     TestUtils.InvokeCounter mOnBringToForegroundCounter;
     TestUtils.InvokeCounter mOnCallAudioStateChangedCounter;
@@ -79,33 +88,86 @@
     String mPreviousDefaultDialer = null;
     MockConnectionService connectionService = null;
 
+    HandlerThread mPhoneStateListenerThread;
+    Handler mPhoneStateListenerHandler;
+    TestPhoneStateListener mPhoneStateListener;
+
+    static class TestPhoneStateListener extends PhoneStateListener {
+        /** Semaphore released for every callback invocation. */
+        public Semaphore mCallbackSemaphore = new Semaphore(0);
+
+        List<Pair<Integer, String>> mCallStates = new ArrayList<>();
+
+        @Override
+        public void onCallStateChanged(int state, String number) {
+            mCallStates.add(Pair.create(state, number));
+            mCallbackSemaphore.release();
+        }
+    }
+
     boolean mShouldTestTelecom = true;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mContext = getInstrumentation().getContext();
-        mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
 
         mShouldTestTelecom = TestUtils.shouldTestTelecom(mContext);
-        if (mShouldTestTelecom) {
-            mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
-            TestUtils.setDefaultDialer(getInstrumentation(), PACKAGE);
-            setupCallbacks();
+        if (!mShouldTestTelecom) {
+            return;
         }
+
+        mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+
+        mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
+        TestUtils.setDefaultDialer(getInstrumentation(), PACKAGE);
+        setupCallbacks();
+
+        // PhoneStateListener's public API registers the listener on the calling thread, which must
+        // be a looper thread. So we need to create and register the listener in a custom looper
+        // thread.
+        mPhoneStateListenerThread = new HandlerThread("PhoneStateListenerThread");
+        mPhoneStateListenerThread.start();
+        mPhoneStateListenerHandler = new Handler(mPhoneStateListenerThread.getLooper());
+        final CountDownLatch registeredLatch = new CountDownLatch(1);
+        mPhoneStateListenerHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mPhoneStateListener = new TestPhoneStateListener();
+                mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+                registeredLatch.countDown();
+            }
+        });
+        registeredLatch.await(
+                TestUtils.WAIT_FOR_PHONE_STATE_LISTENER_REGISTERED_TIMEOUT_S, TimeUnit.SECONDS);
     }
 
     @Override
     protected void tearDown() throws Exception {
-        if (mShouldTestTelecom) {
-            cleanupCalls();
-            if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
-                TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
-            }
-            tearDownConnectionService(TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
-            assertMockInCallServiceUnbound();
-        }
         super.tearDown();
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
+        final CountDownLatch unregisteredLatch = new CountDownLatch(1);
+        mPhoneStateListenerHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+                unregisteredLatch.countDown();
+            }
+        });
+        unregisteredLatch.await(
+                TestUtils.WAIT_FOR_PHONE_STATE_LISTENER_REGISTERED_TIMEOUT_S, TimeUnit.SECONDS);
+        mPhoneStateListenerThread.quit();
+
+        cleanupCalls();
+        if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
+            TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
+        }
+        tearDownConnectionService(TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
+        assertMockInCallServiceUnbound();
     }
 
     protected PhoneAccount setupConnectionService(MockConnectionService connectionService,
@@ -506,6 +568,14 @@
         assertConferenceState(conference, Connection.STATE_ACTIVE);
     }
 
+    void verifyPhoneStateListenerCallbacksForCall(int expectedCallState) throws Exception {
+        assertTrue(mPhoneStateListener.mCallbackSemaphore.tryAcquire(
+                TestUtils.WAIT_FOR_PHONE_STATE_LISTENER_CALLBACK_TIMEOUT_S, TimeUnit.SECONDS));
+        Pair<Integer, String> callState = mPhoneStateListener.mCallStates.get(0);
+        assertEquals(expectedCallState, (int) callState.first);
+        assertEquals(getTestNumber().getSchemeSpecificPart(), callState.second);
+    }
+
     /**
      * Disconnect the created test call and verify that Telecom has cleared all calls.
      */
diff --git a/tests/tests/telecom/src/android/telecom/cts/IncomingCallTest.java b/tests/tests/telecom/src/android/telecom/cts/IncomingCallTest.java
index f3ffeaa..472b03b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/IncomingCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/IncomingCallTest.java
@@ -16,17 +16,18 @@
 
 package android.telecom.cts;
 
+import static android.telecom.cts.TestUtils.COMPONENT;
+import static android.telecom.cts.TestUtils.PACKAGE;
+
 import android.content.ComponentName;
 import android.os.Bundle;
 import android.telecom.Connection;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 
 import java.util.Collection;
 
-import static android.telecom.cts.TestUtils.COMPONENT;
-import static android.telecom.cts.TestUtils.PACKAGE;
-
 /**
  * Tests valid/invalid incoming calls that are received from the ConnectionService
  * and registered through TelecomManager
@@ -36,12 +37,6 @@
     private static final PhoneAccountHandle TEST_INVALID_HANDLE = new PhoneAccountHandle(
             new ComponentName(PACKAGE, COMPONENT), "WRONG_ID");
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mContext = getInstrumentation().getContext();
-    }
-
     public void testAddNewIncomingCall_CorrectPhoneAccountHandle() throws Exception {
         if (!mShouldTestTelecom) {
             return;
@@ -54,6 +49,16 @@
         assertTrue(connections.contains(connection3));
     }
 
+    public void testPhoneStateListenerInvokedOnIncomingCall() throws Exception {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+        setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
+        addAndVerifyNewIncomingCall(createTestNumber(), null);
+        verifyConnectionForIncomingCall();
+        verifyPhoneStateListenerCallbacksForCall(TelephonyManager.CALL_STATE_RINGING);
+    }
+
     /**
      * Tests to be sure that new incoming calls can only be added using a valid PhoneAccountHandle
      * (b/26864502). If a PhoneAccount has not been registered for the PhoneAccountHandle, then
diff --git a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
index 38a6709..6df32f8 100644
--- a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
@@ -16,13 +16,12 @@
 
 package android.telecom.cts;
 
-import static android.telecom.cts.TestUtils.shouldTestTelecom;
-
 import android.content.Context;
 import android.media.AudioManager;
 import android.os.Bundle;
 import android.telecom.CallAudioState;
 import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 
 /**
  * Verifies the behavior of Telecom during various outgoing call flows.
@@ -94,4 +93,14 @@
         }
         assertNotAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_SPEAKER);
     }
+
+    public void testPhoneStateListenerInvokedOnOutgoingCall() throws Exception {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
+        placeAndVerifyCall();
+        verifyConnectionForOutgoingCall();
+        verifyPhoneStateListenerCallbacksForCall(TelephonyManager.CALL_STATE_OFFHOOK);
+    }
 }
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index 5c67190..ac717d7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -15,8 +15,6 @@
  */
 package android.telecom.cts;
 
-import com.android.compatibility.common.util.ApiLevelUtil;
-
 import android.app.Instrumentation;
 import android.content.ComponentName;
 import android.content.Context;
@@ -28,7 +26,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
-import android.os.Process;
 import android.os.SystemClock;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -53,6 +50,8 @@
     static final long WAIT_FOR_STATE_CHANGE_TIMEOUT_MS = 10000;
     static final long WAIT_FOR_CALL_ADDED_TIMEOUT_S = 15;
     static final long WAIT_FOR_STATE_CHANGE_TIMEOUT_CALLBACK = 50;
+    static final long WAIT_FOR_PHONE_STATE_LISTENER_REGISTERED_TIMEOUT_S = 15;
+    static final long WAIT_FOR_PHONE_STATE_LISTENER_CALLBACK_TIMEOUT_S = 15;
 
     // Non-final to allow modification by tests not in this package (e.g. permission-related
     // tests in the Telecom2 test package.