Merge "Merge history of cts/hostsidetests/statsd" into stage-aosp-master
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index 5adb97f..191a70b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -888,7 +888,10 @@
      * that are smaller than the dockedSizes.
      */
     private static void assertSizesAreSane(SizeInfo fullscreenSizes, SizeInfo dockedSizes) {
-        if (isDisplayPortrait()) {
+        final boolean isHorizontalDivision =
+                fullscreenSizes.displayHeight - dockedSizes.displayHeight >
+                fullscreenSizes.displayWidth - dockedSizes.displayWidth;
+        if (isHorizontalDivision) {
             assertThat(dockedSizes.displayHeight, lessThan(fullscreenSizes.displayHeight));
             assertThat(dockedSizes.heightDp, lessThan(fullscreenSizes.heightDp));
             assertThat(dockedSizes.metricsHeight, lessThan(fullscreenSizes.metricsHeight));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index 89b310d..2a82511 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -862,7 +862,7 @@
     public void testConfigurationChangeOrderDuringTransition() throws Exception {
         // Launch a PiP activity and ensure configuration change only happened once, and that the
         // configuration change happened after the picture-in-picture and multi-window callbacks
-        launchActivity(PIP_ACTIVITY);
+        launchActivity(PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
         separateTestJournal();
         int windowingMode = mWmState.getTaskByActivity(PIP_ACTIVITY).getWindowingMode();
         mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP);
diff --git a/tests/media/OWNERS b/tests/media/OWNERS
index 4f734c8..ad8bb0a 100644
--- a/tests/media/OWNERS
+++ b/tests/media/OWNERS
@@ -9,3 +9,7 @@
 marcone@google.com
 pawin@google.com
 wonsik@google.com
+
+# LON
+olly@google.com
+andrewlewis@google.com
diff --git a/tests/tests/media/OWNERS b/tests/tests/media/OWNERS
index e3d8ccc..4f5a2ef 100644
--- a/tests/tests/media/OWNERS
+++ b/tests/tests/media/OWNERS
@@ -12,3 +12,7 @@
 jmtrivi@google.com
 jsharkey@android.com
 sungsoo@google.com
+
+# LON
+olly@google.com
+andrewlewis@google.com
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index cbcaf24..e04ace9 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -2302,6 +2302,15 @@
     <permission android:name="android.permission.READ_CARRIER_APP_INFO"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an GbaService to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_GBA_SERVICE"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
     <!-- ================================== -->
diff --git a/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java b/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java
index 6ec352c..496270f 100644
--- a/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java
+++ b/tests/tests/selinux/common/src/android/security/SELinuxTargetSdkTestBase.java
@@ -12,6 +12,7 @@
 import java.util.Collections;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
+import org.junit.Assert;
 
 abstract class SELinuxTargetSdkTestBase extends AndroidTestCase
 {
@@ -19,6 +20,8 @@
         System.loadLibrary("ctsselinux_jni");
     }
 
+    static final byte[] ANONYMIZED_HARDWARE_ADDRESS = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
     protected static String getFile(String filename) throws IOException {
         BufferedReader in = null;
         try {
@@ -76,19 +79,11 @@
         }
     }
 
-    protected static void checkNetlinkRouteBind(boolean expectAllowed) throws IOException {
-        if (!expectAllowed) {
-            assertEquals(
-                    "Bind() is not allowed on a netlink route sockets",
-                    13,
-                    checkNetlinkRouteBind());
-        } else {
-            assertEquals(
-                    "Bind() should succeed for netlink route sockets for apps with "
-                            + "targetSdkVersion <= Q",
-                    -1,
-                    checkNetlinkRouteBind());
-        }
+    protected static void noNetlinkRouteBind() throws IOException {
+        assertEquals(
+                "bind() is not allowed on netlink route sockets",
+                13,
+                checkNetlinkRouteBind());
     }
 
     /**
@@ -169,16 +164,17 @@
     }
 
     /**
-     * Verify that apps having targetSdkVersion <= 29 are able to see MAC
-     * addresses of ethernet devices.
+     * Verify that apps having targetSdkVersion <= 29 get an anonymized MAC
+     * address (02:00:00:00:00:00) instead of a null MAC for ethernet interfaces.
      * The counterpart of this test (testing for targetSdkVersion > 29) is
      * {@link libcore.java.net.NetworkInterfaceTest#testGetHardwareAddress_returnsNull()}.
      */
-    protected static void checkNetworkInterface_returnsHardwareAddresses() throws Exception {
+    protected static void checkNetworkInterface_returnsAnonymizedHardwareAddresses()
+        throws Exception {
         assertNotNull(NetworkInterface.getNetworkInterfaces());
         for (NetworkInterface nif : Collections.list(NetworkInterface.getNetworkInterfaces())) {
             if (isEthernet(nif.getName())) {
-                assertEquals(6, nif.getHardwareAddress().length);
+                Assert.assertArrayEquals(ANONYMIZED_HARDWARE_ADDRESS, nif.getHardwareAddress());
             }
         }
     }
diff --git a/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java
index 1ed366e..1098a6f 100644
--- a/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxEphemeral/src/android/security/SELinuxTargetSdkTest.java
@@ -83,6 +83,6 @@
     }
 
     public void testNoNetlinkRouteBind() throws IOException {
-        checkNetlinkRouteBind(false);
+        noNetlinkRouteBind();
     }
 }
diff --git a/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java
index a784464..5e2f75d 100644
--- a/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk27/src/android/security/SELinuxTargetSdkTest.java
@@ -66,6 +66,6 @@
     }
 
     public void testNetworkInterface() throws Exception {
-        checkNetworkInterface_returnsHardwareAddresses();
+        checkNetworkInterface_returnsAnonymizedHardwareAddresses();
     }
 }
diff --git a/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java
index 880ae1a..29b68db 100644
--- a/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java
@@ -66,6 +66,6 @@
     }
 
     public void testNetworkInterface() throws Exception {
-        checkNetworkInterface_returnsHardwareAddresses();
+        checkNetworkInterface_returnsAnonymizedHardwareAddresses();
     }
 }
diff --git a/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java
index 1f1eaaa..c1d93dc 100644
--- a/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk29/src/android/security/SELinuxTargetSdkTest.java
@@ -47,8 +47,8 @@
         checkNetlinkRouteGetlink(true);
     }
 
-    public void testNetlinkRouteBindSucceeds() throws IOException {
-        checkNetlinkRouteBind(true);
+    public void testNoNetlinkRouteBind() throws IOException {
+        noNetlinkRouteBind();
     }
 
     public void testCanNotExecuteFromHomeDir() throws Exception {
@@ -86,6 +86,6 @@
     }
 
     public void testNetworkInterface() throws Exception {
-        checkNetworkInterface_returnsHardwareAddresses();
+        checkNetworkInterface_returnsAnonymizedHardwareAddresses();
     }
 }
diff --git a/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
index 05fad31..4de03b0 100644
--- a/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
@@ -38,7 +38,7 @@
     }
 
     public void testNoNetlinkRouteBind() throws IOException {
-        checkNetlinkRouteBind(false);
+        noNetlinkRouteBind();
     }
 
     public void testCanNotExecuteFromHomeDir() throws Exception {
diff --git a/tests/tests/telephony/current/AndroidManifest.xml b/tests/tests/telephony/current/AndroidManifest.xml
index f6b655e..2a26b18 100644
--- a/tests/tests/telephony/current/AndroidManifest.xml
+++ b/tests/tests/telephony/current/AndroidManifest.xml
@@ -150,6 +150,16 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name="android.telephony.gba.cts.TestGbaService"
+            android:directBootAware="true"
+            android:permission="android.permission.BIND_GBA_SERVICE"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.telephony.gba.GbaService"/>
+            </intent-filter>
+        </service>
+
         <activity android:name="android.telephony.cts.StubDialerActvity">
             <intent-filter>
                 <action android:name="android.intent.action.DIAL" />
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
new file mode 100644
index 0000000..64a1538
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2020 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.gba.cts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Instrumentation;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.cts.TelephonyUtils;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@RunWith(AndroidJUnit4.class)
+public final class GbaServiceTest {
+
+    private static final String TAG = "GbaServiceTest";
+
+    private static final String COMMAND_UPDATE_PACKAGE = "cmd phone gba set-service ";
+    private static final String COMMAND_UPDATE_RELEASE = "cmd phone gba set-release ";
+    private static final String COMMAND_GET_PACKAGE = "cmd phone gba get-service";
+    private static final String COMMAND_GET_RELEASE = "cmd phone gba get-release";
+    private static final String SERVICE_PACKAGE = "android.telephony.cts";
+    private static final String NAF = "3GPP-bootstrapping@naf1.operator.com";
+    private static final String BTID = "(B-TID)";
+    private static final int REQ_TIMEOUT = 5000;
+    private static final int RELEASE_DEFAULT = 0;
+    private static final int RELEASE_TEST_MS = 15 * 1000;
+    private static final int RELEASE_NEVER = -1;
+
+    private static int sSubId;
+    private static Instrumentation sInstrumentation;
+    private static TelephonyManager sTm;
+    private static TestGbaConfig sConfig;
+    private static String sServiceConfig;
+    private static int sReleaseTimeConfig;
+
+    @BeforeClass
+    public static void init() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        sConfig = TestGbaConfig.getInstance();
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+        sTm = sInstrumentation.getContext().getSystemService(TelephonyManager.class);
+        sServiceConfig = TelephonyUtils.executeShellCommand(
+                sInstrumentation, COMMAND_GET_PACKAGE);
+        sReleaseTimeConfig = Integer.parseInt(TelephonyUtils.executeShellCommand(
+                sInstrumentation, COMMAND_GET_RELEASE));
+    }
+
+    @AfterClass
+    public static void release() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        setService(sServiceConfig);
+        setReleaseTime(sReleaseTimeConfig);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        setService(SERVICE_PACKAGE);
+        setReleaseTime(RELEASE_DEFAULT);
+    }
+
+    @Test (expected = SecurityException.class)
+    public void testPermissions() {
+        if (!isFeatureSupported()) {
+            throw new SecurityException("Feaure is not supported");
+        }
+
+        runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED,
+                android.Manifest.permission.READ_PHONE_STATE);
+    }
+
+    @Test
+    public void testAuthSuccess() {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        Random rand = new Random();
+
+        for (int i = 0; i < 20; i++) {
+            Log.d(TAG, "testAuthSuccess[" + i + "]");
+            byte[] key = new byte[16];
+            rand.nextBytes(key);
+            sConfig.setConfig(true, key, BTID, TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+            final AtomicBoolean isSuccess = new AtomicBoolean(false);
+            final AtomicBoolean isFail = new AtomicBoolean(false);
+            TelephonyManager.BootstrapAuthenticationCallback cb = new
+                      TelephonyManager.BootstrapAuthenticationCallback() {
+                @Override
+                public void onKeysAvailable(byte[] gbaKey, String btId) {
+                    assertNotNull(gbaKey);
+                    assertNotNull(btId);
+                    assertArrayEquals(key, gbaKey);
+                    assertEquals(BTID, btId);
+                    synchronized (isSuccess) {
+                        isSuccess.set(true);
+                        isSuccess.notify();
+                    }
+                }
+
+                @Override
+                public void onAuthenticationFailure(int reason) {
+                    synchronized (isSuccess) {
+                        isFail.set(true);
+                        isSuccess.notify();
+                    }
+                }
+            };
+            UaSecurityProtocolIdentifier.Builder builder =
+                    new UaSecurityProtocolIdentifier.Builder();
+            builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP).setProtocol(
+                    UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS);
+
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTm,
+                    (tm) -> tm.bootstrapAuthenticationRequest(TelephonyManager.APPTYPE_USIM,
+                    Uri.parse(NAF), builder.build(), true, AsyncTask.SERIAL_EXECUTOR, cb),
+                    android.Manifest.permission.MODIFY_PHONE_STATE);
+            waitForMs(isSuccess, REQ_TIMEOUT);
+
+            assertTrue(isSuccess.get());
+            assertFalse(isFail.get());
+        }
+    }
+
+    @Test
+    public void testGbaNotSupported() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        setService("");
+        sConfig.setConfig(true, new byte[16], BTID, TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+
+        runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED,
+                android.Manifest.permission.MODIFY_PHONE_STATE);
+
+        assertTrue(setService(SERVICE_PACKAGE));
+    }
+
+    @Test
+    public void testAuthFail() {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        for (int r = TelephonyManager.GBA_FAILURE_REASON_UNKNOWN;
+                r <= TelephonyManager.GBA_FAILURE_REASON_SECURITY_PROTOCOL_NOT_SUPPORTED; r++) {
+            sConfig.setConfig(false, new byte[16], BTID, r);
+            runGbaFailCase(r, android.Manifest.permission.MODIFY_PHONE_STATE);
+        }
+    }
+
+    private void runGbaFailCase(int r, String permission) {
+        final AtomicBoolean isSuccess = new AtomicBoolean(false);
+        final AtomicBoolean isFail = new AtomicBoolean(false);
+        TelephonyManager.BootstrapAuthenticationCallback cb = new
+                  TelephonyManager.BootstrapAuthenticationCallback() {
+            @Override
+            public void onKeysAvailable(byte[] gbaKey, String btId) {
+                synchronized (isFail) {
+                    isSuccess.set(true);
+                    isFail.notify();
+                }
+            }
+
+            @Override
+            public void onAuthenticationFailure(int reason) {
+                assertEquals(reason, r);
+                synchronized (isFail) {
+                    isFail.set(true);
+                    isFail.notify();
+                }
+            }
+        };
+        UaSecurityProtocolIdentifier.Builder builder = new UaSecurityProtocolIdentifier.Builder();
+        builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP).setProtocol(
+                UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS);
+
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sTm,
+                (tm) -> tm.bootstrapAuthenticationRequest(TelephonyManager.APPTYPE_USIM,
+                Uri.parse(NAF), builder.build(), true, AsyncTask.SERIAL_EXECUTOR, cb), permission);
+        waitForMs(isFail, REQ_TIMEOUT);
+
+        assertTrue(isFail.get());
+        assertFalse(isSuccess.get());
+    }
+
+    @Test
+    public void testServiceReleaseDefault() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        int ss = sConfig.getServiceState();
+        boolean isExpected = (ss == TestGbaConfig.STATE_UNKNOWN
+                || ss == TestGbaConfig.STATE_REMOVED
+                || ss == TestGbaConfig.STATE_UNBOUND);
+        assertTrue(isExpected);
+        sConfig.setConfig(false, new byte[16], BTID,
+                TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+
+        runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_UNKNOWN,
+                android.Manifest.permission.MODIFY_PHONE_STATE);
+        waitForMs(sConfig, 500);
+
+        assertFalse(TestGbaConfig.STATE_BOUND == sConfig.getServiceState());
+    }
+
+    @Test
+    public void testServiceReleaseDuration() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        int ss = sConfig.getServiceState();
+        boolean isExpected = (ss == TestGbaConfig.STATE_UNKNOWN
+                || ss == TestGbaConfig.STATE_REMOVED
+                || ss == TestGbaConfig.STATE_UNBOUND);
+        assertTrue(isExpected);
+        sConfig.setConfig(false, new byte[16], BTID,
+                TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+        assertTrue(setReleaseTime(RELEASE_TEST_MS));
+
+        runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_UNKNOWN,
+                android.Manifest.permission.MODIFY_PHONE_STATE);
+
+        waitForMs(sConfig, 500);
+        assertEquals(TestGbaConfig.STATE_BOUND, sConfig.getServiceState());
+
+        waitForMs(sConfig, RELEASE_TEST_MS);
+        assertFalse(TestGbaConfig.STATE_BOUND == sConfig.getServiceState());
+    }
+
+    @Test
+    public void testServiceNoRelease() throws Exception {
+        if (!isFeatureSupported()) {
+            return;
+        }
+
+        int ss = sConfig.getServiceState();
+        boolean isExpected = (ss == TestGbaConfig.STATE_UNKNOWN
+                || ss == TestGbaConfig.STATE_REMOVED
+                || ss == TestGbaConfig.STATE_UNBOUND);
+        assertTrue(isExpected);
+        sConfig.setConfig(false, new byte[16], BTID,
+                TelephonyManager.GBA_FAILURE_REASON_UNKNOWN);
+        assertTrue(setReleaseTime(RELEASE_NEVER));
+
+        runGbaFailCase(TelephonyManager.GBA_FAILURE_REASON_UNKNOWN,
+                android.Manifest.permission.MODIFY_PHONE_STATE);
+        waitForMs(sConfig, 2 * RELEASE_TEST_MS);
+
+        assertEquals(TestGbaConfig.STATE_BOUND, sConfig.getServiceState());
+    }
+
+    public static void waitForMs(Object obj, long ms) {
+        synchronized (obj) {
+            try {
+                obj.wait(ms);
+            } catch (InterruptedException e) {
+                Log.d(TAG, "InterruptedException while waiting: " + e);
+            }
+        }
+    }
+
+    private static boolean setService(String packageName) throws Exception {
+        String result = TelephonyUtils.executeShellCommand(sInstrumentation,
+                COMMAND_UPDATE_PACKAGE + packageName);
+        return "true".equals(result);
+    }
+
+    private static boolean setReleaseTime(int interval) throws Exception {
+        String result = TelephonyUtils.executeShellCommand(sInstrumentation,
+                COMMAND_UPDATE_RELEASE + interval);
+        return "true".equals(result);
+    }
+
+    private static boolean isFeatureSupported() {
+        if (!InstrumentationRegistry.getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY)) {
+            return false;
+        }
+        int[] activeSubs = InstrumentationRegistry.getContext().getSystemService(
+                SubscriptionManager.class).getActiveSubscriptionIdList();
+        if (activeSubs.length == 0) {
+            return false;
+        }
+        sSubId = activeSubs[0];
+        return true;
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaConfig.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaConfig.java
new file mode 100644
index 0000000..33d1a83
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaConfig.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 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.gba.cts;
+
+final class TestGbaConfig {
+
+    static final int STATE_UNKNOWN = 0;
+    static final int STATE_CREATED = 1;
+    static final int STATE_BOUND   = 2;
+    static final int STATE_UNBOUND = 3;
+    static final int STATE_REMOVED = 4;
+
+    private boolean mIsAuthSuccess;
+    private byte[] mGbaKey;
+    private String mBTid;
+    private int mFailReason;
+    private int mServiceState;
+
+    private static TestGbaConfig sInstance;
+
+    private TestGbaConfig() {
+    }
+
+    static TestGbaConfig getInstance() {
+        if (sInstance == null) {
+            sInstance = new TestGbaConfig();
+        }
+        return sInstance;
+    }
+
+    void setConfig(boolean success, byte[] key, String id, int reason) {
+        synchronized (this) {
+            mIsAuthSuccess = success;
+            mGbaKey = key;
+            mBTid = id;
+            mFailReason = reason;
+        }
+    }
+
+    boolean isAuthSuccess() {
+        synchronized (this) {
+            return mIsAuthSuccess;
+        }
+    }
+
+    byte[] getGbaKey() {
+        synchronized (this) {
+            return mGbaKey;
+        }
+    }
+
+    String getBTid() {
+        synchronized (this) {
+            return mBTid;
+        }
+    }
+
+    int getFailReason() {
+        synchronized (this) {
+            return mFailReason;
+        }
+    }
+
+    void setServiceState(int state) {
+        synchronized (this) {
+            mServiceState = state;
+            this.notify();
+        }
+    }
+
+    int getServiceState() {
+        synchronized (this) {
+            return mServiceState;
+        }
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaService.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaService.java
new file mode 100644
index 0000000..702f757
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/TestGbaService.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 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.gba.cts;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.IBinder;
+import android.telephony.gba.GbaService;
+import android.util.Log;
+
+public class TestGbaService extends GbaService {
+
+    private static final String TAG = "TestGbaService";
+
+    private TestGbaConfig mConfig;
+
+    @Override
+    public void onCreate() {
+        Log.i(TAG, "Service created");
+        mConfig = TestGbaConfig.getInstance();
+        mConfig.setServiceState(TestGbaConfig.STATE_CREATED);
+    }
+
+    @Override
+    public void onAuthenticationRequest(int subId, int token, int appType,
+            @NonNull Uri nafUrl, @NonNull byte[] securityProtocol, boolean forceBootStrapping) {
+        boolean isSuccess = mConfig.isAuthSuccess();
+        int reason = mConfig.getFailReason();
+        byte[] key = mConfig.getGbaKey();
+        String btid = mConfig.getBTid();
+
+        if (isSuccess) {
+            reportKeysAvailable(token, key, btid);
+        } else {
+            reportAuthenticationFailure(token, reason);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(TAG, "onBind intent:" + intent);
+        mConfig.setServiceState(TestGbaConfig.STATE_BOUND);
+        return super.onBind(intent);
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.d(TAG, "onUnbind intent:" + intent);
+        mConfig.setServiceState(TestGbaConfig.STATE_UNBOUND);
+        return super.onUnbind(intent);
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(TAG, "onDestroy!");
+        mConfig.setServiceState(TestGbaConfig.STATE_REMOVED);
+        super.onDestroy();
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/UaSecurityProtocolIdentifierTest.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/UaSecurityProtocolIdentifierTest.java
new file mode 100644
index 0000000..ae1b0fd
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/UaSecurityProtocolIdentifierTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2020 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.gba.cts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.telephony.gba.TlsParams;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Random;
+
+@RunWith(AndroidJUnit4.class)
+public final class UaSecurityProtocolIdentifierTest {
+    private static final String TAG = "UaSecurityProtocolIdentifierTest";
+    private static final int PROTO_SIZE = 5;
+    private static final byte[] PROTO_DEFAULT = {0x00, 0x00, 0x00, 0x00, 0x00};
+    private static final int[] PROTO_3GPP_PLAIN_ID = {
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_MBMS,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI};
+    private static final byte[][] PROTO_3GPP_PLAIN = {
+        {0x01, 0x00, 0x00, 0x00, 0x00},
+        {0x01, 0x00, 0x00, 0x00, 0x01},
+        {0x01, 0x00, 0x00, 0x00, 0x02},
+        {0x01, 0x00, 0x00, 0x00, 0x03},
+        {0x01, 0x00, 0x00, 0x00, 0x04},
+        {0x01, 0x00, 0x00, 0x00, 0x05},
+        {0x01, 0x00, 0x00, 0x00, 0x06},
+        {0x01, 0x00, 0x00, 0x01, 0x00}};
+    private static final int[] PROTO_3GPP_TLS_ID = {
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT,
+        UaSecurityProtocolIdentifier.UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER};
+    private static final byte[][] PROTO_3GPP_TLS = {
+        {0x01, 0x00, 0x01, 0x00, 0x00},
+        {0x01, 0x00, 0x02, 0x00, 0x00}};
+
+    private static final int[] TLS_CS_ID_SUPPORTED = {
+        0x0000, 0x0001, 0x0002, 0x0004, 0x0005, 0x000A, 0x000D, 0x0010, 0x0013, 0x0016, 0x0018,
+        0x001B, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+        0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0067, 0x0068, 0x0069,
+        0x006A, 0x006B, 0x006C, 0x006D, 0x009E, 0x009F, 0x00AA, 0x00AB, 0x1301, 0x1302, 0x1303,
+        0x1304, 0xC02B, 0xC02C, 0xC02F, 0xC030, 0xC09E, 0xC09F, 0xC0A6, 0xC0A7, 0xCCA8, 0xCCA9,
+        0xCCAA, 0xCCAC, 0xCCAD, 0xD001, 0xD002, 0xD005};
+
+    @Test
+    public void testDefaultId() {
+        UaSecurityProtocolIdentifier.Builder builder = new UaSecurityProtocolIdentifier.Builder();
+        UaSecurityProtocolIdentifier sp = builder.build();
+        assertNotNull(sp);
+        assertEquals(UaSecurityProtocolIdentifier.ORG_NONE, sp.getOrg());
+        assertArrayEquals(sp.toByteArray(), PROTO_DEFAULT);
+    }
+
+    @Test
+    public void testValid3gppId() {
+        for (int i = 0; i < PROTO_3GPP_PLAIN_ID.length; i++) {
+            UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+                    PROTO_3GPP_PLAIN_ID[i], null, false);
+            assertNotNull(sp);
+            assertEquals(UaSecurityProtocolIdentifier.ORG_3GPP, sp.getOrg());
+            assertEquals(PROTO_3GPP_PLAIN_ID[i], sp.getProtocol());
+            assertEquals(0, sp.getTlsCipherSuite());
+            assertArrayEquals(sp.toByteArray(), PROTO_3GPP_PLAIN[i]);
+        }
+    }
+
+    @Test
+    public void testValid3gppIdWithTls() {
+        for (int i = 0; i < PROTO_3GPP_TLS_ID.length; i++) {
+            for (int j = 0; j < TLS_CS_ID_SUPPORTED.length; j++) {
+                UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+                        PROTO_3GPP_TLS_ID[i], TLS_CS_ID_SUPPORTED[j], false);
+                assertNotNull(sp);
+                assertEquals(UaSecurityProtocolIdentifier.ORG_3GPP, sp.getOrg());
+                assertEquals(PROTO_3GPP_TLS_ID[i], sp.getProtocol());
+                assertEquals(TLS_CS_ID_SUPPORTED[j], sp.getTlsCipherSuite());
+                byte[] targetData = new byte[PROTO_SIZE];
+                ByteBuffer buf = ByteBuffer.wrap(targetData);
+                buf.put(PROTO_3GPP_TLS[i]);
+                buf.putShort(PROTO_SIZE - 2, (short) TLS_CS_ID_SUPPORTED[j]);
+                assertArrayEquals(targetData, sp.toByteArray());
+            }
+        }
+    }
+
+    @Test
+    public void testInvalidId() {
+        Random rand = new Random();
+        HashSet<Integer> validIds = new HashSet<>();
+        for (int id : PROTO_3GPP_PLAIN_ID) {
+            validIds.add(id);
+        }
+        for (int id : PROTO_3GPP_TLS_ID) {
+            validIds.add(id);
+        }
+        for (int i = 0; i < 200; i++) {
+            int r = rand.nextInt();
+            UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+                    r, TlsParams.TLS_NULL_WITH_NULL_NULL, !validIds.contains(r));
+        }
+    }
+
+    @Test
+    public void testInvalid3gppIdWithTls() {
+        Random rand = new Random();
+        for (int i = 0; i < PROTO_3GPP_TLS_ID.length; i++) {
+            for (int j = 0; j < 200; j++) {
+                int r = rand.nextInt(Integer.MAX_VALUE);
+                int index = Arrays.binarySearch(TLS_CS_ID_SUPPORTED, r);
+                boolean isFailExpected = index < 0;
+                UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+                        PROTO_3GPP_TLS_ID[i], r, isFailExpected);
+            }
+        }
+    }
+
+    @Test
+    public void testParcelUnparcel() {
+        UaSecurityProtocolIdentifier sp = testCreate3GppSpId(
+                PROTO_3GPP_TLS_ID[0], TLS_CS_ID_SUPPORTED[0], false);
+        Parcel parcel = Parcel.obtain();
+        sp.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        UaSecurityProtocolIdentifier sp2 =
+                UaSecurityProtocolIdentifier.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+        assertTrue(sp.equals(sp2));
+    }
+
+    @Test
+    public void testIsTlsCipherSuiteSupported() {
+        Random rand = new Random();
+
+        for (int i = 0; i < TLS_CS_ID_SUPPORTED.length; i++) {
+            assertTrue(TlsParams.isTlsCipherSuiteSupported(TLS_CS_ID_SUPPORTED[i]));
+        }
+
+        for (int i = 0; i < 100; i++) {
+            int val = rand.nextInt();
+            if (Arrays.binarySearch(TLS_CS_ID_SUPPORTED, val) < 0) {
+                assertFalse(TlsParams.isTlsCipherSuiteSupported(val));
+            }
+        }
+    }
+
+    private UaSecurityProtocolIdentifier testCreate3GppSpId(
+            Integer id, Integer cs, boolean nullExpected) {
+        boolean isFail = false;
+        UaSecurityProtocolIdentifier sp = null;
+        UaSecurityProtocolIdentifier.Builder builder = new UaSecurityProtocolIdentifier.Builder();
+        builder.setOrg(UaSecurityProtocolIdentifier.ORG_3GPP);
+        try {
+            if (id != null) {
+                builder.setProtocol(id);
+            }
+            if (cs != null) {
+                builder.setTlsCipherSuite(cs);
+            }
+            sp = builder.build();
+        } catch (IllegalArgumentException e) {
+        }
+        if (nullExpected) {
+            assertNull(sp);
+        } else {
+            assertNotNull(sp);
+        }
+        return sp;
+    }
+
+    private String getRandomString(Random rand) {
+        int size = rand.nextInt(64);
+        byte[] arr = new byte[size];
+        rand.nextBytes(arr);
+        return new String(arr);
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
index e691e51..bf45867 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
@@ -46,6 +46,7 @@
     public static final int ITEM_COMPRESSED = 2001;
     // TODO Replace with a real sip message once that logic is in.
     public static final String TEST_TRANSACTION_ID = "z9hG4bK.TeSt";
+    public static final String TEST_CALL_ID = "testcall";
     public static final SipMessage TEST_SIP_MESSAGE = new SipMessage("A", "B", new byte[0]);
 
     public static boolean shouldTestTelephony() {
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
index 3f786fa..c0f2e6b 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
@@ -832,6 +832,8 @@
         // Send a message and ensure it gets received on the other end as well as acked
         delegateConn.sendMessageAndVerifyCompletedSuccessfully(ImsUtils.TEST_SIP_MESSAGE);
         delegate.verifyMessageSend(ImsUtils.TEST_SIP_MESSAGE);
+        delegateConn.sendCloseDialog(ImsUtils.TEST_CALL_ID);
+        delegate.verifyCloseDialog(ImsUtils.TEST_CALL_ID);
         // send a message and notify connection that it failed
         delegate.setSendMessageDenyReason(
                 SipDelegateManager.MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE);
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
index 3d06dce..729efb9 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
@@ -48,6 +48,7 @@
     // Pair is <transactionId, error reason>
     private final LinkedBlockingQueue<Pair<String, Integer>> mReceivedMessageAcks =
             new LinkedBlockingQueue<>();
+    private final LinkedBlockingQueue<String> mCloseDialogRequests = new LinkedBlockingQueue<>();
     private int mSendMessageDenyReason = -1;
 
     public TestSipDelegate(int sub, DelegateRequest request, DelegateStateCallback cb,
@@ -73,7 +74,7 @@
     @Override
     public void closeDialog(@NonNull String callId) {
         if (ImsUtils.VDBG) Log.d(LOG_TAG, "closeDialog");
-        // TODO: Test once dialogs are tracked in AOSP.
+        mCloseDialogRequests.offer(callId);
     }
 
     @Override
@@ -93,6 +94,12 @@
         assertEquals(messageToVerify, m);
     }
 
+    public void verifyCloseDialog(String callIdToVerify) throws Exception {
+        String requestedCallId = mCloseDialogRequests.poll(ImsUtils.TEST_TIMEOUT_MS,
+                TimeUnit.MILLISECONDS);
+        assertEquals(callIdToVerify, requestedCallId);
+    }
+
     public void setSendMessageDenyReason(int reason) {
         mSendMessageDenyReason = reason;
     }
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java
index 6b3b134..adf4956 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegateConnection.java
@@ -145,6 +145,11 @@
         mLatch.countDown();
     }
 
+    public void sendCloseDialog(String callId) {
+        assertNotNull("SipDelegate was null when closing dialog", connection);
+        connection.closeDialog(callId);
+    }
+
     public void sendMessageAndVerifyCompletedSuccessfully(SipMessage messageToSend)
             throws Exception {
         assertNotNull("SipDelegate was null when sending message", connection);