diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-12-05 10:11:26 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-12-05 10:11:26 +0000 |
commit | 0aa3846b1287a01ce9d7ef472ae1247f0453413f (patch) | |
tree | 94a15036f0e3383f1474922e8b594b7c9c86d7c9 | |
parent | 30ae343e0da34ebd0d57e189e89c30d14444d573 (diff) | |
parent | f95c6d4c1bffea3d03ee516eba01741ac56624a2 (diff) | |
download | cts-aml_sdk_331412000.tar.gz |
Snap for 9368510 from f95c6d4c1bffea3d03ee516eba01741ac56624a2 to mainline-sdkext-releaseaml_sdk_331811100aml_sdk_331412000aml_sdk_331410000
Change-Id: I3d33627f2fbdcad8878c6316eb840b9a3d8ebb0f
174 files changed, 3555 insertions, 3677 deletions
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java index 0b70c8b000c..eab62fe576d 100644 --- a/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java +++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java @@ -33,11 +33,9 @@ import androidx.test.InstrumentationRegistry; import com.android.modules.utils.build.SdkLevel; -import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.util.concurrent.Callable; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; @@ -400,4 +398,18 @@ public class SystemUtil { } } } + + /** + * Use `wait-for-broadcast-barrier` on U+ + * and `wait-for-broadcast-idle` on previous version + */ + public static void waitForBroadcasts() { + String cmd; + if (SdkLevel.isAtLeastU()) { + cmd = "am wait-for-broadcast-barrier"; + } else { + cmd = "am wait-for-broadcast-idle"; + } + runShellCommand(cmd); + } } diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java index 6b1f6fc33b7..a3cec319484 100644 --- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java +++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java @@ -743,7 +743,8 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test { "Lcom/android/sdksandbox/ISdkSandboxService;", "Lcom/android/sdksandbox/SandboxLatencyInfo-IA;", "Lcom/android/sdksandbox/SandboxLatencyInfo;", - "Lcom/android/sdksandbox/IUnloadSdkCallback;" + "Lcom/android/sdksandbox/IUnloadSdkCallback;", + "Lcom/android/sdksandbox/IComputeSdkStorageCallback;" ); private static final ImmutableMap<String, ImmutableSet<String>> FULL_APK_IN_APEX_BURNDOWN = @@ -1044,7 +1045,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test { final Multimap<String, String> bcpOnlyDuplicates = Multimaps.filterKeys(filteredDuplicates, sBootclasspathJars::contains); - if (!filteredDuplicates.isEmpty()) { + if (!bcpOnlyDuplicates.isEmpty()) { synchronized (perApkClasspathDuplicates) { perApkClasspathDuplicates.put(apk, bcpOnlyDuplicates); } diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp index ff1e1226b0b..de8c4e291d6 100644 --- a/hostsidetests/appsecurity/Android.bp +++ b/hostsidetests/appsecurity/Android.bp @@ -32,6 +32,7 @@ java_test_host { "compatibility-host-util", "truth-prebuilt", "hamcrest-library", + "sts-host-util", ], static_libs: [ diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java index e86aa574897..2e182eb8349 100644 --- a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java +++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java @@ -21,7 +21,7 @@ import android.platform.test.annotations.AsbSecurityTest; import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; -import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; +import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase; import static org.junit.Assert.assertNull; import static org.junit.Assume.assumeTrue; @@ -30,7 +30,7 @@ import org.junit.Test; import org.junit.runner.RunWith; @RunWith(DeviceJUnit4ClassRunner.class) -public class RoleSecurityTest extends BaseHostJUnit4Test { +public class RoleSecurityTest extends StsExtraBusinessLogicHostTestBase { private static final String ROLE_SECURITY_TEST_APP_APK = "CtsRoleSecurityTestApp.apk"; private static final String ROLE_SECURITY_TEST_APP_PACKAGE = "com.android.cts.rolesecuritytest"; diff --git a/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml b/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml index 78b59546d39..a55d689dd85 100644 --- a/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml +++ b/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml @@ -19,6 +19,7 @@ android:targetSandboxVersion="2"> <uses-permission android:name="android.permission.RECORD_AUDIO"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-sdk android:minSdkVersion="30"/> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" diff --git a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java index a3fe0a45255..8c91c5bc52d 100644 --- a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java +++ b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java @@ -34,14 +34,23 @@ import android.media.metrics.TranscodingSession; import android.os.Bundle; import android.os.PersistableBundle; import android.provider.DeviceConfig; +import android.util.Log; -import androidx.test.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; import com.android.compatibility.common.util.SystemUtil; import org.junit.Test; +import org.junit.runner.RunWith; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +@RunWith(AndroidJUnit4.class) public class MediaMetricsAtomHostSideTests { + private static final String TAG = "MediaMetricsAtomHostSideTests"; private static final String MEDIA_METRICS_MODE = "media_metrics_mode"; private static final String PLAYER_METRICS_APP_ALLOWLIST = "player_metrics_app_allowlist"; private static final String PLAYER_METRICS_APP_BLOCKLIST = "player_metrics_app_blocklist"; @@ -87,7 +96,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testPlaybackStateEvent_default() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackStateEvent e = @@ -100,7 +109,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testPlaybackStateEvent() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackStateEvent e = @@ -116,7 +125,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testPlaybackErrorEvent_default() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackErrorEvent e = @@ -130,7 +139,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testPlaybackErrorEvent() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackErrorEvent e = @@ -148,7 +157,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testTrackChangeEvent_default() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); TrackChangeEvent e = @@ -160,7 +169,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testTrackChangeEvent_text() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); TrackChangeEvent e = @@ -182,7 +191,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testTrackChangeEvent_audio() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); TrackChangeEvent e = @@ -206,7 +215,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testTrackChangeEvent_video() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); TrackChangeEvent e = @@ -232,7 +241,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testNetworkEvent_default() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); NetworkEvent e = @@ -244,7 +253,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testNetworkEvent() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); NetworkEvent e = @@ -260,7 +269,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testPlaybackMetrics_default() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackMetrics e = @@ -272,7 +281,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testPlaybackMetrics() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackMetrics e = @@ -301,10 +310,10 @@ public class MediaMetricsAtomHostSideTests { @Test public void testSessionId() throws Exception { - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); - try(PlaybackSession s = manager.createPlaybackSession()) { + try (PlaybackSession s = manager.createPlaybackSession()) { LogSessionId idObj = s.getSessionId(); assertThat(idObj).isNotEqualTo(null); assertThat(idObj.getStringId().length()).isGreaterThan(0); @@ -313,10 +322,10 @@ public class MediaMetricsAtomHostSideTests { @Test public void testRecordingSession() throws Exception { - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); - try(RecordingSession s = manager.createRecordingSession()) { + try (RecordingSession s = manager.createRecordingSession()) { assertThat(s).isNotEqualTo(null); LogSessionId idObj = s.getSessionId(); assertThat(idObj).isNotEqualTo(null); @@ -326,7 +335,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testEditingSession() throws Exception { - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); try (EditingSession s = manager.createEditingSession()) { @@ -339,7 +348,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testTranscodingSession() throws Exception { - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); try (TranscodingSession s = manager.createTranscodingSession()) { @@ -352,7 +361,7 @@ public class MediaMetricsAtomHostSideTests { @Test public void testBundleSession() throws Exception { - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); try (BundleSession s = manager.createBundleSession()) { @@ -366,12 +375,12 @@ public class MediaMetricsAtomHostSideTests { @Test public void testBundleSessionPlaybackStateEvent() throws Exception { turnOnForTesting(); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); BundleSession s = manager.createBundleSession(); PersistableBundle b = new PersistableBundle(); b.putInt(BundleSession.KEY_STATSD_ATOM, 322); - // eventually want these keys from within the service side. + // eventually want these keys from within the service side. b.putString("playbackstateevent-sessionid", s.getSessionId().getStringId()); b.putInt("playbackstateevent-state", PlaybackStateEvent.STATE_JOINING_FOREGROUND); b.putLong("playbackstateevent-lifetime", 1763L); @@ -390,7 +399,7 @@ public class MediaMetricsAtomHostSideTests { .build()); }); Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackStateEvent e = @@ -400,6 +409,7 @@ public class MediaMetricsAtomHostSideTests { .setMetricsBundle(new Bundle()) .build(); s.reportPlaybackStateEvent(e); + writeSessionIdToFile(s.getSessionId().getStringId()); resetProperties(); } @@ -414,7 +424,7 @@ public class MediaMetricsAtomHostSideTests { .build()); }); Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackMetrics e = @@ -438,6 +448,7 @@ public class MediaMetricsAtomHostSideTests { .addExperimentId(123) .build(); s.reportPlaybackMetrics(e); + writeSessionIdToFile(s.getSessionId().getStringId()); resetProperties(); } @@ -452,7 +463,7 @@ public class MediaMetricsAtomHostSideTests { .build()); }); Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackStateEvent e = @@ -462,6 +473,7 @@ public class MediaMetricsAtomHostSideTests { .setMetricsBundle(new Bundle()) .build(); s.reportPlaybackStateEvent(e); + writeSessionIdToFile(s.getSessionId().getStringId()); resetProperties(); } @@ -476,7 +488,7 @@ public class MediaMetricsAtomHostSideTests { .build()); }); Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS); - Context context = InstrumentationRegistry.getContext(); + Context context = InstrumentationRegistry.getInstrumentation().getContext(); MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class); PlaybackSession s = manager.createPlaybackSession(); PlaybackMetrics e = @@ -500,6 +512,7 @@ public class MediaMetricsAtomHostSideTests { .addExperimentId(123) .build(); s.reportPlaybackMetrics(e); + writeSessionIdToFile(s.getSessionId().getStringId()); resetProperties(); } @@ -526,4 +539,17 @@ public class MediaMetricsAtomHostSideTests { */ @Test public native void testAAudioLegacyInputStream(); + + private void writeSessionIdToFile(String stringId) throws IOException { + // TODO(b/259258249): Name session id after the test. + Context context = InstrumentationRegistry.getInstrumentation().getContext(); + Log.i(TAG, "log_session_id=" + stringId); + File logDir = context.getExternalFilesDir(null); + File logFile = new File(logDir, "log_session_id.txt"); + logFile.createNewFile(); + FileWriter fw = new FileWriter(logFile.getAbsolutePath()); + fw.write(stringId); + fw.close(); + Log.i(TAG, "Logged to " + logFile.getAbsolutePath()); + } } diff --git a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java index 3e6bbea06e3..fe2ac25be0d 100644 --- a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java +++ b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java @@ -17,6 +17,7 @@ package android.media.metrics.cts; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import android.cts.statsdatom.lib.AtomTestUtils; import android.cts.statsdatom.lib.ConfigUtils; @@ -26,15 +27,21 @@ import android.cts.statsdatom.lib.ReportUtils; import com.android.os.AtomsProto; import com.android.os.StatsLog; import com.android.tradefed.build.IBuildInfo; +import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.testtype.DeviceTestCase; import com.android.tradefed.testtype.IBuildReceiver; +import com.google.common.truth.Correspondence; + import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildReceiver { + private static final String TAG = "MediaMetricsAtomTests"; public static final String TEST_APK = "CtsMediaMetricsHostTestApp.apk"; public static final String TEST_PKG = "android.media.metrics.cts"; private static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output"; @@ -68,9 +75,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testPlaybackStateEvent_default() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackStateEvent_default"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -79,8 +84,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); - AtomsProto.MediaPlaybackStateChanged result = - data.get(0).getAtom().getMediaPlaybackStateChanged(); + AtomsProto.MediaPlaybackStateChanged result = data.get( + 0).getAtom().getMediaPlaybackStateChanged(); assertThat(result.getPlaybackState().toString()).isEqualTo("NOT_STARTED"); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); } @@ -88,9 +93,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testPlaybackStateEvent() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackStateEvent"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -99,8 +102,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); - AtomsProto.MediaPlaybackStateChanged result = - data.get(0).getAtom().getMediaPlaybackStateChanged(); + AtomsProto.MediaPlaybackStateChanged result = data.get( + 0).getAtom().getMediaPlaybackStateChanged(); assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND"); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L); } @@ -109,9 +112,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testBundleSessionPlaybackStateEvent() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSessionPlaybackStateEvent"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -120,8 +121,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); - AtomsProto.MediaPlaybackStateChanged result = - data.get(0).getAtom().getMediaPlaybackStateChanged(); + AtomsProto.MediaPlaybackStateChanged result = data.get( + 0).getAtom().getMediaPlaybackStateChanged(); assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND"); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L); } @@ -130,9 +131,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testPlaybackErrorEvent_default() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackErrorEvent_default"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -141,23 +140,21 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue(); - AtomsProto.MediaPlaybackErrorReported result = - data.get(0).getAtom().getMediaPlaybackErrorReported(); + AtomsProto.MediaPlaybackErrorReported result = data.get( + 0).getAtom().getMediaPlaybackErrorReported(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_UNKNOWN"); assertThat(result.getSubErrorCode()).isEqualTo(0); assertThat(result.getExceptionStack().startsWith( - "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent")) - .isTrue(); + "android.media.metrics.cts.MediaMetricsAtomHostSideTests" + + ".testPlaybackErrorEvent")).isTrue(); } public void testPlaybackErrorEvent() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackErrorEvent"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -166,23 +163,21 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue(); - AtomsProto.MediaPlaybackErrorReported result = - data.get(0).getAtom().getMediaPlaybackErrorReported(); + AtomsProto.MediaPlaybackErrorReported result = data.get( + 0).getAtom().getMediaPlaybackErrorReported(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(17630000L); assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_RUNTIME"); assertThat(result.getSubErrorCode()).isEqualTo(378); assertThat(result.getExceptionStack().startsWith( - "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent")) - .isTrue(); + "android.media.metrics.cts.MediaMetricsAtomHostSideTests" + + ".testPlaybackErrorEvent")).isTrue(); } public void testTrackChangeEvent_default() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testTrackChangeEvent_default"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -191,8 +186,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); - AtomsProto.MediaPlaybackTrackChanged result = - data.get(0).getAtom().getMediaPlaybackTrackChanged(); + AtomsProto.MediaPlaybackTrackChanged result = data.get( + 0).getAtom().getMediaPlaybackTrackChanged(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); assertThat(result.getState().toString()).isEqualTo("OFF"); @@ -211,9 +206,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testTrackChangeEvent_text() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testTrackChangeEvent_text"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -222,8 +215,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); - AtomsProto.MediaPlaybackTrackChanged result = - data.get(0).getAtom().getMediaPlaybackTrackChanged(); + AtomsProto.MediaPlaybackTrackChanged result = data.get( + 0).getAtom().getMediaPlaybackTrackChanged(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L); assertThat(result.getState().toString()).isEqualTo("ON"); @@ -240,9 +233,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testTrackChangeEvent_audio() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testTrackChangeEvent_audio"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -251,8 +242,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); - AtomsProto.MediaPlaybackTrackChanged result = - data.get(0).getAtom().getMediaPlaybackTrackChanged(); + AtomsProto.MediaPlaybackTrackChanged result = data.get( + 0).getAtom().getMediaPlaybackTrackChanged(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L); assertThat(result.getState().toString()).isEqualTo("OFF"); @@ -271,9 +262,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testTrackChangeEvent_video() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testTrackChangeEvent_video"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -282,8 +271,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); - AtomsProto.MediaPlaybackTrackChanged result = - data.get(0).getAtom().getMediaPlaybackTrackChanged(); + AtomsProto.MediaPlaybackTrackChanged result = data.get( + 0).getAtom().getMediaPlaybackTrackChanged(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L); assertThat(result.getState().toString()).isEqualTo("OFF"); @@ -303,9 +292,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testNetworkEvent_default() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent_default"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -314,8 +301,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue(); - AtomsProto.MediaNetworkInfoChanged result = - data.get(0).getAtom().getMediaNetworkInfoChanged(); + AtomsProto.MediaNetworkInfoChanged result = data.get( + 0).getAtom().getMediaNetworkInfoChanged(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_UNKNOWN"); @@ -324,19 +311,16 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testNetworkEvent() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testNetworkEvent"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue(); - AtomsProto.MediaNetworkInfoChanged result = - data.get(0).getAtom().getMediaNetworkInfoChanged(); + AtomsProto.MediaNetworkInfoChanged result = data.get( + 0).getAtom().getMediaNetworkInfoChanged(); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(3032L); assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_WIFI"); @@ -345,9 +329,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testPlaybackMetrics_default() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics_default"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); @@ -357,8 +339,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue(); - AtomsProto.MediametricsPlaybackReported result = - data.get(0).getAtom().getMediametricsPlaybackReported(); + AtomsProto.MediametricsPlaybackReported result = data.get( + 0).getAtom().getMediametricsPlaybackReported(); assertThat(result.getUid()).isEqualTo(appUid); assertThat(result.getMediaDurationMillis()).isEqualTo(-1L); @@ -382,11 +364,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testPlaybackMetrics() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testPlaybackMetrics"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); @@ -394,8 +373,8 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei assertThat(data.size()).isEqualTo(1); assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue(); - AtomsProto.MediametricsPlaybackReported result = - data.get(0).getAtom().getMediametricsPlaybackReported(); + AtomsProto.MediametricsPlaybackReported result = data.get( + 0).getAtom().getMediametricsPlaybackReported(); assertThat(result.getUid()).isEqualTo(appUid); assertThat(result.getMediaDurationMillis()).isEqualTo(233L); @@ -421,104 +400,96 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testSessionId() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testSessionId"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - assertThat(data.size()).isEqualTo(0); + assertThat(data).isEmpty(); } public void testRecordingSession() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testRecordingSession"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - assertThat(data.size()).isEqualTo(0); + assertThat(data).isEmpty(); } public void testEditingSession() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testEditingSession"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - assertThat(data.size()).isEqualTo(0); + assertThat(data).isEmpty(); } public void testTranscodingSession() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testTranscodingSession"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - assertThat(data.size()).isEqualTo(0); + assertThat(data).isEmpty(); } public void testBundleSession() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testBundleSession"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - assertThat(data.size()).isEqualTo(0); + assertThat(data).isEmpty(); } public void testAppBlocklist() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testAppBlocklist"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); + String logSessionId = getLogSessionId(); + assertWithMessage("log session id").that(logSessionId).isNotEmpty(); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - - assertThat(data.size()).isEqualTo(0); + List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data, + AtomsProto.Atom::getMediametricsPlaybackReported); + assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming( + AtomsProto.MediametricsPlaybackReported::getLogSessionId, + "getLogSessionId")).doesNotContain(logSessionId); } + public void testAttributionBlocklist() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAttributionBlocklist"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); + String logSessionId = getLogSessionId(); + assertWithMessage("log session id").that(logSessionId).isNotEmpty(); + List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data, + AtomsProto.Atom::getMediametricsPlaybackReported); + assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming( + AtomsProto.MediametricsPlaybackReported::getLogSessionId, + "getLogSessionId")).contains(logSessionId); - assertThat(data.size()).isEqualTo(1); - assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue(); - AtomsProto.MediametricsPlaybackReported result = - data.get(0).getAtom().getMediametricsPlaybackReported(); + AtomsProto.MediametricsPlaybackReported result = playbackReportedList.stream().filter( + a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow(); assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0. assertThat(result.getMediaDurationMillis()).isEqualTo(233L); @@ -540,19 +511,21 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testAppAllowlist() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - "testAppAllowlist"); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppAllowlist"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); - - assertThat(data.size()).isEqualTo(1); - assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); - AtomsProto.MediaPlaybackStateChanged result = - data.get(0).getAtom().getMediaPlaybackStateChanged(); + String logSessionId = getLogSessionId(); + assertWithMessage("log session id").that(logSessionId).isNotEmpty(); + List<AtomsProto.MediaPlaybackStateChanged> stateChangedList = toMyAtoms(data, + AtomsProto.Atom::getMediaPlaybackStateChanged); + assertThat(stateChangedList).comparingElementsUsing( + Correspondence.transforming(AtomsProto.MediaPlaybackStateChanged::getLogSessionId, + "getLogSessionId")).contains(logSessionId); + + AtomsProto.MediaPlaybackStateChanged result = stateChangedList.stream().filter( + a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow(); assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND"); assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L); } @@ -560,19 +533,22 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei public void testAttributionAllowlist() throws Exception { ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAttributionAllowlist"); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); + String logSessionId = getLogSessionId(); + assertWithMessage("log session id").that(logSessionId).isNotEmpty(); + List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data, + AtomsProto.Atom::getMediametricsPlaybackReported); + assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming( + AtomsProto.MediametricsPlaybackReported::getLogSessionId, + "getLogSessionId")).contains(logSessionId); - assertThat(data.size()).isEqualTo(1); - assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue(); - AtomsProto.MediametricsPlaybackReported result = - data.get(0).getAtom().getMediametricsPlaybackReported(); + AtomsProto.MediametricsPlaybackReported result = playbackReportedList.stream().filter( + a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow(); assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0. assertThat(result.getMediaDurationMillis()).isEqualTo(233L); @@ -611,19 +587,16 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei } } - private void runAAudioTestAndValidate( - String requiredFeature, int direction, String testFunctionName) throws Exception { + private void runAAudioTestAndValidate(String requiredFeature, int direction, + String testFunctionName) throws Exception { if (!DeviceUtils.hasFeature(getDevice(), requiredFeature)) { return; } ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, AtomsProto.Atom.MEDIAMETRICS_AAUDIOSTREAM_REPORTED_FIELD_NUMBER); - DeviceUtils.runDeviceTests( - getDevice(), - TEST_PKG, - "android.media.metrics.cts.MediaMetricsAtomHostSideTests", - testFunctionName); + DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, + "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName); Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); validateAAudioStreamAtom(direction); @@ -636,8 +609,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei * the data is collected correctly. */ public void testAAudioLowLatencyInputStream() throws Exception { - runAAudioTestAndValidate( - FEATURE_MICROPHONE, + runAAudioTestAndValidate(FEATURE_MICROPHONE, AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE, "testAAudioLowLatencyInputStream"); } @@ -649,8 +621,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei * the data is collected correctly. */ public void testAAudioLowLatencyOutputStream() throws Exception { - runAAudioTestAndValidate( - FEATURE_AUDIO_OUTPUT, + runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT, AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE, "testAAudioLowLatencyOutputStream"); } @@ -662,8 +633,7 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei * the data is collected correctly. */ public void testAAudioLegacyInputStream() throws Exception { - runAAudioTestAndValidate( - FEATURE_MICROPHONE, + runAAudioTestAndValidate(FEATURE_MICROPHONE, AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE, "testAAudioLegacyInputStream"); } @@ -675,9 +645,22 @@ public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildRecei * the data is collected correctly. */ public void testAAudioLegacyOutputStream() throws Exception { - runAAudioTestAndValidate( - FEATURE_AUDIO_OUTPUT, + runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT, AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE, "testAAudioLegacyOutputStream"); } + + private String getLogSessionId() throws DeviceNotAvailableException { + // TODO(b/259258249): Name session id file after the test. + String logSessionId = getDevice().pullFileContents( + "/storage/emulated/0/Android/data/android.media.metrics" + + ".cts/files/log_session_id" + ".txt"); + return logSessionId; + } + + private static <T> List<T> toMyAtoms(List<StatsLog.EventMetricData> data, + Function<AtomsProto.Atom, T> mapper) { + return data.stream().map(StatsLog.EventMetricData::getAtom).map(mapper).collect( + Collectors.toUnmodifiableList()); + } } diff --git a/hostsidetests/multidevices/uwb/Android.bp b/hostsidetests/multidevices/uwb/Android.bp deleted file mode 100644 index cee671ab1ed..00000000000 --- a/hostsidetests/multidevices/uwb/Android.bp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2022 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 { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -python_test_host { - name: "CtsUwbMultiDeviceTestCases", - main: "uwb_manager_test.py", - srcs: ["uwb_manager_test.py"], - test_suites: [ - "cts", - "general-tests", - ], - test_options: { - unit_test: false, - }, - data: [ - // Package the snippet with the mobly test - ":uwb_snippet", - ], -} diff --git a/hostsidetests/multidevices/uwb/AndroidTest.xml b/hostsidetests/multidevices/uwb/AndroidTest.xml deleted file mode 100644 index d230b3a3bae..00000000000 --- a/hostsidetests/multidevices/uwb/AndroidTest.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2022 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. ---> -<configuration description="Config for CTS Uwb multi-device test cases"> - <option name="test-suite-tag" value="cts" /> - <option name="config-descriptor:metadata" key="component" value="uwb" /> - <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" /> - <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> - <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" /> - - <object class="com.android.tradefed.testtype.suite.module.DeviceFeatureModuleController" - type="module_controller"> - <option name="required-feature" value="android.hardware.uwb" /> - </object> - - <device name="device1"> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="test-file-name" value="uwb_snippet.apk" /> - </target_preparer> - <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> - <option name="run-command" value="input keyevent KEYCODE_WAKEUP" /> - <option name="run-command" value="wm dismiss-keyguard" /> - </target_preparer> - <!-- Any python dependencies can be specified and will be installed with pip --> - <!-- TODO(b/225958696): Import python dependencies --> - <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer"> - <option name="dep-module" value="mobly" /> - </target_preparer> - --> - </device> - <device name="device2"> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="test-file-name" value="uwb_snippet.apk" /> - </target_preparer> - <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> - <option name="run-command" value="input keyevent KEYCODE_WAKEUP" /> - <option name="run-command" value="wm dismiss-keyguard" /> - </target_preparer> - </device> - - <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest"> - <!-- The mobly-par-file-name should match the module name --> - <option name="mobly-par-file-name" value="CtsUwbMultiDeviceTestCases" /> - <!-- Timeout limit in milliseconds for all test cases of the python binary --> - <option name="mobly-test-timeout" value="60000" /> - </test> -</configuration> - diff --git a/hostsidetests/multidevices/uwb/OWNERS b/hostsidetests/multidevices/uwb/OWNERS deleted file mode 100644 index ea05fdf0f48..00000000000 --- a/hostsidetests/multidevices/uwb/OWNERS +++ /dev/null @@ -1,7 +0,0 @@ -# Bug component: 33618 -include platform/packages/modules/Uwb:/OWNERS - -# Engprod - Not owner of the test but help maintaining the module as an example -jdesprez@google.com -frankfeng@google.com -murj@google.com diff --git a/hostsidetests/multidevices/uwb/snippet/AndroidManifest.xml b/hostsidetests/multidevices/uwb/snippet/AndroidManifest.xml deleted file mode 100644 index 6b28be9b461..00000000000 --- a/hostsidetests/multidevices/uwb/snippet/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.google.snippet.uwb"> - - <uses-permission android:name="android.permissions.UWB_PRIVILEGED" /> - <uses-permission android:name="android.permission.UWB_RANGING" /> - - <application> - <!-- Add any classes that implement the Snippet interface as meta-data, whose - value is a comma-separated string, each section being the package path - of a snippet class --> - <meta-data - android:name="mobly-snippets" - android:value="com.google.snippet.uwb.UwbManagerSnippet" /> - </application> - <!-- Add an instrumentation tag so that the app can be launched through an - instrument command. The runner `com.google.android.mobly.snippet.SnippetRunner` - is derived from `AndroidJUnitRunner`, and is required to use the - Mobly Snippet Lib. --> - <instrumentation - android:name="com.google.android.mobly.snippet.SnippetRunner" - android:targetPackage="com.google.snippet.uwb" /> -</manifest> diff --git a/hostsidetests/multidevices/uwb/snippet/UwbManagerSnippet.java b/hostsidetests/multidevices/uwb/snippet/UwbManagerSnippet.java deleted file mode 100644 index 484d8cbd2b0..00000000000 --- a/hostsidetests/multidevices/uwb/snippet/UwbManagerSnippet.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2022 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 com.google.snippet.uwb; - -import android.app.UiAutomation; -import android.content.Context; -import android.uwb.UwbManager; - -import androidx.test.platform.app.InstrumentationRegistry; - -import com.google.android.mobly.snippet.Snippet; -import com.google.android.mobly.snippet.rpc.Rpc; -import com.google.android.mobly.snippet.util.Log; - -import java.lang.reflect.Method; - -/** Snippet class exposing Android APIs for Uwb. */ -public class UwbManagerSnippet implements Snippet { - private static class UwbManagerSnippetException extends Exception { - private static final long serialVersionUID = 1; - - UwbManagerSnippetException(String msg) { - super(msg); - } - - UwbManagerSnippetException(String msg, Throwable err) { - super(msg, err); - } - } - private final UwbManager mUwbManager; - private final Context mContext; - - public UwbManagerSnippet() throws Throwable { - mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - mUwbManager = mContext.getSystemService(UwbManager.class); - adoptShellPermission(); - } - - /** Get the UWB state. */ - @Rpc(description = "Get Uwb state") - public boolean isUwbEnabled() { - return mUwbManager.isUwbEnabled(); - } - - /** Get the UWB state. */ - @Rpc(description = "Set Uwb state") - public void setUwbEnabled(boolean enabled) { - mUwbManager.setUwbEnabled(enabled); - } - - @Override - public void shutdown() {} - - private void adoptShellPermission() throws Throwable { - UiAutomation uia = InstrumentationRegistry.getInstrumentation().getUiAutomation(); - uia.adoptShellPermissionIdentity(); - try { - Class<?> cls = Class.forName("android.app.UiAutomation"); - Method destroyMethod = cls.getDeclaredMethod("destroy"); - destroyMethod.invoke(uia); - } catch (ReflectiveOperationException e) { - throw new UwbManagerSnippetException("Failed to cleaup Ui Automation", e); - } - } -} diff --git a/hostsidetests/multidevices/uwb/uwb_manager_test.py b/hostsidetests/multidevices/uwb/uwb_manager_test.py deleted file mode 100644 index abff6166895..00000000000 --- a/hostsidetests/multidevices/uwb/uwb_manager_test.py +++ /dev/null @@ -1,73 +0,0 @@ -# Lint as: python3 -"""Porting UWB tests from mobly.""" -import sys -import time - -import logging -logging.basicConfig(filename="/tmp/uwb_test_log.txt", level=logging.INFO) - -from mobly import asserts -from mobly import base_test -from mobly import test_runner -from mobly import utils -from mobly.controllers import android_device -from pprint import pprint - -UWB_SNIPPET_PACKAGE = 'com.google.snippet.uwb' - -class UwbManagerTest(base_test.BaseTestClass): - - def setup_class(self): - # Declare that two Android devices are needed. - self.initiator, self.responder = self.register_controller( - android_device, min_number=2) - - def setup_device(device): - # Expect uwb apk to be installed as it is configured to install - # with the module configuration AndroidTest.xml on both devices. - device.adb.shell([ - 'pm', 'grant', UWB_SNIPPET_PACKAGE, - 'android.permission.UWB_RANGING' - ]) - device.load_snippet('uwb_snippet', UWB_SNIPPET_PACKAGE) - - # Sets up devices in parallel to save time. - utils.concurrent_exec( - setup_device, ((self.initiator,), (self.responder,)), - max_workers=2, - raise_on_exception=True) - - - def test_default_uwb_state(self): - """Verifies default UWB state is On after flashing the device.""" - asserts.assert_true(self.initiator.uwb_snippet.isUwbEnabled(), - "UWB state: Off; Expected: On.") - asserts.assert_true(self.responder.uwb_snippet.isUwbEnabled(), - "UWB state: Off; Expected: On.") - - def test_uwb_toggle(self): - """Verifies UWB toggle on/off """ - self.initiator.uwb_snippet.setUwbEnabled(False) - self.responder.uwb_snippet.setUwbEnabled(False) - # TODO: Use callback to wait for toggle off completion. - time.sleep(5) - asserts.assert_false(self.initiator.uwb_snippet.isUwbEnabled(), - "UWB state: Off; Expected: On.") - asserts.assert_false(self.responder.uwb_snippet.isUwbEnabled(), - "UWB state: Off; Expected: On.") - - self.initiator.uwb_snippet.setUwbEnabled(True) - self.responder.uwb_snippet.setUwbEnabled(True) - # TODO: Use callback to wait for toggle off completion. - time.sleep(5) - asserts.assert_true(self.initiator.uwb_snippet.isUwbEnabled(), - "UWB state: Off; Expected: On.") - asserts.assert_true(self.responder.uwb_snippet.isUwbEnabled(), - "UWB state: Off; Expected: On.") - -if __name__ == '__main__': - # Take test args - index = sys.argv.index('--') - sys.argv = sys.argv[:1] + sys.argv[index + 1:] - - test_runner.main() diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp index 1aafea389e8..cea0ad032dd 100644 --- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp +++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 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. @@ -18,49 +18,37 @@ #include <media/mediaplayer.h> #include "../includes/common.h" -#define PREPARE_DRM 39 - using namespace android; int main() { + constexpr size_t bufferSize = 16; + constexpr uint32_t prepareDrm = 39; + constexpr uint32_t unknownTrxnCode = prepareDrm + 5; sp<IServiceManager> serviceManager = defaultServiceManager(); - if (serviceManager == nullptr) { - return EXIT_FAILURE; - } + FAIL_CHECK(serviceManager != nullptr); sp<IBinder> mediaPlayerService = serviceManager->getService(String16("media.player")); - if (mediaPlayerService == nullptr) { - return EXIT_FAILURE; - } + FAIL_CHECK(mediaPlayerService != nullptr); sp<IMediaPlayerService> iMediaPlayerService = IMediaPlayerService::asInterface(mediaPlayerService); - if (iMediaPlayerService == nullptr) { - return EXIT_FAILURE; - } + FAIL_CHECK(iMediaPlayerService != nullptr); - MediaPlayer *mediaPlayer = new MediaPlayer(); - if (mediaPlayer == nullptr) { - return EXIT_FAILURE; - } + sp<MediaPlayer> mediaPlayer = new MediaPlayer(); + FAIL_CHECK(mediaPlayer != nullptr); sp<IMediaPlayer> iMediaPlayer = iMediaPlayerService->create(mediaPlayer); - if (iMediaPlayer == nullptr) { - delete (mediaPlayer); - return EXIT_FAILURE; - } + FAIL_CHECK(iMediaPlayer != nullptr); Parcel data, reply; data.writeInterfaceToken(iMediaPlayer->getInterfaceDescriptor()); - const uint8_t arr[16] = {}; - data.write(arr, 16); - data.writeUint32(2); - data.writeUnpadded(arr, 1); - - IMediaPlayer::asBinder(iMediaPlayer)->transact(PREPARE_DRM, data, &reply); - uint32_t size = 0; - reply.readUint32(&size); - - delete (mediaPlayer); - return (size > 0) ? EXIT_VULNERABLE : EXIT_SUCCESS; + status_t status = IMediaPlayer::asBinder(iMediaPlayer)->transact(unknownTrxnCode, data, &reply); + FAIL_CHECK(status == UNKNOWN_TRANSACTION); + + const uint8_t arr[bufferSize] = {}; + data.write(arr, bufferSize); + data.writeUint32(bufferSize); + data.writeUnpadded(arr, bufferSize - 1); + status = IMediaPlayer::asBinder(iMediaPlayer)->transact(prepareDrm, data, &reply); + return status == OK ? EXIT_VULNERABLE : EXIT_SUCCESS; } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java index bea2bd82ce4..53d4a93f118 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java @@ -18,10 +18,8 @@ package android.security.cts; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; -import com.android.compatibility.common.util.CrashUtils; import com.android.compatibility.common.util.MetricsReportLog; import com.android.compatibility.common.util.ResultType; import com.android.compatibility.common.util.ResultUnit; @@ -29,14 +27,11 @@ import com.android.ddmlib.CollectingOutputReceiver; import com.android.ddmlib.IShellOutputReceiver; import com.android.ddmlib.NullOutputReceiver; import com.android.sts.common.tradefed.testtype.SecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; import com.android.tradefed.log.LogUtil.CLog; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -63,15 +58,18 @@ public class AdbUtils { final static Pattern regexSpecialCharsEscapedPattern = Pattern.compile("[" + regexSpecialCharsEscaped + "]"); + /** + * @deprecated Use {@link NativePoc} instead. + */ + @Deprecated public static class pocConfig { String binaryName; String arguments; Map<String, String> envVars; String inputFilesDestination; ITestDevice device; - CrashUtils.Config config; + TombstoneUtils.Config config; List<String> inputFiles = Collections.emptyList(); - boolean checkCrash = true; pocConfig(String binaryName, ITestDevice device) { this.binaryName = binaryName; @@ -79,12 +77,15 @@ public class AdbUtils { } } - /** Runs a commandline on the specified device + /** + * Runs a commandline on the specified device * + * @deprecated Use {@link CommandUtil} instead. * @param command the command to be ran * @param device device for the command to be ran on * @return the console output from running the command */ + @Deprecated public static String runCommandLine(String command, ITestDevice device) throws Exception { if ("reboot".equals(command)) { throw new IllegalArgumentException( @@ -96,10 +97,12 @@ public class AdbUtils { /** * Pushes and runs a binary to the selected device * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @return the console output from the binary */ + @Deprecated public static String runPoc(String pocName, ITestDevice device) throws Exception { return runPoc(pocName, device, SecurityTestCase.TIMEOUT_NONDETERMINISTIC); } @@ -107,11 +110,13 @@ public class AdbUtils { /** * Pushes and runs a binary to the selected device * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @param timeout time to wait for output in seconds * @return the console output from the binary */ + @Deprecated public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception { return runPoc(pocName, device, timeout, null); } @@ -119,12 +124,14 @@ public class AdbUtils { /** * Pushes and runs a binary to the selected device * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @param timeout time to wait for output in seconds * @param arguments the input arguments for the poc * @return the console output from the binary */ + @Deprecated public static String runPoc(String pocName, ITestDevice device, int timeout, String arguments) throws Exception { CollectingOutputReceiver receiver = new CollectingOutputReceiver(); @@ -135,48 +142,57 @@ public class AdbUtils { /** * Pushes and runs a binary to the selected device and ignores any of its output. * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @param timeout time to wait for output in seconds */ + @Deprecated public static void runPocNoOutput(String pocName, ITestDevice device, int timeout) throws Exception { runPocNoOutput(pocName, device, timeout, null); } /** - * Pushes and runs a binary with arguments to the selected device and - * ignores any of its output. + * Pushes and runs a binary with arguments to the selected device and ignores any of its output. * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @param timeout time to wait for output in seconds * @param arguments input arguments for the poc */ - public static void runPocNoOutput(String pocName, ITestDevice device, int timeout, - String arguments) throws Exception { + @Deprecated + public static void runPocNoOutput( + String pocName, ITestDevice device, int timeout, String arguments) throws Exception { runPoc(pocName, device, timeout, arguments, null); } /** - * Pushes and runs a binary with arguments to the selected device and - * ignores any of its output. + * Pushes and runs a binary with arguments to the selected device and ignores any of its output. * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @param timeout time to wait for output in seconds * @param arguments input arguments for the poc * @param receiver the type of receiver to run against */ - public static int runPoc(String pocName, ITestDevice device, int timeout, - String arguments, IShellOutputReceiver receiver) throws Exception { + @Deprecated + public static int runPoc( + String pocName, + ITestDevice device, + int timeout, + String arguments, + IShellOutputReceiver receiver) + throws Exception { return runPoc(pocName, device, timeout, arguments, null, receiver); } /** - * Pushes and runs a binary with arguments to the selected device and - * ignores any of its output. + * Pushes and runs a binary with arguments to the selected device and ignores any of its output. * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on * @param timeout time to wait for output in seconds @@ -184,9 +200,15 @@ public class AdbUtils { * @param envVars run the poc with environment variables * @param receiver the type of receiver to run against */ - public static int runPoc(String pocName, ITestDevice device, int timeout, - String arguments, Map<String, String> envVars, - IShellOutputReceiver receiver) throws Exception { + @Deprecated + public static int runPoc( + String pocName, + ITestDevice device, + int timeout, + String arguments, + Map<String, String> envVars, + IShellOutputReceiver receiver) + throws Exception { String remoteFile = String.format("%s%s", TMP_PATH, pocName); SecurityTestCase.getPocPusher(device).pushFile(pocName + "_sts", remoteFile); @@ -242,9 +264,12 @@ public class AdbUtils { /** * Assert the poc is executable + * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param device device to be ran on */ + @Deprecated private static void assertPocExecutable(String pocName, ITestDevice device) throws Exception { String fullPocPath = TMP_PATH + pocName; device.executeShellCommand("chmod 777 " + fullPocPath); @@ -351,7 +376,10 @@ public class AdbUtils { } /** * Utility function to help check the exit code of a shell command + * + * @deprecated Use {@link CommandUtil} instead. */ + @Deprecated public static int runCommandGetExitCode(String cmd, ITestDevice device) throws Exception { long time = System.currentTimeMillis(); String exitStatusString = runCommandLine( @@ -373,16 +401,17 @@ public class AdbUtils { } /** - * Pushes and runs a binary to the selected device and checks exit code - * Return code 113 is used to indicate the vulnerability + * Pushes and runs a binary to the selected device and checks exit code Return code 113 is used + * to indicate the vulnerability * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param device device to be ran on * @param timeout time to wait for output in seconds */ @Deprecated - public static boolean runPocCheckExitCode(String pocName, ITestDevice device, - int timeout) throws Exception { + public static boolean runPocCheckExitCode(String pocName, ITestDevice device, int timeout) + throws Exception { //Refer to go/asdl-sts-guide Test section for knowing the significance of 113 code return runPocGetExitStatus(pocName, device, timeout) == 113; @@ -390,11 +419,13 @@ public class AdbUtils { /** * Pushes and runs a binary to the device and returns the exit status. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param device device to be ran on * @param timeout time to wait for output in seconds - */ + @Deprecated public static int runPocGetExitStatus(String pocName, ITestDevice device, int timeout) throws Exception { return runPocGetExitStatus(pocName, null, device, timeout); @@ -402,36 +433,49 @@ public class AdbUtils { /** * Pushes and runs a binary to the device and returns the exit status. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param arguments input arguments for the poc * @param device device to be ran on * @param timeout time to wait for output in seconds */ - public static int runPocGetExitStatus(String pocName, String arguments, ITestDevice device, - int timeout) throws Exception { + @Deprecated + public static int runPocGetExitStatus( + String pocName, String arguments, ITestDevice device, int timeout) throws Exception { return runPocGetExitStatus(pocName, arguments, null, device, timeout); } /** * Pushes and runs a binary to the device and returns the exit status. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param arguments input arguments for the poc * @param envVars run the poc with environment variables * @param device device to be run on * @param timeout time to wait for output in seconds */ + @Deprecated public static int runPocGetExitStatus( - String pocName, String arguments, Map<String, String> envVars, - ITestDevice device, int timeout) throws Exception { + String pocName, + String arguments, + Map<String, String> envVars, + ITestDevice device, + int timeout) + throws Exception { return runPoc(pocName, device, timeout, arguments, envVars, null); } /** * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param device device to be ran on * @param timeout time to wait for output in seconds */ + @Deprecated public static void runPocAssertExitStatusNotVulnerable( String pocName, ITestDevice device, int timeout) throws Exception { runPocAssertExitStatusNotVulnerable(pocName, null, device, timeout); @@ -439,27 +483,37 @@ public class AdbUtils { /** * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param arguments input arguments for the poc * @param device device to be ran on * @param timeout time to wait for output in seconds */ - public static void runPocAssertExitStatusNotVulnerable(String pocName, String arguments, - ITestDevice device, int timeout) throws Exception { + @Deprecated + public static void runPocAssertExitStatusNotVulnerable( + String pocName, String arguments, ITestDevice device, int timeout) throws Exception { runPocAssertExitStatusNotVulnerable(pocName, arguments, null, device, timeout); } /** * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName name of the poc binary * @param arguments input arguments for the poc * @param envVars run the poc with environment variables * @param device device to be ran on * @param timeout time to wait for output in seconds */ + @Deprecated public static void runPocAssertExitStatusNotVulnerable( - String pocName, String arguments, Map<String, String> envVars, - ITestDevice device, int timeout) throws Exception { + String pocName, + String arguments, + Map<String, String> envVars, + ITestDevice device, + int timeout) + throws Exception { assertTrue("PoC returned exit status 113: vulnerable", runPocGetExitStatus(pocName, arguments, envVars, device, timeout) != 113); } @@ -467,136 +521,164 @@ public class AdbUtils { /** * Runs the poc binary and asserts that there are no security crashes that match the expected * process pattern. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param device device to be ran on * @param processPatternStrings a Pattern string to match the crash tombstone process */ - public static void runPocAssertNoCrashes(String pocName, ITestDevice device, - String... processPatternStrings) throws Exception { + @Deprecated + public static void runPocAssertNoCrashes( + String pocName, ITestDevice device, String... processPatternStrings) throws Exception { runPocAssertNoCrashes(pocName, device, - new CrashUtils.Config().setProcessPatterns(processPatternStrings)); + new TombstoneUtils.Config().setProcessPatterns(processPatternStrings)); } /** * Runs the poc binary and asserts that there are no security crashes that match the expected * process pattern. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param device device to be ran on * @param config a crash parser configuration */ - public static void runPocAssertNoCrashes(String pocName, ITestDevice device, - CrashUtils.Config config) throws Exception { + @Deprecated + public static void runPocAssertNoCrashes( + String pocName, ITestDevice device, TombstoneUtils.Config config) throws Exception { runPocAssertNoCrashes(pocName, device, null, config); } /** * Runs the poc binary and asserts that there are no security crashes that match the expected * process pattern, including arguments when running. + * + * @deprecated Use {@link NativePoc} instead. * @param pocName a string path to poc from the /res folder * @param device device to be ran on * @param arguments input arguments for the poc * @param config a crash parser configuration */ - public static void runPocAssertNoCrashes(String pocName, ITestDevice device, String arguments, - CrashUtils.Config config) throws Exception { - AdbUtils.runCommandLine("logcat -c", device); - AdbUtils.runPocNoOutput(pocName, device, - SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments); - assertNoCrashes(device, config); + @Deprecated + public static void runPocAssertNoCrashes( + String pocName, ITestDevice device, String arguments, TombstoneUtils.Config config) + throws Exception { + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(device, config)) { + AdbUtils.runPocNoOutput(pocName, device, + SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments); + } } /** - * Runs the poc binary and asserts following 2 conditions. - * 1. There are no security crashes in the binary. - * 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). + * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in + * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability + * condition). * + * @deprecated Use {@link NativePoc} instead. * @param binaryName name of the binary * @param arguments arguments for running the binary * @param device device to be run on */ - public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments, - ITestDevice device) throws Exception { + @Deprecated + public static void runPocAssertNoCrashesNotVulnerable( + String binaryName, String arguments, ITestDevice device) throws Exception { runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device, null); } /** - * Runs the poc binary and asserts following 2 conditions. - * 1. There are no security crashes in the binary. - * 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). + * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in + * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability + * condition). * + * @deprecated Use {@link NativePoc} instead. * @param binaryName name of the binary * @param arguments arguments for running the binary * @param device device to be run on - * @param processPatternStrings a Pattern string to match the crash tombstone - * process + * @param processPatternStrings a Pattern string to match the crash tombstone process */ - public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments, - ITestDevice device, String processPatternStrings[]) throws Exception { + @Deprecated + public static void runPocAssertNoCrashesNotVulnerable( + String binaryName, String arguments, ITestDevice device, String processPatternStrings[]) + throws Exception { runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device, processPatternStrings); } /** - * Runs the poc binary and asserts following 2 conditions. - * 1. There are no security crashes in the binary. - * 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). + * Runs the poc binary and asserts following 2 conditions. 1. There are no security crashes in + * the binary. 2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability + * condition). * + * @deprecated Use {@link NativePoc} instead. * @param binaryName name of the binary * @param arguments arguments for running the binary * @param inputFiles files required as input - * @param inputFilesDestination destination directory to which input files are - * pushed + * @param inputFilesDestination destination directory to which input files are pushed * @param device device to be run on */ - public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments, - String inputFiles[], String inputFilesDestination, ITestDevice device) + @Deprecated + public static void runPocAssertNoCrashesNotVulnerable( + String binaryName, + String arguments, + String inputFiles[], + String inputFilesDestination, + ITestDevice device) throws Exception { runPocAssertNoCrashesNotVulnerable(binaryName, arguments, inputFiles, inputFilesDestination, device, null); } /** - * Runs the poc binary and asserts following 3 conditions. - * 1. There are no security crashes in the binary. - * 2. There are no security crashes that match the expected process pattern. - * 3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). + * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in + * the binary. 2. There are no security crashes that match the expected process pattern. 3. The + * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). * + * @deprecated Use {@link NativePoc} instead. * @param binaryName name of the binary * @param arguments arguments for running the binary * @param inputFiles files required as input - * @param inputFilesDestination destination directory to which input files are - * pushed + * @param inputFilesDestination destination directory to which input files are pushed * @param device device to be run on - * @param processPatternStrings a Pattern string to match the crash tombstone - * process + * @param processPatternStrings a Pattern string to match the crash tombstone process */ - public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments, - String inputFiles[], String inputFilesDestination, ITestDevice device, - String processPatternStrings[]) throws Exception { + @Deprecated + public static void runPocAssertNoCrashesNotVulnerable( + String binaryName, + String arguments, + String inputFiles[], + String inputFilesDestination, + ITestDevice device, + String processPatternStrings[]) + throws Exception { runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, inputFiles, inputFilesDestination, device, processPatternStrings); } /** - * Runs the poc binary and asserts following 3 conditions. - * 1. There are no security crashes in the binary. - * 2. There are no security crashes that match the expected process pattern. - * 3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). + * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in + * the binary. 2. There are no security crashes that match the expected process pattern. 3. The + * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). * + * @deprecated Use {@link NativePoc} instead. * @param binaryName name of the binary * @param arguments arguments for running the binary * @param envVars run the poc with environment variables * @param inputFiles files required as input - * @param inputFilesDestination destination directory to which input files are - * pushed + * @param inputFilesDestination destination directory to which input files are pushed * @param device device to be run on * @param processPatternStrings a Pattern string (other than binary name) to match the crash - * tombstone process + * tombstone process */ + @Deprecated public static void runPocAssertNoCrashesNotVulnerable( - String binaryName, String arguments, Map<String, String> envVars, - String inputFiles[], String inputFilesDestination, ITestDevice device, - String... processPatternStrings) throws Exception { + String binaryName, + String arguments, + Map<String, String> envVars, + String inputFiles[], + String inputFilesDestination, + ITestDevice device, + String... processPatternStrings) + throws Exception { pocConfig testConfig = new pocConfig(binaryName, device); testConfig.arguments = arguments; testConfig.envVars = envVars; @@ -614,27 +696,28 @@ public class AdbUtils { String[] processPatternStringsWithSelf = new String[processPatternList.size()]; processPatternList.toArray(processPatternStringsWithSelf); testConfig.config = - new CrashUtils.Config().setProcessPatterns(processPatternStringsWithSelf); + new TombstoneUtils.Config().setProcessPatterns(processPatternStringsWithSelf); runPocAssertNoCrashesNotVulnerable(testConfig); } /** - * Runs the poc binary and asserts following 3 conditions. - * 1. There are no security crashes in the binary. - * 2. There are no security crashes that match the expected process pattern. - * 3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). + * Runs the poc binary and asserts following 3 conditions. 1. There are no security crashes in + * the binary. 2. There are no security crashes that match the expected process pattern. 3. The + * exit status isn't 113 (Code 113 is used to indicate the vulnerability condition). * + * @deprecated Use {@link NativePoc} instead. * @param testConfig test configuration */ + @Deprecated public static void runPocAssertNoCrashesNotVulnerable(pocConfig testConfig) throws Exception { String[] inputFiles = null; if(!testConfig.inputFiles.isEmpty()) { inputFiles = testConfig.inputFiles.toArray(new String[testConfig.inputFiles.size()]); pushResources(inputFiles, testConfig.inputFilesDestination, testConfig.device); } - runCommandLine("logcat -c", testConfig.device); - try { + try (AutoCloseable a = + TombstoneUtils.withAssertNoSecurityCrashes(testConfig.device, testConfig.config)) { runPocAssertExitStatusNotVulnerable(testConfig.binaryName, testConfig.arguments, testConfig.envVars, testConfig.device, TIMEOUT_SEC); } catch (IllegalArgumentException e) { @@ -650,63 +733,6 @@ public class AdbUtils { removeResources(inputFiles, testConfig.inputFilesDestination, testConfig.device); } } - if(testConfig.checkCrash) { - if (testConfig.config == null) { - testConfig.config = new CrashUtils.Config(); - } - assertNoCrashes(testConfig.device, testConfig.config); - } - } - - /** - * Dumps logcat and asserts that there are no security crashes that match the expected process. - * By default, checks min crash addresses - * pattern. Ensure that adb logcat -c is called beforehand. - * @param device device to be ran on - * @param processPatternStrings a Pattern string to match the crash tombstone process - */ - public static void assertNoCrashes(ITestDevice device, String... processPatternStrings) - throws Exception { - assertNoCrashes(device, new CrashUtils.Config().setProcessPatterns(processPatternStrings)); - } - - /** - * Dumps logcat and asserts that there are no security crashes that match the expected process - * pattern. Ensure that adb logcat -c is called beforehand. - * @param device device to be ran on - * @param config a crash parser configuration - */ - public static void assertNoCrashes(ITestDevice device, - CrashUtils.Config config) throws Exception { - String logcat = AdbUtils.runCommandLine("logcat -d *:S DEBUG:V", device); - - JSONArray crashes = CrashUtils.addAllCrashes(logcat, new JSONArray()); - JSONArray securityCrashes = CrashUtils.matchSecurityCrashes(crashes, config); - - MetricsReportLog reportLog = SecurityTestCase.buildMetricsReportLog(device); - reportLog.addValue("all_crashes", crashes.toString(), ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue("security_crashes", securityCrashes.toString(), - ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.submit(); - - if (securityCrashes.length() == 0) { - return; // no security crashes detected - } - - StringBuilder error = new StringBuilder(); - error.append("Security crash detected:\n"); - error.append("Process patterns:"); - for (Pattern pattern : config.getProcessPatterns()) { - error.append(String.format(" '%s'", pattern.toString())); - } - error.append("\nCrashes:\n"); - for (int i = 0; i < crashes.length(); i++) { - try { - JSONObject crash = crashes.getJSONObject(i); - error.append(String.format("%s\n", crash)); - } catch (JSONException e) {} - } - fail(error.toString()); } public static void assumeHasNfc(ITestDevice device) throws DeviceNotAvailableException { diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java index 5580acb598f..21d24565f95 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java @@ -21,6 +21,7 @@ import static org.junit.Assume.assumeFalse; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -36,9 +37,11 @@ public class Bug_187957589 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 187957589) public void testPocBug_187957589() throws Exception { assumeFalse(moduleIsPlayManaged("com.google.android.os.statsd")); - AdbUtils.runPoc("Bug-187957589", getDevice()); - // Sleep to ensure statsd was able to process the injected event. - Thread.sleep(5_000); - AdbUtils.assertNoCrashes(getDevice(), "statsd"); + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("statsd"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { + AdbUtils.runPoc("Bug-187957589", getDevice()); + // Sleep to ensure statsd was able to process the injected event. + Thread.sleep(5_000); + } } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java index a4b8506aed2..29601f99179 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java @@ -20,8 +20,8 @@ import static org.junit.Assume.assumeFalse; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -40,8 +40,8 @@ public class CVE_2016_2182 extends NonRootSecurityTestCase { assumeFalse(moduleIsPlayManaged("com.google.android.conscrypt")); String binaryName = "CVE-2016-2182"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); - testConfig.config.checkMinAddress(false); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); + testConfig.config.setIgnoreLowFaultAddress(false); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java index d58b3c39991..3e0760d0ddb 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -37,11 +37,11 @@ public class CVE_2018_9537 extends NonRootSecurityTestCase { @Test public void testPocCVE_2018_9537() throws Exception { String binaryName = "CVE-2018-9537"; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV, TombstoneUtils.Signals.SIGBUS, TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); // example of check crash to skip: // Abort message: 'frameworks/av/media/extractors/mkv/MatroskaExtractor.cpp:548 CHECK(mCluster) failed.' - testConfig.config = new CrashUtils.Config() + testConfig.config = new TombstoneUtils.Config() .setProcessPatterns(binaryName) .appendAbortMessageExcludes("CHECK\\(.*?\\)"); testConfig.config.setSignals(signals); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java index 1db523b4d1a..0c63f53fdf2 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -36,9 +36,9 @@ public class CVE_2018_9549 extends NonRootSecurityTestCase { @Test public void testPocCVE_2018_9549() throws Exception { String binaryName = "CVE-2018-9549"; - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.config .setAbortMessageIncludes(AdbUtils.escapeRegexSpecialChars("ubsan: mul-overflow")); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java index fdf85b77234..0e0e2cfae67 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java @@ -19,9 +19,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,10 +44,10 @@ public class CVE_2018_9558 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String[] signals = {CrashUtils.SIGABRT}; + String[] signals = {TombstoneUtils.Signals.SIGABRT}; String binaryName = "CVE-2018-9558"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "rw_t2t_handle_tlv_detect_rsp")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java index 1b4a4a7d364..926bd8c7440 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -43,10 +43,10 @@ public class CVE_2019_2012 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2019-2012"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes( new BacktraceFilterPattern("libnfc-nci", "rw_t3t_update_block")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java index b54d767a91b..0327e0387f4 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -37,9 +37,9 @@ public class CVE_2019_2014 extends NonRootSecurityTestCase { public void testPocCVE_2019_2014() throws Exception { pocPusher.only64(); String binaryName = "CVE-2019-2014"; - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java index bf46c60e611..388ac4c58d2 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -43,10 +43,10 @@ public class CVE_2019_2015 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2019-2015"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "rw_t3t_act_handle_check_rsp")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java index b1a1b54581f..9a36d86162b 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -43,10 +43,10 @@ public class CVE_2019_2017 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; String binaryName = "CVE-2019-2017"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "rw_t2t_handle_tlv_detect_rsp")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java index 9ea384649f9..baf4c63fd50 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -43,15 +43,15 @@ public class CVE_2019_2020 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2019-2020"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "llcp_dlc_proc_rx_pdu")); testConfig.config .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath")); - testConfig.config.checkMinAddress(false); + testConfig.config.setIgnoreLowFaultAddress(false); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java index ad289bf43b9..5eafc337b0e 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -36,9 +36,9 @@ public class CVE_2019_2027 extends NonRootSecurityTestCase { @Test public void testPocCVE_2019_2027() throws Exception { String binaryName = "CVE-2019-2027"; - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.config .setAbortMessageIncludes(AdbUtils.escapeRegexSpecialChars("ubsan: mul-overflow")); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java index dc941865c22..2476923e2bd 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -43,10 +43,10 @@ public class CVE_2019_2031 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; String binaryName = "CVE-2019-2031"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "rw_t3t_act_handle_check_ndef_rsp")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java index 3d054f099d1..cffa74a7331 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -40,9 +40,9 @@ public class CVE_2020_0034 extends NonRootSecurityTestCase { pocPusher.only32(); String binaryName = "CVE-2020-0034"; String inputFiles[] = {"cve_2020_0034.ivf"}; - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.inputFiles = Arrays.asList(inputFiles); testConfig.inputFilesDestination = AdbUtils.TMP_PATH; testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java index 83e6b7a17e5..85cd75c2333 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java @@ -38,7 +38,6 @@ public class CVE_2020_0072 extends NonRootSecurityTestCase { assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0072", getDevice()); - testConfig.checkCrash = false; AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java index 8f285d0fdf7..cbf3ef1362c 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,9 +44,9 @@ public class CVE_2020_0073 extends NonRootSecurityTestCase { assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); String binaryName = "CVE-2020-0073"; - String[] signals = {CrashUtils.SIGABRT}; + String[] signals = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "rw_t2t_handle_tlv_detect_rsp")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java index a6609a4b26c..f5189faf9d5 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,10 +44,10 @@ public class CVE_2020_0241 extends NonRootSecurityTestCase { pocPusher.only32(); String binaryName = "CVE-2020-0241"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice", "android::NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener")); - String signals[] = {CrashUtils.SIGABRT}; + String[] signals = {TombstoneUtils.Signals.SIGABRT}; testConfig.config.setSignals(signals); testConfig.config.setAbortMessageIncludes( AdbUtils.escapeRegexSpecialChars("Pure virtual function called")); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java index 59c7370e823..f9cd2e222a2 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -36,8 +36,8 @@ public class CVE_2020_0243 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 151644303) public void testPocCVE_2020_0243() throws Exception { AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0243", getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns("mediaserver"); - testConfig.config.checkMinAddress(false); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns("mediaserver"); + testConfig.config.setIgnoreLowFaultAddress(false); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java index 524f2d60abb..6eb6bff8933 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java @@ -20,9 +20,9 @@ import static org.junit.Assume.assumeFalse; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,9 +44,9 @@ public class CVE_2020_0381 extends NonRootSecurityTestCase { assumeFalse(moduleIsPlayManaged("com.google.android.media")); String binaryName = "CVE-2020-0381"; String inputFiles[] = {"cve_2020_0381.xmf", "cve_2020_0381.info"}; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_ptbl")); testConfig.config.setSignals(signals); testConfig.arguments = diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java index 5bdf01708e5..f73d8122add 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java @@ -20,9 +20,9 @@ import static org.junit.Assume.assumeFalse; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,9 +44,9 @@ public class CVE_2020_0383 extends NonRootSecurityTestCase { assumeFalse(moduleIsPlayManaged("com.google.android.media")); String binaryName = "CVE-2020-0383"; String inputFiles[] = {"cve_2020_0383.xmf", "cve_2020_0383.info"}; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins")); testConfig.config.setSignals(signals); testConfig.arguments = diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java index 000e9705f98..42505ca240c 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java @@ -20,9 +20,9 @@ import static org.junit.Assume.assumeFalse; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,9 +44,9 @@ public class CVE_2020_0384 extends NonRootSecurityTestCase { assumeFalse(moduleIsPlayManaged("com.google.android.media")); String binaryName = "CVE-2020-0384"; String inputFiles[] = {"cve_2020_0384.xmf", "cve_2020_0384.info"}; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes( new BacktraceFilterPattern("libmidiextractor", "Convert_art")); testConfig.config.setSignals(signals); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java index b9ba1279d8a..6bbc89e8d5e 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java @@ -20,9 +20,9 @@ import static org.junit.Assume.assumeFalse; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -44,9 +44,9 @@ public class CVE_2020_0385 extends NonRootSecurityTestCase { assumeFalse(moduleIsPlayManaged("com.google.android.media")); String binaryName = "CVE-2020-0385"; String inputFiles[] = {"cve_2020_0385.xmf", "cve_2020_0385.info"}; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins")); testConfig.config.setSignals(signals); testConfig.arguments = diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java index 15cdab54d96..4c9908fa5ed 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -36,8 +36,8 @@ public class CVE_2021_0330 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 170732441) public void testPocCVE_2021_0330() throws Exception { AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0330", getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns("storaged"); - testConfig.config.checkMinAddress(false); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns("storaged"); + testConfig.config.setIgnoreLowFaultAddress(false); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java index 71ce363ba8b..21905389223 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -43,10 +43,10 @@ public class CVE_2021_0430 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2021-0430"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "rw_mfc_handle_read_op")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java index 90e65c2e338..77d178aa674 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java @@ -37,7 +37,6 @@ public class CVE_2021_0473 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); pocPusher.only64(); AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0473", getDevice()); - testConfig.checkCrash = false; AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java index 05aa43e47c1..c96b27ae3a2 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 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. @@ -30,10 +30,12 @@ public class CVE_2021_0484 extends NonRootSecurityTestCase { /** * b/173720767 * Vulnerability Behavior: EXIT_VULNERABLE (113) + * Vulnerable library : libmedia + * Is Play managed : No */ @Test @AsbSecurityTest(cveBugId = 173720767) public void testPocCVE_2021_0484() throws Exception { - AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0484", null, getDevice()); + AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-0484", getDevice(), 300); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java index 41455a40249..d798166c165 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java @@ -21,6 +21,7 @@ import static org.junit.Assert.*; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -35,13 +36,14 @@ public class CVE_2021_0636 extends NonRootSecurityTestCase { */ AdbUtils.pushResource( "/" + mediaFileName, "/sdcard/" + mediaFileName, getDevice()); - AdbUtils.runCommandLine("logcat -c", getDevice()); - AdbUtils.runCommandLine( - "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/" - + mediaFileName, getDevice()); - Thread.sleep(4000); // Delay to run the media file and capture output in logcat - AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice()); - AdbUtils.assertNoCrashes(getDevice(), "mediaserver"); + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("mediaserver"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { + AdbUtils.runCommandLine( + "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/" + + mediaFileName, getDevice()); + Thread.sleep(4000); // Delay to run the media file and capture output in logcat + AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice()); + } } @Test diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java index 513942520a0..095fdd37118 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java @@ -19,8 +19,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -38,9 +38,9 @@ public class CVE_2021_0919 extends NonRootSecurityTestCase { public void testPocCVE_2021_0919() throws Exception { pocPusher.only32(); String binaryName = "CVE-2021-0919"; - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java index b3c9717a280..5802549f0b9 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0925.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -37,9 +37,9 @@ public class CVE_2021_0925 extends NonRootSecurityTestCase { pocPusher.only64(); String binaryName = "CVE-2021-0925"; String inputFiles[] = {"cve_2021_0925"}; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java index eddde21aacf..68eabdec09f 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.device.ITestDevice; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; @@ -41,9 +41,9 @@ public class CVE_2021_0956 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(device); assumeIsSupportedNfcDevice(device); String binaryName = "CVE-2021-0956"; - String signals[] = {CrashUtils.SIGABRT}; + String signals[] = {TombstoneUtils.Signals.SIGABRT}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, device); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java new file mode 100644 index 00000000000..90d8196c3f6 --- /dev/null +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException; + +import android.platform.test.annotations.AsbSecurityTest; + +import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase; +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(DeviceJUnit4ClassRunner.class) +public class CVE_2021_0963 extends StsExtraBusinessLogicHostTestBase { + static final String TEST_PKG = "android.security.cts.CVE_2021_0963"; + + /** + * b/199754277 + * Vulnerable app : KeyChain.apk + * Vulnerable module : com.android.keychain + * Is Play managed : No + */ + @AsbSecurityTest(cveBugId = 199754277) + @Test + public void testPocCVE_2021_0963() { + try { + ITestDevice device = getDevice(); + + /* Wake up the device */ + AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device); + + /* Install the application */ + installPackage("CVE-2021-0963.apk"); + + /* + * Set device as owner. After the test is completed, this change is reverted in the + * DeviceTest.java's tearDown() method by calling clearDeviceOwnerApp() on an instance + * of DevicePolicyManager. + */ + AdbUtils.runCommandLine("dpm set-device-owner --user 0 '" + TEST_PKG + "/" + TEST_PKG + + ".PocDeviceAdminReceiver" + "'", device); + + /* Run the device test "testOverlayButtonPresence" */ + runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence"); + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java index 7b4712f2d5a..1031df8cb76 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java @@ -18,6 +18,7 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.device.ITestDevice; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; @@ -39,7 +40,8 @@ public class CVE_2021_30351 extends NonRootSecurityTestCase { String packageName = "android.security.cts.CVE_2021_30351"; ITestDevice device = getDevice(); - try { + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("media.codec"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { /* Push the app to /data/local/tmp */ pocPusher.appendBitness(false); pocPusher.pushFile(apkName, appPath); @@ -60,11 +62,6 @@ public class CVE_2021_30351 extends NonRootSecurityTestCase { } finally { /* Un-install the app after the test */ AdbUtils.runCommandLine("pm uninstall " + packageName, device); - - /* Check if media.codec has crashed thereby indicating the presence */ - /* of the vulnerability */ - String logcat = AdbUtils.runCommandLine("logcat -d", device); - AdbUtils.assertNoCrashes(getDevice(), "media.codec"); } } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java index aaaa502f934..d88cc836a28 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -42,10 +42,10 @@ public class CVE_2021_39623 extends NonRootSecurityTestCase { public void testPocCVE_2021_39623() throws Exception { String binaryName = "CVE-2021-39623"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName) .setBacktraceIncludes(new BacktraceFilterPattern("libstagefright", "android::SimpleDecodingSource::doRead")); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; testConfig.config.setSignals(signals); testConfig.inputFilesDestination = AdbUtils.TMP_PATH; String inputFiles[] = {"cve_2021_39623.ogg"}; diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java index 29de04e3d0c..930138f8a74 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -42,10 +42,10 @@ public class CVE_2021_39664 extends NonRootSecurityTestCase { @Test public void testPocCVE_2021_39664() throws Exception { String inputFiles[] = {"cve_2021_39664"}; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2021-39664"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libandroidfw", "android::LoadedPackage::Load")); testConfig.config.setSignals(signals); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java index 79e3d0fdbd6..ef3713322a4 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -40,10 +40,10 @@ public class CVE_2021_39665 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 204077881) @Test public void testPocCVE_2021_39665() throws Exception { - String[] signals = {CrashUtils.SIGSEGV}; + String[] signals = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2021-39665"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice", "android::AAVCAssembler::checkSpsUpdated")); testConfig.config.setSignals(signals); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java index 0053fc6d219..9c5887ad911 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java @@ -18,9 +18,9 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -42,12 +42,12 @@ public class CVE_2021_39804 extends NonRootSecurityTestCase { public void testPocCVE_2021_39804() throws Exception { String inputFiles[] = {"cve_2021_39804.heif"}; String binaryName = "CVE-2021-39804"; - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); testConfig.config = - new CrashUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes( + new TombstoneUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes( new BacktraceFilterPattern("libheif", "android::HeifDecoderImpl::reinit")); - testConfig.config.checkMinAddress(false); + testConfig.config.setIgnoreLowFaultAddress(false); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; testConfig.inputFiles = Arrays.asList(inputFiles); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java index baa87075b75..f9832a4fdbf 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java @@ -18,8 +18,8 @@ package android.security.cts; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; @@ -42,10 +42,10 @@ public class CVE_2022_20123 extends NonRootSecurityTestCase { public void testPocCVE_2022_20123() throws Exception { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2022-20123"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes( new BacktraceFilterPattern("libnfc_nci_jni", "Mfc_RecvPacket")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java index 1aeaa1d80fd..bb717d2013c 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java @@ -20,9 +20,9 @@ import static org.junit.Assume.assumeNoException; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -45,11 +45,11 @@ public class CVE_2022_20131 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = {CrashUtils.SIGSEGV}; + String signals[] = {TombstoneUtils.Signals.SIGSEGV}; String binaryName = "CVE-2022-20131"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); testConfig.config = - new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) + new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci", "nfc_ncif_proc_ee_discover_req")); testConfig.config diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java index 5b1d38ca53f..7157a130964 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java @@ -20,9 +20,9 @@ import static org.junit.Assume.assumeNoException; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; -import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; +import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -45,11 +45,11 @@ public class CVE_2022_20147 extends NonRootSecurityTestCase { AdbUtils.assumeHasNfc(getDevice()); assumeIsSupportedNfcDevice(getDevice()); pocPusher.only64(); - String signals[] = { CrashUtils.SIGSEGV }; + String signals[] = { TombstoneUtils.Signals.SIGSEGV }; String binaryName = "CVE-2022-20147"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config() + testConfig.config = new TombstoneUtils.Config() .setProcessPatterns(Pattern.compile(binaryName)) .setBacktraceIncludes(new BacktraceFilterPattern( "libnfc-nci", "nfa_dm_check_set_config")); diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java new file mode 100644 index 00000000000..62d0f16f216 --- /dev/null +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 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 static org.junit.Assume.assumeNoException; + +import android.platform.test.annotations.AsbSecurityTest; + +import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(DeviceJUnit4ClassRunner.class) +public class CVE_2022_20475 extends NonRootSecurityTestCase { + + /** + * b/240663194 + * Vulnerable module : services.jar + * Is Play Managed : No + */ + @AsbSecurityTest(cveBugId = 240663194) + @Test + public void testPocCVE_2022_20475() { + try { + final String testPkg = "android.security.cts.CVE_2022_20475_test"; + ITestDevice device = getDevice(); + + // Install the test and target apps + installPackage("CVE-2022-20475-test.apk"); + installPackage("CVE-2022-20475-target.apk"); + + // Wake up the device + AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device); + + // Run the test "testCVE_2022_20475" + runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2022_20475"); + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java index a0200f17840..cc3fd4249df 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java @@ -20,6 +20,7 @@ import static org.junit.Assume.*; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -39,12 +40,13 @@ public class CVE_2022_22082 extends NonRootSecurityTestCase { */ safeReboot(); AdbUtils.pushResource("/cve_2022_22082.dsf", "/sdcard/cve_2022_22082.dsf", getDevice()); - AdbUtils.runCommandLine("logcat -c", getDevice()); - AdbUtils.runCommandLine( - "am start -a android.intent.action.VIEW -t audio/dsf -d" - + " file:///sdcard/cve_2022_22082.dsf", - getDevice()); - Thread.sleep(10000); - AdbUtils.assertNoCrashes(getDevice(), "media.extractor"); + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("media.extractor"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { + AdbUtils.runCommandLine( + "am start -a android.intent.action.VIEW -t audio/dsf -d" + + " file:///sdcard/cve_2022_22082.dsf", + getDevice()); + Thread.sleep(10000); + } } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java index 4d406b7ce29..ca50ea81898 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java @@ -21,6 +21,7 @@ import static org.junit.Assert.*; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -35,13 +36,14 @@ public class Poc17_11 extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 36075131) public void testPocCVE_2017_0859() throws Exception { - AdbUtils.runCommandLine("logcat -c", getDevice()); AdbUtils.pushResource("/cve_2017_0859.mp4", "/sdcard/cve_2017_0859.mp4", getDevice()); - AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " + - "-d file:///sdcard/cve_2017_0859.mp4" + - " -t audio/amr", getDevice()); - // Wait for intent to be processed before checking logcat - Thread.sleep(5000); - AdbUtils.assertNoCrashes(getDevice(), "mediaserver"); + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("mediaserver"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { + AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " + + "-d file:///sdcard/cve_2017_0859.mp4" + + " -t audio/amr", getDevice()); + // Wait for intent to be processed before checking logcat + Thread.sleep(5000); + } } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java index 3f2d1d0d798..32d82514cb9 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java @@ -17,10 +17,12 @@ package android.security.cts; import static org.junit.Assert.*; +import static org.junit.Assume.assumeTrue; import android.platform.test.annotations.AsbSecurityTest; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import org.junit.Test; @@ -36,13 +38,11 @@ public class Poc20_06 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 148817146) public void testPocCVE_2020_3635() throws Exception { String isApplicable = AdbUtils.runCommandLine("service list", getDevice()); - if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) { - AdbUtils.runCommandLine("logcat -c", getDevice()); + assumeTrue(isApplicable.contains("com.qualcomm.qti.IPerfManager")); + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("perfservice"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { AdbUtils.runCommandLine( "service call vendor.perfservice 4 i32 1 i64 4702394920265069920", getDevice()); - String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice()); - assertNotMatchesMultiLine( - "Fatal signal 11 \\(SIGSEGV\\).*?>>> /system/bin/perfservice <<<", logcatOut); } } @@ -79,11 +79,11 @@ public class Poc20_06 extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 152310294) public void testPocCVE_2020_3676() throws Exception { String isApplicable = AdbUtils.runCommandLine("service list", getDevice()); - if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) { - AdbUtils.runCommandLine("logcat -c", getDevice()); + assumeTrue(isApplicable.contains("com.qualcomm.qti.IPerfManager")); + TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("perfservice"); + try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) { AdbUtils.runCommandLine( "service call vendor.perfservice 4 i32 2442302356 i64 -2", getDevice()); - AdbUtils.assertNoCrashes(getDevice(), "perfservice"); } } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java index 91c84d7333e..cc336042e2b 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java @@ -23,8 +23,8 @@ import static org.junit.Assume.assumeThat; import android.platform.test.annotations.AsbSecurityTest; -import com.android.compatibility.common.util.CrashUtils; import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase; +import com.android.sts.common.util.TombstoneUtils; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import junit.framework.Assert; @@ -124,10 +124,14 @@ public class TestMedia extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 156997193) public void testPocCVE_2020_0409() throws Exception { - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; String binaryName = "CVE-2020-0409"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } @@ -139,10 +143,14 @@ public class TestMedia extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 161894517) public void testPocCVE_2020_0421() throws Exception { - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; String binaryName = "CVE-2020-0421"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } @@ -259,7 +267,11 @@ public class TestMedia extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 74122779) public void testPocCVE_2018_9428() throws Exception { - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2018-9428", getDevice()); } @@ -270,9 +282,13 @@ public class TestMedia extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 64340921) public void testPocCVE_2017_0837() throws Exception { - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2017-0837", getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver"); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns("audioserver"); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } @@ -287,9 +303,13 @@ public class TestMedia extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 62151041) public void testPocCVE_2018_9466_CVE_2017_9047() throws Exception { String binaryName = "CVE-2018-9466-CVE-2017-9047"; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } @@ -301,9 +321,13 @@ public class TestMedia extends NonRootSecurityTestCase { @AsbSecurityTest(cveBugId = 62151041) public void testPocCVE_2018_9466_CVE_2017_9048() throws Exception { String binaryName = "CVE-2018-9466-CVE-2017-9048"; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } @@ -316,9 +340,13 @@ public class TestMedia extends NonRootSecurityTestCase { public void testPocCVE_2018_9466_CVE_2017_9049() throws Exception { String binaryName = "CVE-2018-9466-CVE-2017-9049"; String inputFiles[] = {"cve_2018_9466_cve_2017_9049.xml"}; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; testConfig.inputFiles = Arrays.asList(inputFiles); @@ -334,9 +362,13 @@ public class TestMedia extends NonRootSecurityTestCase { public void testPocCVE_2018_9466_CVE_2017_9050() throws Exception { String binaryName = "CVE-2018-9466-CVE-2017-9049"; String inputFiles[] = {"cve_2018_9466_cve_2017_9050.xml"}; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; testConfig.inputFiles = Arrays.asList(inputFiles); @@ -353,9 +385,13 @@ public class TestMedia extends NonRootSecurityTestCase { public void testPocCVE_2015_3873() throws Exception { String inputFiles[] = {"cve_2015_3873.mp4"}; String binaryName = "CVE-2015-3873"; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; testConfig.inputFiles = Arrays.asList(inputFiles); @@ -498,9 +534,13 @@ public class TestMedia extends NonRootSecurityTestCase { assumeFalse(moduleIsPlayManaged("com.google.android.media.swcodec")); String inputFiles[] = {"cve_2020_0451.aac"}; String binaryName = "CVE-2020-0451"; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; testConfig.inputFiles = Arrays.asList(inputFiles); @@ -548,10 +588,14 @@ public class TestMedia extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 120426980) public void testPocCVE_2019_9362() throws Exception { - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; String binaryName = "CVE-2019-9362"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } @@ -565,9 +609,13 @@ public class TestMedia extends NonRootSecurityTestCase { public void testPocCVE_2019_9308() throws Exception { String inputFiles[] = {"cve_2019_9308.mp4"}; String binaryName = "CVE-2019-9308"; - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0]; testConfig.inputFiles = Arrays.asList(inputFiles); @@ -582,10 +630,14 @@ public class TestMedia extends NonRootSecurityTestCase { @Test @AsbSecurityTest(cveBugId = 112662995) public void testPocCVE_2019_9357() throws Exception { - String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT}; + String signals[] = { + TombstoneUtils.Signals.SIGSEGV, + TombstoneUtils.Signals.SIGBUS, + TombstoneUtils.Signals.SIGABRT, + }; String binaryName = "CVE-2019-9357"; AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice()); - testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName); + testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName); testConfig.config.setSignals(signals); AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); } diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp new file mode 100644 index 00000000000..ea39e68b2be --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test_helper_app { + name: "CVE-2021-0963", + defaults: [ + "cts_defaults", + ], + srcs: [ + "src/**/*.java", + ], + test_suites: [ + "sts", + ], + static_libs: [ + "androidx.test.core", + "androidx.test.rules", + "androidx.test.uiautomator_uiautomator", + ], + platform_apis: true, +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml new file mode 100644 index 00000000000..ae0d4160fcb --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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_0963"> + <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> + <application> + <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> + <receiver android:name=".PocDeviceAdminReceiver" + android:exported="true" + android:permission="android.permission.BIND_DEVICE_ADMIN"> + <meta-data android:name="android.app.device_admin" + android:resource="@xml/device_policies" /> + <intent-filter> + <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> + </intent-filter> + </receiver> + <service android:name=".PocService" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.security.cts.CVE_2021_0963" /> +</manifest> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml new file mode 100644 index 00000000000..6a14b4a8240 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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> + <integer name="assumptionFailure">-1</integer> + <integer name="noException">0</integer> + <integer name="timeoutMs">10000</integer> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml new file mode 100644 index 00000000000..1da84fe3711 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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="actionKeychainActivity">com.android.keychain.CHOOSER</string> + <string name="activityNotFoundMsg">The activity with intent was not found : </string> + <string name="activityNotStartedException">Unable to start the activity with intent : </string> + <string name="alias">Client</string> + <string name="callbackKey">callback</string> + <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string> + <string name="certType">X.509</string> + <string name="dumpsysActivity">dumpsys activity %1$s</string> + <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command + </string> + <string name="errorMessage">Device is vulnerable to b/199754277 hence any app with + "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string> + <string name="keyType">RSA</string> + <string name="mResumedTrue">mResumed=true</string> + <string name="messageKey">message</string> + <string name="overlayButtonText">OverlayButton</string> + <string name="overlayServiceNotStartedException">Unable to start the overlay service</string> + <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string> + <string name="statusKey">status</string> + <string name="vulActivityNotRunningError">The activity %1$s is not currently running + on the device</string> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml new file mode 100644 index 00000000000..a826e80f531 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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. + --> + +<device-admin> + <uses-policies> + </uses-policies> +</device-admin> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java new file mode 100644 index 00000000000..3d1c0df2131 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2022 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_0963; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeNoException; +import static org.junit.Assume.assumeTrue; + +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.os.Bundle; +import android.os.RemoteCallback; +import android.provider.Settings; + +import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.Until; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.ByteArrayInputStream; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +@RunWith(AndroidJUnit4.class) +public class DeviceTest { + private DevicePolicyManager mDevicePolicyManager; + private ComponentName mComponentName; + Context mContext; + + /** + * Generated from above and converted with: + * + * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] PRIVATE_KEY = + new byte[] {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x76, (byte) 0x02, + (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, + (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, + (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, + (byte) 0x82, (byte) 0x02, (byte) 0x60, (byte) 0x30, (byte) 0x82, (byte) 0x02, + (byte) 0x5c, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, + (byte) 0x81, (byte) 0x00, (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8, + (byte) 0xc4, (byte) 0x44, (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1, + (byte) 0xb9, (byte) 0x1b, (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f, + (byte) 0x06, (byte) 0xe7, (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8, + (byte) 0xaa, (byte) 0x0a, (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b, + (byte) 0xad, (byte) 0xfe, (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d, + (byte) 0xc9, (byte) 0xf5, (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1, + (byte) 0xcc, (byte) 0x3f, (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67, + (byte) 0x6a, (byte) 0xe8, (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a, + (byte) 0x53, (byte) 0xd9, (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90, + (byte) 0xbb, (byte) 0x95, (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32, + (byte) 0xce, (byte) 0xf8, (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19, + (byte) 0x91, (byte) 0x29, (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1, + (byte) 0xcb, (byte) 0xa7, (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a, + (byte) 0x0c, (byte) 0x07, (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d, + (byte) 0x08, (byte) 0xf4, (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66, + (byte) 0x28, (byte) 0xcb, (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f, + (byte) 0x7e, (byte) 0x83, (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83, + (byte) 0x2d, (byte) 0xa0, (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68, + (byte) 0x47, (byte) 0x31, (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e, + (byte) 0x12, (byte) 0x1b, (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8, + (byte) 0x84, (byte) 0x5f, (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03, + (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, + (byte) 0x24, (byte) 0x95, (byte) 0xb8, (byte) 0xe1, (byte) 0xf4, (byte) 0x7b, + (byte) 0xbc, (byte) 0x0c, (byte) 0x6d, (byte) 0x4d, (byte) 0x01, (byte) 0xe2, + (byte) 0x42, (byte) 0xe2, (byte) 0x9a, (byte) 0xe4, (byte) 0xab, (byte) 0xe2, + (byte) 0x9a, (byte) 0x8c, (byte) 0xd5, (byte) 0x93, (byte) 0xe8, (byte) 0x43, + (byte) 0x77, (byte) 0x85, (byte) 0xfd, (byte) 0xf3, (byte) 0xd8, (byte) 0xd6, + (byte) 0xe9, (byte) 0x02, (byte) 0xf3, (byte) 0xbf, (byte) 0x82, (byte) 0x65, + (byte) 0xc3, (byte) 0x7c, (byte) 0x96, (byte) 0x09, (byte) 0x04, (byte) 0x16, + (byte) 0x1d, (byte) 0x03, (byte) 0x3d, (byte) 0x82, (byte) 0xb8, (byte) 0xdc, + (byte) 0xbb, (byte) 0xd6, (byte) 0xbf, (byte) 0x2a, (byte) 0x52, (byte) 0x83, + (byte) 0x76, (byte) 0x5b, (byte) 0xae, (byte) 0x59, (byte) 0xf6, (byte) 0xee, + (byte) 0x84, (byte) 0x44, (byte) 0x4a, (byte) 0xa7, (byte) 0x25, (byte) 0x50, + (byte) 0x89, (byte) 0x63, (byte) 0x43, (byte) 0x0b, (byte) 0xc8, (byte) 0xd5, + (byte) 0x17, (byte) 0x9d, (byte) 0x8b, (byte) 0x62, (byte) 0xd5, (byte) 0xf1, + (byte) 0xde, (byte) 0x45, (byte) 0xe6, (byte) 0x35, (byte) 0x10, (byte) 0xba, + (byte) 0x58, (byte) 0x18, (byte) 0x44, (byte) 0xc1, (byte) 0x6d, (byte) 0xb6, + (byte) 0x1d, (byte) 0x2f, (byte) 0x53, (byte) 0xb6, (byte) 0x5a, (byte) 0xf1, + (byte) 0x66, (byte) 0xbc, (byte) 0x0e, (byte) 0x63, (byte) 0xa7, (byte) 0x0f, + (byte) 0x81, (byte) 0x4b, (byte) 0x07, (byte) 0x31, (byte) 0xa5, (byte) 0x70, + (byte) 0xec, (byte) 0x30, (byte) 0x57, (byte) 0xc4, (byte) 0x14, (byte) 0xb2, + (byte) 0x8b, (byte) 0x6f, (byte) 0x26, (byte) 0x7e, (byte) 0x55, (byte) 0x60, + (byte) 0x63, (byte) 0x7d, (byte) 0x90, (byte) 0xd7, (byte) 0x5f, (byte) 0xef, + (byte) 0x7d, (byte) 0xc1, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xfe, + (byte) 0x92, (byte) 0xa9, (byte) 0xf1, (byte) 0x29, (byte) 0x1e, (byte) 0xd4, + (byte) 0x72, (byte) 0xd3, (byte) 0x3f, (byte) 0x9d, (byte) 0xd6, (byte) 0x3d, + (byte) 0xe9, (byte) 0xcf, (byte) 0x3e, (byte) 0x06, (byte) 0xdc, (byte) 0x65, + (byte) 0x8f, (byte) 0xc0, (byte) 0x81, (byte) 0xc2, (byte) 0x66, (byte) 0xc1, + (byte) 0x5c, (byte) 0x2c, (byte) 0xfa, (byte) 0x08, (byte) 0x65, (byte) 0xb6, + (byte) 0x47, (byte) 0xc5, (byte) 0x14, (byte) 0x8d, (byte) 0x69, (byte) 0xe9, + (byte) 0xaf, (byte) 0x42, (byte) 0x02, (byte) 0x53, (byte) 0x04, (byte) 0x63, + (byte) 0x47, (byte) 0xaf, (byte) 0xcc, (byte) 0xae, (byte) 0x08, (byte) 0x31, + (byte) 0xba, (byte) 0xea, (byte) 0x85, (byte) 0xda, (byte) 0xd6, (byte) 0xb2, + (byte) 0xe7, (byte) 0x4c, (byte) 0xda, (byte) 0xad, (byte) 0x52, (byte) 0x76, + (byte) 0x48, (byte) 0x16, (byte) 0xeb, (byte) 0x02, (byte) 0x41, (byte) 0x00, + (byte) 0xef, (byte) 0xc4, (byte) 0x7d, (byte) 0x69, (byte) 0x7b, (byte) 0xcb, + (byte) 0xcb, (byte) 0xf7, (byte) 0x00, (byte) 0x2d, (byte) 0x05, (byte) 0x3c, + (byte) 0xe4, (byte) 0xfd, (byte) 0x5c, (byte) 0xea, (byte) 0xcf, (byte) 0x40, + (byte) 0x84, (byte) 0x10, (byte) 0xf1, (byte) 0xc0, (byte) 0xaf, (byte) 0xc7, + (byte) 0xc8, (byte) 0x51, (byte) 0xac, (byte) 0x18, (byte) 0x25, (byte) 0x63, + (byte) 0x75, (byte) 0xc7, (byte) 0x0e, (byte) 0xa9, (byte) 0xed, (byte) 0x9c, + (byte) 0x78, (byte) 0x08, (byte) 0x28, (byte) 0x1d, (byte) 0x9e, (byte) 0xfa, + (byte) 0x17, (byte) 0x0f, (byte) 0x7a, (byte) 0x6a, (byte) 0x78, (byte) 0x63, + (byte) 0x6e, (byte) 0xb3, (byte) 0x6b, (byte) 0xd6, (byte) 0x43, (byte) 0x4b, + (byte) 0x58, (byte) 0xb8, (byte) 0x77, (byte) 0x10, (byte) 0x07, (byte) 0x70, + (byte) 0xa6, (byte) 0xa9, (byte) 0xae, (byte) 0x0d, (byte) 0x02, (byte) 0x41, + (byte) 0x00, (byte) 0x92, (byte) 0x4c, (byte) 0x79, (byte) 0x0b, (byte) 0x95, + (byte) 0xc5, (byte) 0x18, (byte) 0xf4, (byte) 0x90, (byte) 0x40, (byte) 0x8c, + (byte) 0x15, (byte) 0x96, (byte) 0x69, (byte) 0x2a, (byte) 0xe7, (byte) 0x8b, + (byte) 0x8b, (byte) 0xd7, (byte) 0x76, (byte) 0x00, (byte) 0x7c, (byte) 0xd1, + (byte) 0xda, (byte) 0xb9, (byte) 0x9e, (byte) 0x9e, (byte) 0x5e, (byte) 0x66, + (byte) 0xbb, (byte) 0x05, (byte) 0x41, (byte) 0x43, (byte) 0x9a, (byte) 0x67, + (byte) 0x16, (byte) 0x89, (byte) 0xec, (byte) 0x65, (byte) 0x33, (byte) 0xee, + (byte) 0xbf, (byte) 0xa3, (byte) 0xca, (byte) 0x8b, (byte) 0xd6, (byte) 0x45, + (byte) 0xe1, (byte) 0x81, (byte) 0xaa, (byte) 0xd8, (byte) 0xa2, (byte) 0x6a, + (byte) 0x3c, (byte) 0x5e, (byte) 0x7e, (byte) 0x1c, (byte) 0xa5, (byte) 0xc3, + (byte) 0x5b, (byte) 0x93, (byte) 0x8c, (byte) 0x24, (byte) 0x57, (byte) 0x02, + (byte) 0x40, (byte) 0x0a, (byte) 0x6d, (byte) 0x3f, (byte) 0x0e, (byte) 0xf1, + (byte) 0x45, (byte) 0x41, (byte) 0x8f, (byte) 0x72, (byte) 0x40, (byte) 0x82, + (byte) 0xf3, (byte) 0xcc, (byte) 0xf9, (byte) 0x7f, (byte) 0xaa, (byte) 0xee, + (byte) 0x6c, (byte) 0x5d, (byte) 0xd1, (byte) 0xe6, (byte) 0xd1, (byte) 0x7c, + (byte) 0x53, (byte) 0x71, (byte) 0xd0, (byte) 0xab, (byte) 0x6d, (byte) 0x39, + (byte) 0x63, (byte) 0x03, (byte) 0xe2, (byte) 0x2e, (byte) 0x2f, (byte) 0x11, + (byte) 0x98, (byte) 0x36, (byte) 0x58, (byte) 0x14, (byte) 0x76, (byte) 0x85, + (byte) 0x4d, (byte) 0x56, (byte) 0xe7, (byte) 0x63, (byte) 0x69, (byte) 0x71, + (byte) 0xe6, (byte) 0xd1, (byte) 0x0f, (byte) 0x98, (byte) 0x66, (byte) 0xee, + (byte) 0xf2, (byte) 0x3d, (byte) 0xdf, (byte) 0x77, (byte) 0xbe, (byte) 0x08, + (byte) 0xb4, (byte) 0xcb, (byte) 0x6a, (byte) 0xa1, (byte) 0x99, (byte) 0x02, + (byte) 0x40, (byte) 0x52, (byte) 0x01, (byte) 0xde, (byte) 0x62, (byte) 0xc2, + (byte) 0x25, (byte) 0xbf, (byte) 0x5d, (byte) 0x77, (byte) 0xe4, (byte) 0x6b, + (byte) 0xb6, (byte) 0xd7, (byte) 0x8f, (byte) 0x89, (byte) 0x2c, (byte) 0xe6, + (byte) 0x8d, (byte) 0xe5, (byte) 0xad, (byte) 0x39, (byte) 0x17, (byte) 0x54, + (byte) 0x2b, (byte) 0x35, (byte) 0x53, (byte) 0xd1, (byte) 0xa1, (byte) 0xef, + (byte) 0x48, (byte) 0xbc, (byte) 0x95, (byte) 0x48, (byte) 0xcf, (byte) 0x62, + (byte) 0xf4, (byte) 0x33, (byte) 0xcf, (byte) 0x37, (byte) 0x78, (byte) 0xeb, + (byte) 0x17, (byte) 0xb4, (byte) 0x0b, (byte) 0x83, (byte) 0x4f, (byte) 0xb6, + (byte) 0xab, (byte) 0x7d, (byte) 0x67, (byte) 0x3e, (byte) 0x4e, (byte) 0x44, + (byte) 0x4a, (byte) 0x55, (byte) 0x2e, (byte) 0x34, (byte) 0x12, (byte) 0x0b, + (byte) 0x59, (byte) 0xb3, (byte) 0xb1, (byte) 0x1e, (byte) 0x3d}; + + + /** + * Generated from above and converted with: + * + * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g' + */ + private static final byte[] USER_CERT = + {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xd8, (byte) 0x30, (byte) 0x82, + (byte) 0x01, (byte) 0xc0, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01, + (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d, + (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, + (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x0b, (byte) 0x05, + (byte) 0x00, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b, (byte) 0x30, + (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, + (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13, + (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d, + (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74, + (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x06, + (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, + (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x32, + (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x30, (byte) 0x37, + (byte) 0x32, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x5a, (byte) 0x17, + (byte) 0x0d, (byte) 0x33, (byte) 0x32, (byte) 0x30, (byte) 0x33, (byte) 0x32, + (byte) 0x32, (byte) 0x30, (byte) 0x37, (byte) 0x32, (byte) 0x30, (byte) 0x31, + (byte) 0x32, (byte) 0x5a, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b, + (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, + (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, + (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, + (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, + (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, + (byte) 0x06, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, + (byte) 0x65, (byte) 0x30, (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, + (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, + (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, + (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, + (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, + (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8, (byte) 0xc4, (byte) 0x44, + (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1, (byte) 0xb9, (byte) 0x1b, + (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f, (byte) 0x06, (byte) 0xe7, + (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8, (byte) 0xaa, (byte) 0x0a, + (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b, (byte) 0xad, (byte) 0xfe, + (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d, (byte) 0xc9, (byte) 0xf5, + (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1, (byte) 0xcc, (byte) 0x3f, + (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67, (byte) 0x6a, (byte) 0xe8, + (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a, (byte) 0x53, (byte) 0xd9, + (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90, (byte) 0xbb, (byte) 0x95, + (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32, (byte) 0xce, (byte) 0xf8, + (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19, (byte) 0x91, (byte) 0x29, + (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1, (byte) 0xcb, (byte) 0xa7, + (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a, (byte) 0x0c, (byte) 0x07, + (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d, (byte) 0x08, (byte) 0xf4, + (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66, (byte) 0x28, (byte) 0xcb, + (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f, (byte) 0x7e, (byte) 0x83, + (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83, (byte) 0x2d, (byte) 0xa0, + (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68, (byte) 0x47, (byte) 0x31, + (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e, (byte) 0x12, (byte) 0x1b, + (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8, (byte) 0x84, (byte) 0x5f, + (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, + (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30, (byte) 0x79, (byte) 0x30, + (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, + (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00, (byte) 0x30, (byte) 0x2c, + (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01, + (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01, (byte) 0x0d, (byte) 0x04, + (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f, (byte) 0x70, (byte) 0x65, + (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c, (byte) 0x20, (byte) 0x47, + (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72, (byte) 0x61, (byte) 0x74, + (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43, (byte) 0x65, (byte) 0x72, + (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69, (byte) 0x63, (byte) 0x61, + (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d, (byte) 0x06, (byte) 0x03, + (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16, (byte) 0x04, + (byte) 0x14, (byte) 0xee, (byte) 0xec, (byte) 0x08, (byte) 0xcc, (byte) 0xdd, + (byte) 0xa3, (byte) 0x29, (byte) 0x6e, (byte) 0x2b, (byte) 0x78, (byte) 0x23, + (byte) 0xb3, (byte) 0xf0, (byte) 0xb8, (byte) 0x9d, (byte) 0x53, (byte) 0x41, + (byte) 0x2e, (byte) 0x3c, (byte) 0x61, (byte) 0x30, (byte) 0x1f, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04, (byte) 0x18, + (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0x86, (byte) 0xdb, + (byte) 0xa5, (byte) 0x5e, (byte) 0x0e, (byte) 0x03, (byte) 0xbc, (byte) 0xe4, + (byte) 0xc1, (byte) 0xc8, (byte) 0xf3, (byte) 0xed, (byte) 0x24, (byte) 0x48, + (byte) 0xb1, (byte) 0x37, (byte) 0x3a, (byte) 0x52, (byte) 0x10, (byte) 0x57, + (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, + (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, + (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82, (byte) 0x01, + (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x5a, (byte) 0x5c, (byte) 0x08, + (byte) 0xe4, (byte) 0x0e, (byte) 0x28, (byte) 0x4c, (byte) 0xa9, (byte) 0x0e, + (byte) 0x35, (byte) 0xbe, (byte) 0xe3, (byte) 0xd5, (byte) 0xd1, (byte) 0xb4, + (byte) 0x47, (byte) 0x87, (byte) 0x63, (byte) 0xd2, (byte) 0x5e, (byte) 0x7e, + (byte) 0xf6, (byte) 0xd8, (byte) 0xce, (byte) 0xdf, (byte) 0x10, (byte) 0x15, + (byte) 0x61, (byte) 0xc4, (byte) 0x9a, (byte) 0xf1, (byte) 0xba, (byte) 0x33, + (byte) 0xf2, (byte) 0xc2, (byte) 0x01, (byte) 0x95, (byte) 0xa7, (byte) 0x74, + (byte) 0x97, (byte) 0xc1, (byte) 0x43, (byte) 0x68, (byte) 0x92, (byte) 0xbe, + (byte) 0x9a, (byte) 0x6f, (byte) 0x38, (byte) 0xcb, (byte) 0xa0, (byte) 0xcf, + (byte) 0x1e, (byte) 0x5b, (byte) 0x03, (byte) 0xde, (byte) 0x45, (byte) 0x6d, + (byte) 0xea, (byte) 0xf0, (byte) 0x46, (byte) 0x4d, (byte) 0xb6, (byte) 0x4b, + (byte) 0x88, (byte) 0xc7, (byte) 0xb8, (byte) 0xe3, (byte) 0x9f, (byte) 0x58, + (byte) 0x8b, (byte) 0x2d, (byte) 0xbf, (byte) 0x4b, (byte) 0x3f, (byte) 0x54, + (byte) 0x2d, (byte) 0xa8, (byte) 0x27, (byte) 0x72, (byte) 0x5e, (byte) 0x36, + (byte) 0x67, (byte) 0x5c, (byte) 0x6e, (byte) 0x9a, (byte) 0x67, (byte) 0x73, + (byte) 0x44, (byte) 0xaf, (byte) 0x46, (byte) 0x7f, (byte) 0xd6, (byte) 0x2b, + (byte) 0x9d, (byte) 0x28, (byte) 0xb1, (byte) 0xc4, (byte) 0xc4, (byte) 0x72, + (byte) 0x3d, (byte) 0x6d, (byte) 0x7d, (byte) 0x28, (byte) 0x40, (byte) 0x62, + (byte) 0x40, (byte) 0x21, (byte) 0x52, (byte) 0xb5, (byte) 0x0b, (byte) 0xf3, + (byte) 0xcc, (byte) 0x36, (byte) 0x03, (byte) 0x10, (byte) 0x19, (byte) 0xe3, + (byte) 0xc2, (byte) 0xfe, (byte) 0xe9, (byte) 0x08, (byte) 0x0d, (byte) 0xd4, + (byte) 0x8b, (byte) 0x12, (byte) 0xd6, (byte) 0x3d, (byte) 0xc5, (byte) 0xb8, + (byte) 0x8c, (byte) 0xbd, (byte) 0xa5, (byte) 0xcd, (byte) 0xb3, (byte) 0xe4, + (byte) 0xd1, (byte) 0xd8, (byte) 0x4c, (byte) 0x32, (byte) 0x44, (byte) 0x3f, + (byte) 0x63, (byte) 0x32, (byte) 0x09, (byte) 0xdb, (byte) 0x8b, (byte) 0x7b, + (byte) 0x30, (byte) 0x58, (byte) 0xc7, (byte) 0xcf, (byte) 0xc3, (byte) 0x44, + (byte) 0xd9, (byte) 0xff, (byte) 0x63, (byte) 0x91, (byte) 0x74, (byte) 0xd8, + (byte) 0x62, (byte) 0x2b, (byte) 0x52, (byte) 0xc8, (byte) 0x82, (byte) 0x9f, + (byte) 0xeb, (byte) 0x22, (byte) 0x5c, (byte) 0xa2, (byte) 0x26, (byte) 0xfe, + (byte) 0x04, (byte) 0x31, (byte) 0x53, (byte) 0x09, (byte) 0xa7, (byte) 0x23, + (byte) 0xe3, (byte) 0x0f, (byte) 0xf8, (byte) 0xe9, (byte) 0x99, (byte) 0xad, + (byte) 0x4b, (byte) 0x23, (byte) 0x07, (byte) 0xfb, (byte) 0xfa, (byte) 0xc3, + (byte) 0x55, (byte) 0x59, (byte) 0xdb, (byte) 0x6b, (byte) 0x71, (byte) 0xdf, + (byte) 0x25, (byte) 0x0f, (byte) 0xaa, (byte) 0xa2, (byte) 0xfa, (byte) 0x28, + (byte) 0x49, (byte) 0x65, (byte) 0x7e, (byte) 0x0b, (byte) 0x74, (byte) 0x30, + (byte) 0xd9, (byte) 0x9a, (byte) 0xfe, (byte) 0x2c, (byte) 0x8c, (byte) 0x67, + (byte) 0x50, (byte) 0x0c, (byte) 0x6d, (byte) 0x4c, (byte) 0xba, (byte) 0x34, + (byte) 0x3b, (byte) 0x0d, (byte) 0x16, (byte) 0x45, (byte) 0x63, (byte) 0x73, + (byte) 0xc2, (byte) 0x9f, (byte) 0xb4, (byte) 0xdd, (byte) 0x6f, (byte) 0xde, + (byte) 0x9d, (byte) 0x71, (byte) 0xbf, (byte) 0x8d, (byte) 0x1b, (byte) 0x79, + (byte) 0xa0, (byte) 0x0a, (byte) 0x66, (byte) 0x7e, (byte) 0x56, (byte) 0x83, + (byte) 0x8f, (byte) 0x3f, (byte) 0x7d, (byte) 0x93, (byte) 0xf6, (byte) 0xc9, + (byte) 0x42, (byte) 0xfc, (byte) 0xc5, (byte) 0xf2, (byte) 0x49, (byte) 0xec}; + + @After + public void tearDown() { + try { + mDevicePolicyManager.removeKeyPair(mComponentName, mContext.getString(R.string.alias)); + mDevicePolicyManager.clearDeviceOwnerApp(mContext.getPackageName()); + } catch (Exception e) { + // ignore all exceptions as the test is already complete + } + } + + @Test + public void testOverlayButtonPresence() { + try { + /* Install key pair required to launch KeyChainActivity dialog */ + mContext = getInstrumentation().getContext(); + Resources resources = mContext.getResources(); + KeyFactory kf = KeyFactory.getInstance(mContext.getString(R.string.keyType)); + PrivateKey privKey = kf.generatePrivate(new PKCS8EncodedKeySpec(PRIVATE_KEY)); + CertificateFactory cf = + CertificateFactory.getInstance(mContext.getString(R.string.certType)); + Certificate cert = cf.generateCertificate(new ByteArrayInputStream(USER_CERT)); + mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class); + mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(), + PocDeviceAdminReceiver.class.getName()); + assumeTrue(mDevicePolicyManager.installKeyPair(mComponentName, privKey, cert, + mContext.getString(R.string.alias))); + + /* Start the overlay service */ + Intent intent = new Intent(mContext, PocService.class); + assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg), + Settings.canDrawOverlays(mContext)); + CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>(); + RemoteCallback cb = new RemoteCallback((Bundle result) -> { + PocStatus pocStatus = + new PocStatus(result.getInt(mContext.getString(R.string.statusKey)), + result.getString(mContext.getString(R.string.messageKey))); + callbackReturn.complete(pocStatus); + }); + intent.putExtra(mContext.getString(R.string.callbackKey), cb); + mContext.startService(intent); + PocStatus result = callbackReturn.get(resources.getInteger(R.integer.timeoutMs), + TimeUnit.MILLISECONDS); + assumeTrue(result.getErrorMessage(), + result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure)); + + /* Wait for the overlay window */ + Pattern overlayTextPattern = Pattern.compile( + mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE); + UiDevice device = UiDevice.getInstance(getInstrumentation()); + assumeTrue(mContext.getString(R.string.overlayUiScreenError), + device.wait(Until.hasObject(By.text(overlayTextPattern)), + mContext.getResources().getInteger(R.integer.timeoutMs))); + + /* Start PocActivity which starts the vulnerable activity */ + intent = new Intent(mContext, PocActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + CompletableFuture<PocStatus> pocActivityReturn = new CompletableFuture<>(); + RemoteCallback pocActivityCb = new RemoteCallback((Bundle pocActivityResult) -> { + PocStatus pocStatus = new PocStatus( + pocActivityResult.getInt(mContext.getString(R.string.statusKey)), + pocActivityResult.getString(mContext.getString(R.string.messageKey))); + pocActivityReturn.complete(pocStatus); + }); + intent.putExtra(mContext.getString(R.string.callbackKey), pocActivityCb); + mContext.startActivity(intent); + result = pocActivityReturn.get(resources.getInteger(R.integer.timeoutMs), + TimeUnit.MILLISECONDS); + assumeTrue(result.getErrorMessage(), + result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure)); + + /* Get the vulnerable activity name by using an alternative intent */ + Intent vulIntent = new Intent(mContext.getString(R.string.actionKeychainActivity)); + ResolveInfo ri = mContext.getPackageManager().resolveActivity(vulIntent, + PackageManager.MATCH_DEFAULT_ONLY); + String vulnerableActivityName = ri.activityInfo.name; + + /* Wait until the object of launcher activity is gone */ + boolean overlayDisallowed = device.wait(Until.gone(By.pkg(mContext.getPackageName())), + mContext.getResources().getInteger(R.integer.timeoutMs)); + + /* Check if the currently running activity is the vulnerable activity */ + String activityDump = ""; + activityDump = device.executeShellCommand( + mContext.getString(R.string.dumpsysActivity, vulnerableActivityName)); + Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue), + Pattern.CASE_INSENSITIVE); + assumeTrue( + mContext.getString(R.string.vulActivityNotRunningError, vulnerableActivityName), + activityPattern.matcher(activityDump).find()); + + /* Failing the test as fix is not present */ + assertTrue(mContext.getString(R.string.errorMessage, vulnerableActivityName), + overlayDisallowed); + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java new file mode 100644 index 00000000000..ac8ea15c6e0 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 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_0963; + +import android.app.Activity; +import android.os.Bundle; +import android.os.RemoteCallback; +import android.security.KeyChain; +import android.security.KeyChainAliasCallback; + +import androidx.annotation.Nullable; + +public class PocActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + try { + super.onCreate(savedInstanceState); + KeyChainAliasCallback callback = new KeyChainAliasCallback() { + @Override + public void alias(@Nullable String alias) {} + }; + KeyChain.choosePrivateKeyAlias(this, callback, null, null, null, -1, null); + sendTestResult(getResources().getInteger(R.integer.noException), ""); + } catch (Exception e) { + sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage()); + } + } + + void sendTestResult(int status, String message) { + try { + RemoteCallback cb = + (RemoteCallback) getIntent().getExtras().get(getString(R.string.callbackKey)); + Bundle res = new Bundle(); + res.putString(getString(R.string.messageKey), message); + res.putInt(getString(R.string.statusKey), status); + cb.sendResult(res); + } catch (Exception e) { + // ignore all exceptions + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java new file mode 100644 index 00000000000..5592323071b --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 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_0963; + +import android.app.admin.DeviceAdminReceiver; + +public class PocDeviceAdminReceiver extends DeviceAdminReceiver { +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java new file mode 100644 index 00000000000..b83e8247d54 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2022 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_0963; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteCallback; +import android.view.Gravity; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; +import android.widget.Button; + +public class PocService extends Service { + Button mButton; + WindowManager mWindowManager; + LayoutParams mLayoutParams; + Intent mIntent; + + private static int getScreenWidth() { + return Resources.getSystem().getDisplayMetrics().widthPixels; + } + + private static int getScreenHeight() { + return Resources.getSystem().getDisplayMetrics().heightPixels; + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + try { + mIntent = intent; + mWindowManager = getSystemService(WindowManager.class); + mLayoutParams = new LayoutParams(); + mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY; + mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | + 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; + Context context = getApplicationContext(); + mButton = new Button(context); + mButton.setText(context.getString(R.string.overlayButtonText)); + mWindowManager.addView(mButton, mLayoutParams); + sendTestResult(getResources().getInteger(R.integer.noException), ""); + } catch (Exception e) { + sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage()); + } + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() { + try { + mWindowManager.removeView(mButton); + } catch (Exception e) { + sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage()); + } + super.onDestroy(); + } + + void sendTestResult(int status, String message) { + try { + RemoteCallback cb = + (RemoteCallback) mIntent.getExtras().get(getString(R.string.callbackKey)); + Bundle res = new Bundle(); + res.putString(getString(R.string.messageKey), message); + res.putInt(getString(R.string.statusKey), status); + cb.sendResult(res); + } catch (Exception e) { + // ignore exception here + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java new file mode 100644 index 00000000000..de67f0ff104 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 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_0963; + +public class PocStatus { + int statusCode; + String errorMessage; + + public PocStatus(int status, String message) { + statusCode = status; + errorMessage = message; + } + + public int getStatusCode() { + return statusCode; + } + + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp new file mode 100644 index 00000000000..db557290d5c --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test_helper_app { + name: "CVE-2022-20475-target", + defaults: [ + "cts_support_defaults", + ], + srcs: [ + "src/**/*.java", + ], + test_suites: [ + "sts", + ], + sdk_version: "current", +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml new file mode 100644 index 00000000000..60fb528509e --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 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_2022_20475_target"> + <application android:allowTaskReparenting="true"> + <activity android:name=".TargetActivity" + android:exported="true" /> + </application> +</manifest> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml new file mode 100644 index 00000000000..c424970f77a --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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="bcastActionTarget">CVE_2022_20475_TargetActivity</string> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java new file mode 100644 index 00000000000..4b885c6a602 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 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_2022_20475_target; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class TargetActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + try { + super.onCreate(savedInstanceState); + sendBroadcast(new Intent(getString(R.string.bcastActionTarget))); + } catch (Exception ignored) { + } + } + + @Override + protected void onResume() { + try { + super.onResume(); + sendBroadcast(new Intent(getString(R.string.bcastActionTarget))); + } catch (Exception ignored) { + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp new file mode 100644 index 00000000000..043de9121ef --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test_helper_app { + name: "CVE-2022-20475-test", + defaults: [ + "cts_support_defaults", + ], + srcs: [ + "src/**/*.java", + ], + test_suites: [ + "sts", + ], + static_libs: [ + "androidx.test.core", + "androidx.test.rules", + ], + sdk_version: "current", +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml new file mode 100644 index 00000000000..2e35b65fc9b --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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_2022_20475_test"> + <application> + <activity android:name=".PocActivity" /> + <activity android:name=".HijackActivity" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.security.cts.CVE_2022_20475_test" /> +</manifest> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml new file mode 100644 index 00000000000..bbeb2c56bb2 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 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="activityTarget">android.security.cts.CVE_2022_20475_target.TargetActivity</string> + <string name="pkgTarget">android.security.cts.CVE_2022_20475_target</string> + <string name="bcastActionHijack">CVE_2022_20475_HijackActivity</string> + <string name="bcastActionTarget">CVE_2022_20475_TargetActivity</string> + <string name="msgFail">Device is vulnerable to b/240663194 !!</string> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java new file mode 100644 index 00000000000..53e4c3e7e4b --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 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_2022_20475_test; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; + +import static org.junit.Assume.assumeNoException; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@RunWith(AndroidJUnit4.class) +public class DeviceTest { + private static final int WAIT_MS = 5000; + + @Test + public void testCVE_2022_20475() { + try { + // Registering a receiver here to wait for a broadcast from either HijackActivity or + // TargetActivity + Context context = getApplicationContext(); + CompletableFuture<Boolean> hijackReturn = new CompletableFuture<>(); + CompletableFuture<Boolean> targetReturn = new CompletableFuture<>(); + final String bcastActionHijack = context.getString(R.string.bcastActionHijack); + final String bcastActionTarget = context.getString(R.string.bcastActionTarget); + BroadcastReceiver broadcastReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(bcastActionHijack)) { + hijackReturn.complete(true); + } else if (intent.getAction().equals(bcastActionTarget)) { + targetReturn.complete(true); + } + } + }; + IntentFilter filter = new IntentFilter(); + filter.addAction(bcastActionHijack); + filter.addAction(bcastActionTarget); + context.registerReceiver(broadcastReceiver, filter); + + // Start PocActivity which in turn starts both TargetActivity and HijackActivity + Intent intent = new Intent(context, PocActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + + // Waiting on callback from HijackActivity which is started last by PocActivity + hijackReturn.get(WAIT_MS, TimeUnit.MILLISECONDS); + + // Start TargetActivity + Intent targetIntent = new Intent(Intent.ACTION_MAIN); + final String pkgTarget = context.getString(R.string.pkgTarget); + targetIntent.setClassName(pkgTarget, context.getString(R.string.activityTarget)); + targetIntent.setFlags( + Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + context.startActivity(targetIntent); + + // Wait on callback from TargetActivity. On vulnerable device, TargetActivity would + // not start and HijackActivity would remain on screen so the test should fail due + // to timeout on callback. + try { + targetReturn.get(WAIT_MS, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + throw new AssertionError(context.getString(R.string.msgFail)); + } + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java new file mode 100644 index 00000000000..8ac03f65c7e --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 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_2022_20475_test; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class HijackActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + try { + super.onCreate(savedInstanceState); + sendBroadcast(new Intent(getString(R.string.bcastActionHijack))); + } catch (Exception ignored) { + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java new file mode 100644 index 00000000000..e1968a4aee6 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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_2022_20475_test; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class PocActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + try { + super.onCreate(savedInstanceState); + // Start TargetActivity + Intent targetIntent = new Intent(Intent.ACTION_MAIN); + targetIntent.setClassName(getString(R.string.pkgTarget), + getString(R.string.activityTarget)); + startActivity(targetIntent); + + // Start HijackActivity. On vulnerable device, this will be parented by the task + // android.security.cts.CVE_2022_20475_target + startActivity(new Intent(this, HijackActivity.class)); + } catch (Exception ignored) { + } + } +} diff --git a/hostsidetests/stagedinstall/Android.bp b/hostsidetests/stagedinstall/Android.bp index 2bab456ace5..35850fe53b0 100644 --- a/hostsidetests/stagedinstall/Android.bp +++ b/hostsidetests/stagedinstall/Android.bp @@ -605,13 +605,17 @@ prebuilt_apex { genrule { name: "deapexer.zip", tools: [ + "blkid", "deapexer", "debugfs_static", + "fsck.erofs", "soong_zip", ], cmd: "rm -rf mkdir $(genDir)/deapexer && mkdir $(genDir)/deapexer && " + "cp $(location deapexer) $(genDir)/deapexer && " + "cp $(location debugfs_static) $(genDir)/deapexer && " + + "cp $(location blkid) $(genDir)/deapexer && " + + "cp $(location fsck.erofs) $(genDir)/deapexer && " + "HOST_OUT_SHARED_LIBRARIES=$$(dirname $(location deapexer))/../lib64 && " + "cp $${HOST_OUT_SHARED_LIBRARIES}/libc++.* $(genDir)/deapexer && " + "$(location soong_zip) -o $(out) -C $(genDir)/deapexer -D $(genDir)/deapexer", diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java index ef03c1fda4c..1e52abdc1e4 100644 --- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java +++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java @@ -76,6 +76,8 @@ public class ApexShimValidationTest extends BaseHostJUnit4Test { private static final String DEAPEXING_FOLDER_NAME = "deapexing_"; private static final String DEAPEXER_FILE_NAME = "deapexer"; private static final String DEBUGFS_STATIC_FILE_NAME = "debugfs_static"; + private static final String BLKID_FILE_NAME = "blkid"; + private static final String FSCKEROFS_FILE_NAME = "fsck.erofs"; private static final long DEFAULT_RUN_TIMEOUT_MS = 30 * 1000L; @@ -148,12 +150,14 @@ public class ApexShimValidationTest extends BaseHostJUnit4Test { mDeapexingDir = FileUtil.createTempDir(DEAPEXING_FOLDER_NAME); final File deapexer = extractDeapexer(mDeapexingDir); final File debugfs = new File(mDeapexingDir, DEBUGFS_STATIC_FILE_NAME); + final File blkid = new File(mDeapexingDir, BLKID_FILE_NAME); + final File fsckerofs = new File(mDeapexingDir, FSCKEROFS_FILE_NAME); final List<File> apexes = extractApexes(mDeapexingDir); for (File apex : apexes) { final File outDir = new File(apex.getParent(), apex.getName().substring( 0, apex.getName().length() - APEX_FILE_SUFFIX.length())); try { - runDeapexerExtract(deapexer, debugfs, apex, outDir); + runDeapexerExtract(deapexer, debugfs, blkid, fsckerofs, apex, outDir); final List<File> apkFiles = FileUtil.findFiles(outDir, ".+\\.apk").stream() .map(str -> new File(str)).collect(Collectors.toList()); for (File apkFile : apkFiles) { @@ -252,6 +256,14 @@ public class ApexShimValidationTest extends BaseHostJUnit4Test { assertWithMessage("Can't find " + DEBUGFS_STATIC_FILE_NAME + " binary file") .that(debugfs).isNotNull(); debugfs.setExecutable(true); + final File blkid = FileUtil.findFile(destDir, BLKID_FILE_NAME); + assertWithMessage("Can't find " + BLKID_FILE_NAME + " binary file") + .that(debugfs).isNotNull(); + blkid.setExecutable(true); + final File fsckerofs = FileUtil.findFile(destDir, FSCKEROFS_FILE_NAME); + assertWithMessage("Can't find " + FSCKEROFS_FILE_NAME + " binary file") + .that(debugfs).isNotNull(); + fsckerofs.setExecutable(true); return deapexer; } @@ -290,7 +302,8 @@ public class ApexShimValidationTest extends BaseHostJUnit4Test { * @param apex The apex file to be extracted. * @param outDir The out folder. */ - private void runDeapexerExtract(File deapexer, File debugfs, File apex, File outDir) { + private void runDeapexerExtract(File deapexer, File debugfs, File blkid, File fsckerofs, + File apex, File outDir) { final RunUtil runUtil = new RunUtil(); final String os = System.getProperty("os.name").toLowerCase(); final boolean isMacOs = (os.startsWith("mac") || os.startsWith("darwin")); @@ -303,6 +316,10 @@ public class ApexShimValidationTest extends BaseHostJUnit4Test { deapexer.getAbsolutePath(), "--debugfs_path", debugfs.getAbsolutePath(), + "--blkid_path", + blkid.getAbsolutePath(), + "--fsckerofs_path", + fsckerofs.getAbsolutePath(), "extract", apex.getAbsolutePath(), outDir.getAbsolutePath()); diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java index 781be6b575f..9888e36b1cd 100644 --- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java +++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java @@ -39,7 +39,6 @@ import com.android.os.AtomsProto.CameraStateChanged; import com.android.os.AtomsProto.FlashlightStateChanged; import com.android.os.AtomsProto.ForegroundServiceAppOpSessionEnded; import com.android.os.AtomsProto.ForegroundServiceStateChanged; -import com.android.os.AtomsProto.GpsScanStateChanged; import com.android.os.AtomsProto.LmkKillOccurred; import com.android.os.AtomsProto.MediaCodecStateChanged; import com.android.os.AtomsProto.OverlayStateChanged; @@ -50,6 +49,7 @@ import com.android.os.AtomsProto.VibratorStateChanged; import com.android.os.AtomsProto.WakelockStateChanged; import com.android.os.AttributionNode; import com.android.os.StatsLog.EventMetricData; +import com.android.os.gps.GpsScanStateChanged; import com.android.tradefed.build.IBuildInfo; import com.android.tradefed.log.LogUtil; import com.android.tradefed.testtype.DeviceTestCase; diff --git a/hostsidetests/multidevices/uwb/snippet/Android.bp b/libs/webkit-shared/Android.bp index 2ad7dd2e308..b3032681d0e 100644 --- a/hostsidetests/multidevices/uwb/snippet/Android.bp +++ b/libs/webkit-shared/Android.bp @@ -11,25 +11,26 @@ // 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 { default_applicable_licenses: ["Android-Apache-2.0"], } -android_test { - name: "uwb_snippet", - sdk_version: "system_current", +java_library { + name: "ctswebkitsharedenv", srcs: [ - "UwbManagerSnippet.java", + "src/**/*.java", + "src/**/*.aidl", + ], + libs: [ + "android.test.base", ], - manifest: "AndroidManifest.xml", static_libs: [ - "androidx.test.runner", - "guava", - "mobly-snippet-lib", - "com.uwb.support.ccc", - "com.uwb.support.fira", - "com.uwb.support.generic", - "com.uwb.support.multichip", + "compatibility-device-util-axt", + "ctsdeviceutillegacy-axt", + "platform-test-annotations", + ], + visibility: [ + "//cts/tests/tests/webkit:__subpackages__", + "//cts/tests/tests/sdksandbox/webkit:__subpackages__", ], } diff --git a/libs/webkit-shared/OWNERS b/libs/webkit-shared/OWNERS new file mode 100644 index 00000000000..4d049f97749 --- /dev/null +++ b/libs/webkit-shared/OWNERS @@ -0,0 +1,2 @@ +# Bug component: 76427 +include /tests/tests/webkit/OWNERS
\ No newline at end of file diff --git a/libs/webkit-shared/README.md b/libs/webkit-shared/README.md new file mode 100644 index 00000000000..ac2a15b0c17 --- /dev/null +++ b/libs/webkit-shared/README.md @@ -0,0 +1,5 @@ +# Shared Webkit Environment + +This helper lib makes a test suite extendable to run +in both an activity based environment and within +the SDK Runtime.
\ No newline at end of file diff --git a/libs/webkit-shared/src/android/webkit/cts/IHostAppInvoker.aidl b/libs/webkit-shared/src/android/webkit/cts/IHostAppInvoker.aidl new file mode 100644 index 00000000000..d2ff7b508d7 --- /dev/null +++ b/libs/webkit-shared/src/android/webkit/cts/IHostAppInvoker.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 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.webkit.cts; + +import android.view.MotionEvent; + +/** + * This shared interface is used to invoke methods + * that belong to the activity of a test. + */ +interface IHostAppInvoker { + void waitForIdleSync(); + + void sendKeyDownUpSync(int keyCode); + + void sendPointerSync(in MotionEvent event); +} diff --git a/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTest.java b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTest.java new file mode 100644 index 00000000000..ef29810b93c --- /dev/null +++ b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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.webkit.cts; + +/** + * Extending this class indicates that a test can be shared between the SDK Runtime and Activity + * based tests. + * + * <p>If a test is shared, it will be expected to provide its own {@link + * SharedWebViewTestEnvironment} implementation. + */ +public abstract class SharedWebViewTest { + private SharedWebViewTestEnvironment mEnvironment; + + protected abstract SharedWebViewTestEnvironment createTestEnvironment(); + + public void setTestEnvironment(SharedWebViewTestEnvironment sharedWebViewTestEnvironment) { + mEnvironment = sharedWebViewTestEnvironment; + } + + protected SharedWebViewTestEnvironment getTestEnvironment() { + if (mEnvironment == null) { + mEnvironment = createTestEnvironment(); + } + return mEnvironment; + } +} diff --git a/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTestEnvironment.java b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTestEnvironment.java new file mode 100644 index 00000000000..e13350d1360 --- /dev/null +++ b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTestEnvironment.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2022 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.webkit.cts; + +import android.app.Instrumentation; +import android.content.Context; +import android.view.MotionEvent; +import android.webkit.WebView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.test.InstrumentationRegistry; + +/** + * This class contains all the environmental variables that need to be configured for WebView tests + * to either run inside the SDK Runtime or within an Activity. + */ +public final class SharedWebViewTestEnvironment { + @Nullable private final Context mContext; + @Nullable private final WebView mWebView; + @Nullable private final WebViewOnUiThread mWebViewOnUiThread; + @Nullable private final IHostAppInvoker mHostAppInvoker; + + private SharedWebViewTestEnvironment( + Context context, + WebView webView, + WebViewOnUiThread webViewOnUiThread, + IHostAppInvoker hostAppInvoker) { + mContext = context; + mWebView = webView; + mWebViewOnUiThread = webViewOnUiThread; + mHostAppInvoker = hostAppInvoker; + } + + @Nullable + public Context getContext() { + return mContext; + } + + @Nullable + public WebView getWebView() { + return mWebView; + } + + @Nullable + public WebViewOnUiThread getWebViewOnUiThread() { + return mWebViewOnUiThread; + } + + /** + * Invokes waitForIdleSync on the {@link Instrumentation} + * in the activity. + */ + public void waitForIdleSync() throws Exception { + mHostAppInvoker.waitForIdleSync(); + } + + /** + * Invokes sendKeyDownUpSync on the {@link Instrumentation} + * in the activity. + */ + public void sendKeyDownUpSync(int keyCode) throws Exception { + mHostAppInvoker.sendKeyDownUpSync(keyCode); + } + + /** + * Invokes sendPointerSync on the {@link Instrumentation} + * in the activity. + */ + public void sendPointerSync(MotionEvent event) throws Exception { + mHostAppInvoker.sendPointerSync(event); + } + + /** + * Use this builder to create a {@link SharedWebViewTestEnvironment}. + * The {@link SharedWebViewTestEnvironment} can not be built directly. + */ + public static final class Builder { + private Context mContext; + private WebView mWebView; + private WebViewOnUiThread mWebViewOnUiThread; + private IHostAppInvoker mHostAppInvoker; + + /** + * Provide a {@link Context} the tests should use + * for your environment. + */ + public Builder setContext(@NonNull Context context) { + mContext = context; + return this; + } + + /** + * Provide a {@link WebView} the tests should use + * for your environment. + */ + public Builder setWebView(@NonNull WebView webView) { + mWebView = webView; + return this; + } + + /** + * Provide a {@link WebViewOnUiThread} the tests should use + * for your environment. + */ + public Builder setWebViewOnUiThread(@NonNull WebViewOnUiThread webViewOnUiThread) { + mWebViewOnUiThread = webViewOnUiThread; + return this; + } + + /** + * Provide a {@link IHostAppInvoker} the tests should use + * for your environment. + * + * This can be created with {@link createHostAppInvoker}. + * + * Note: This is required. + */ + public Builder setHostAppInvoker(@NonNull IHostAppInvoker hostAppInvoker) { + mHostAppInvoker = hostAppInvoker; + return this; + } + + /** + * Build a new SharedWebViewTestEnvironment. + */ + public SharedWebViewTestEnvironment build() { + if (mHostAppInvoker == null) { + throw new NullPointerException("The host app invoker is required"); + } + return new SharedWebViewTestEnvironment( + mContext, mWebView, mWebViewOnUiThread, mHostAppInvoker); + } + } + + /** + * This will generate a new {@link IHostAppInvoker} binder node. This should be called from + * wherever the activity exists for test cases. + */ + public static IHostAppInvoker.Stub createHostAppInvoker() { + return new IHostAppInvoker.Stub() { + private Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); + + public void waitForIdleSync() { + mInstrumentation.waitForIdleSync(); + } + + public void sendKeyDownUpSync(int keyCode) { + mInstrumentation.sendKeyDownUpSync(keyCode); + } + + public void sendPointerSync(MotionEvent event) { + mInstrumentation.sendPointerSync(event); + } + }; + } +} diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java index c89716f8d27..d4caef85f74 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java @@ -16,14 +16,14 @@ package android.photopicker.cts; -import static android.os.SystemProperties.getBoolean; +import static android.photopicker.cts.PhotoPickerCloudUtils.addImage; +import static android.photopicker.cts.PhotoPickerCloudUtils.containsExcept; +import static android.photopicker.cts.PhotoPickerCloudUtils.extractMediaIds; import static android.photopicker.cts.PickerProviderMediaGenerator.MediaGenerator; import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider; import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider; import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris; import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia; -import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton; -import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList; import static android.photopicker.cts.util.ResultsAssertionsUtils.assertRedactedReadOnlyAccess; import static android.provider.MediaStore.PickerMediaColumns; @@ -47,10 +47,8 @@ import android.util.Pair; import androidx.test.filters.SdkSuppress; import androidx.test.runner.AndroidJUnit4; -import androidx.test.uiautomator.UiObject; import org.junit.After; -import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -94,8 +92,6 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { mCloudSecondaryMediaGenerator.setMediaCollectionId(COLLECTION_1); setCloudProvider(mContext, null); - - Assume.assumeTrue(getBoolean("sys.photopicker.pickerdb.enabled", true)); } @After @@ -112,7 +108,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { public void testCloudOnlySync() throws Exception { initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1)); - final ClipData clipData = fetchPickerMedia(1); + final ClipData clipData = launchPickerAndFetchMedia(1); final List<String> mediaIds = extractMediaIds(clipData, 1); assertThat(mediaIds).containsExactly(CLOUD_ID1); @@ -123,7 +119,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { mUriList.addAll(createImagesAndGetUris(1, mContext.getUserId())); initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1)); - final ClipData clipData = fetchPickerMedia(2); + final ClipData clipData = launchPickerAndFetchMedia(2); final List<String> mediaIds = extractMediaIds(clipData, 2); assertThat(mediaIds).containsExactly(CLOUD_ID1, mUriList.get(0).getLastPathSegment()); @@ -135,7 +131,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { initPrimaryCloudProviderWithImage(Pair.create(mUriList.get(0).getLastPathSegment(), CLOUD_ID1)); - final ClipData clipData = fetchPickerMedia(1); + final ClipData clipData = launchPickerAndFetchMedia(1); final List<String> mediaIds = extractMediaIds(clipData, 1); containsExcept(mediaIds, mUriList.get(0).getLastPathSegment(), CLOUD_ID1); @@ -146,7 +142,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2)); - ClipData clipData = fetchPickerMedia(2); + ClipData clipData = launchPickerAndFetchMedia(2); List<String> mediaIds = extractMediaIds(clipData, 2); assertThat(mediaIds).containsExactly(CLOUD_ID1, CLOUD_ID2); @@ -155,7 +151,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { /* trackDeleted */ true); syncCloudProvider(mContext); - clipData = fetchPickerMedia(2); + clipData = launchPickerAndFetchMedia(2); mediaIds = extractMediaIds(clipData, 1); containsExcept(mediaIds, CLOUD_ID2, CLOUD_ID1); @@ -166,7 +162,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2)); - ClipData clipData = fetchPickerMedia(2); + ClipData clipData = launchPickerAndFetchMedia(2); List<String> mediaIds = extractMediaIds(clipData, 2); assertThat(mediaIds).containsExactly(CLOUD_ID1, CLOUD_ID2); @@ -175,7 +171,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { /* trackDeleted */ false); syncCloudProvider(mContext); - clipData = fetchPickerMedia(2); + clipData = launchPickerAndFetchMedia(2); mediaIds = extractMediaIds(clipData, 2); assertThat(mediaIds).containsExactly(CLOUD_ID1, CLOUD_ID2); @@ -183,7 +179,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { mCloudPrimaryMediaGenerator.setMediaCollectionId(COLLECTION_2); syncCloudProvider(mContext); - clipData = fetchPickerMedia(2); + clipData = launchPickerAndFetchMedia(2); mediaIds = extractMediaIds(clipData, 1); containsExcept(mediaIds, CLOUD_ID2, CLOUD_ID1); @@ -213,7 +209,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { syncCloudProvider(mContext); - ClipData clipData = fetchPickerMedia(2); + ClipData clipData = launchPickerAndFetchMedia(2); List<String> mediaIds = extractMediaIds(clipData, 1); containsExcept(mediaIds, CLOUD_ID1, CLOUD_ID2); @@ -222,7 +218,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(), CloudProviderPrimary.AUTHORITY)).isFalse(); - clipData = fetchPickerMedia(2); + clipData = launchPickerAndFetchMedia(2); mediaIds = extractMediaIds(clipData, 1); containsExcept(mediaIds, CLOUD_ID2, CLOUD_ID1); @@ -243,7 +239,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { public void testUriAccessWithValidProjection() throws Exception { initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1)); - final ClipData clipData = fetchPickerMedia(1); + final ClipData clipData = launchPickerAndFetchMedia(1); final List<String> mediaIds = extractMediaIds(clipData, 1); assertThat(mediaIds).containsExactly(CLOUD_ID1); @@ -278,7 +274,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { public void testUriAccessWithInvalidProjection() throws Exception { initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1)); - final ClipData clipData = fetchPickerMedia(1); + final ClipData clipData = launchPickerAndFetchMedia(1); final List<String> mediaIds = extractMediaIds(clipData, 1); assertThat(mediaIds).containsExactly(CLOUD_ID1); @@ -310,7 +306,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { // Sleep because the notification API throttles requests with a 1s delay Thread.sleep(1500); - ClipData clipData = fetchPickerMedia(1); + ClipData clipData = launchPickerAndFetchMedia(1); List<String> mediaIds = extractMediaIds(clipData, 1); assertThat(mediaIds).containsNoneIn(Collections.singletonList(CLOUD_ID1)); @@ -330,7 +326,7 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { // Sleep because the notification API throttles requests with a 1s delay Thread.sleep(1500); - clipData = fetchPickerMedia(1); + clipData = launchPickerAndFetchMedia(1); mediaIds = extractMediaIds(clipData, 1); assertThat(mediaIds).containsExactly(CLOUD_ID1); @@ -353,60 +349,17 @@ public class CloudPhotoPickerTest extends PhotoPickerBaseTest { assertThat(storageManager.getCloudMediaProvider()).isNull(); } - private List<String> extractMediaIds(ClipData clipData, int minCount) { - final int count = clipData.getItemCount(); - assertThat(count).isAtLeast(minCount); - - final List<String> mediaIds = new ArrayList<>(); - for (int i = 0; i < count; i++) { - mediaIds.add(clipData.getItemAt(i).getUri().getLastPathSegment()); - } - - return mediaIds; - } - - private ClipData fetchPickerMedia(int maxCount) throws Exception { + private ClipData launchPickerAndFetchMedia(int maxCount) throws Exception { final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); mActivity.startActivityForResult(intent, REQUEST_CODE); - final List<UiObject> itemList = findItemList(maxCount); - for (int i = 0; i < itemList.size(); i++) { - final UiObject item = itemList.get(i); - item.click(); - sDevice.waitForIdle(); - } - - final UiObject addButton = findAddButton(); - addButton.click(); - sDevice.waitForIdle(); - - return mActivity.getResult().data.getClipData(); + return PhotoPickerCloudUtils.fetchPickerMedia(mActivity, sDevice, maxCount); } private void initPrimaryCloudProviderWithImage(Pair<String, String>... mediaPairs) throws Exception { - setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY); - assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(), - CloudProviderPrimary.AUTHORITY)).isTrue(); - - for (Pair<String, String> pair: mediaPairs) { - addImage(mCloudPrimaryMediaGenerator, pair.first, pair.second); - } - - syncCloudProvider(mContext); - } - - private void addImage(MediaGenerator generator, String localId, String cloudId) - throws Exception { - generator.addMedia(localId, cloudId, /* albumId */ null, "image/jpeg", - /* mimeTypeExtension */ 0, IMAGE_SIZE_BYTES, /* isFavorite */ false, - R.raw.lg_g4_iso_800_jpg); - } - - private static void containsExcept(List<String> mediaIds, String contained, - String notContained) { - assertThat(mediaIds).contains(contained); - assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained)); + PhotoPickerCloudUtils.initCloudProviderWithImage(mContext, mCloudPrimaryMediaGenerator, + CloudProviderPrimary.AUTHORITY, mediaPairs); } } diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java index ca5a251cbb8..8a593a465ee 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java @@ -19,10 +19,14 @@ package android.photopicker.cts; import android.app.Instrumentation; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import androidx.test.InstrumentationRegistry; import androidx.test.uiautomator.UiDevice; +import com.android.bedstead.harrier.annotations.BeforeClass; + +import org.junit.Assume; import org.junit.Before; /** @@ -38,6 +42,11 @@ public class PhotoPickerBaseTest { protected GetResultActivity mActivity; protected Context mContext; + @BeforeClass + public static void setUpClass() { + Assume.assumeTrue(isHardwareSupported()); + } + @Before public void setUp() throws Exception { final String setSyncDelayCommand = @@ -58,4 +67,14 @@ public class PhotoPickerBaseTest { mActivity.clearResult(); sDevice.waitForIdle(); } + + private static boolean isHardwareSupported() { + // These UI tests are not optimised for Watches, TVs, Auto; + // IoT devices do not have a UI to run these UI tests + PackageManager pm = sInstrumentation.getContext().getPackageManager(); + return !pm.hasSystemFeature(pm.FEATURE_EMBEDDED) + && !pm.hasSystemFeature(pm.FEATURE_WATCH) + && !pm.hasSystemFeature(pm.FEATURE_LEANBACK) + && !pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE); + } } diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java new file mode 100644 index 00000000000..204eb1ca974 --- /dev/null +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 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.photopicker.cts; + +import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider; +import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider; +import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton; +import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.ClipData; +import android.content.Context; +import android.provider.MediaStore; +import android.util.Pair; + +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class PhotoPickerCloudUtils { + public static List<String> extractMediaIds(ClipData clipData, int minCount) { + final int count = clipData.getItemCount(); + assertThat(count).isAtLeast(minCount); + + final List<String> mediaIds = new ArrayList<>(); + for (int i = 0; i < count; i++) { + mediaIds.add(clipData.getItemAt(i).getUri().getLastPathSegment()); + } + + return mediaIds; + } + + public static ClipData fetchPickerMedia(GetResultActivity activity, UiDevice uiDevice, + int maxCount) throws Exception { + final List<UiObject> itemList = findItemList(maxCount); + for (int i = 0; i < itemList.size(); i++) { + final UiObject item = itemList.get(i); + item.click(); + uiDevice.waitForIdle(); + } + + final UiObject addButton = findAddButton(); + addButton.click(); + uiDevice.waitForIdle(); + + return activity.getResult().data.getClipData(); + } + + public static void initCloudProviderWithImage( + Context context, PickerProviderMediaGenerator.MediaGenerator mediaGenerator, + String authority, Pair<String, String>... mediaPairs) throws Exception { + setCloudProvider(context, authority); + assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(context.getContentResolver(), + authority)).isTrue(); + + for (Pair<String, String> pair : mediaPairs) { + addImage(mediaGenerator, pair.first, pair.second); + } + + syncCloudProvider(context); + } + + public static void addImage(PickerProviderMediaGenerator.MediaGenerator generator, + String localId, String cloudId) + throws Exception { + final long imageSizeBytes = 107684; + generator.addMedia(localId, cloudId, /* albumId */ null, "image/jpeg", + /* mimeTypeExtension */ 0, imageSizeBytes, /* isFavorite */ false, + R.raw.lg_g4_iso_800_jpg); + } + + public static void containsExcept(List<String> mediaIds, String contained, + String notContained) { + assertThat(mediaIds).contains(contained); + assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained)); + } +} diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java index 83fefd45c70..d0715e3f699 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerSettingsTest.java @@ -16,48 +16,49 @@ package android.photopicker.cts; -import static android.os.SystemProperties.getBoolean; +import static android.photopicker.cts.util.PhotoPickerUiUtils.isPhotoPickerVisible; import static android.photopicker.cts.util.PhotoPickerUiUtils.verifyActionBarExists; import static android.photopicker.cts.util.PhotoPickerUiUtils.verifySettingsActivityIsVisible; import android.content.Intent; +import android.os.Build; import android.photopicker.cts.util.PhotoPickerUiUtils; import android.provider.MediaStore; +import androidx.test.filters.SdkSuppress; import androidx.test.uiautomator.UiObject; import org.junit.AfterClass; import org.junit.Assume; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; +import java.io.IOException; + /** * Photo Picker tests for settings page launched from the overflow menu in PhotoPickerActivity or * the Settings app. */ +// TODO(b/195009187): Enabling settings page requires setting allowed_cloud_providers device config. +// We currently can't do this in R. +@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) public class PhotoPickerSettingsTest extends PhotoPickerBaseTest { private static final String NAMESPACE_STORAGE_NATIVE_BOOT = "storage_native_boot"; private static final String ALLOWED_CLOUD_PROVIDERS_KEY = "allowed_cloud_providers"; - private static final String SETTINGS_SYS_PROP = - "debug.photopicker.enable_settings_screen"; private static String sPreviouslyAllowedCloudProviders; @BeforeClass public static void setUpBeforeClass() throws Exception { // Store current allowed cloud providers for reset at the end of tests. - sPreviouslyAllowedCloudProviders = sDevice.executeShellCommand( - String.format("device_config get %s %s", NAMESPACE_STORAGE_NATIVE_BOOT, - ALLOWED_CLOUD_PROVIDERS_KEY)); + sPreviouslyAllowedCloudProviders = getAllowedProvidersDeviceConfig(); // Enable Settings menu item in PhotoPickerActivity's overflow menu. sDevice.executeShellCommand( String.format("device_config put %s %s not_empty", NAMESPACE_STORAGE_NATIVE_BOOT, ALLOWED_CLOUD_PROVIDERS_KEY)); - sDevice.executeShellCommand(String.format("setprop %s true", SETTINGS_SYS_PROP)); - Assume.assumeTrue(getBoolean(SETTINGS_SYS_PROP, false)); + Assume.assumeTrue(!getAllowedProvidersDeviceConfig().isBlank()); } @AfterClass @@ -74,18 +75,15 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest { String.format("device_config put %s %s %s", NAMESPACE_STORAGE_NATIVE_BOOT, ALLOWED_CLOUD_PROVIDERS_KEY, sPreviouslyAllowedCloudProviders)); } - - // Disable Settings menu item in PhotoPickerActivity's overflow menu. - sDevice.executeShellCommand(String.format("setprop %s false", SETTINGS_SYS_PROP)); - Assume.assumeFalse(getBoolean(SETTINGS_SYS_PROP, true)); } @Test - @Ignore("TODO(b/195009187): Enable this test once fixed and settings activity is enabled.") public void testSettingsLaunchFromOverflowMenu() throws Exception { // Launch PhotoPickerActivity. final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); mActivity.startActivityForResult(intent, REQUEST_CODE); + sDevice.waitForIdle(); + Assume.assumeTrue("Assume photo picker activity is visible", isPhotoPickerVisible()); // Click on the Settings menu item in the overflow menu. final UiObject settingsMenuItem = PhotoPickerUiUtils.findSettingsOverflowMenuItem(sDevice); @@ -93,6 +91,12 @@ public class PhotoPickerSettingsTest extends PhotoPickerBaseTest { // Verify PhotoPickerSettingsActivity is launched and visible. verifySettingsActivityIsVisible(sDevice); - verifyActionBarExists(sDevice); + verifyActionBarExists(); + } + + private static String getAllowedProvidersDeviceConfig() throws IOException { + return sDevice.executeShellCommand( + String.format("device_config get %s %s", NAMESPACE_STORAGE_NATIVE_BOOT, + ALLOWED_CLOUD_PROVIDERS_KEY)); } } diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java index 20b22c56acf..10142e81ed2 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java @@ -16,7 +16,6 @@ package android.photopicker.cts; -import static android.os.SystemProperties.getBoolean; import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider; import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider; import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia; @@ -52,7 +51,6 @@ import androidx.test.uiautomator.UiObject; import androidx.test.uiautomator.UiSelector; import org.junit.After; -import org.junit.Assume; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -90,11 +88,6 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest { public void setUp() throws Exception { super.setUp(); - Assume.assumeTrue(getBoolean("sys.photopicker.pickerdb.enabled", true)); - - sDevice.executeShellCommand("setprop sys.photopicker.remote_preview true"); - Assume.assumeTrue(getBoolean("sys.photopicker.remote_preview", true)); - mCloudPrimaryMediaGenerator = PickerProviderMediaGenerator.getMediaGenerator( mContext, CloudProviderPrimary.AUTHORITY); mCloudPrimaryMediaGenerator.resetAll(); @@ -170,16 +163,14 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest { // Remote Preview calls onSurfaceCreated with monotonically increasing surfaceIds final int surfaceIdForSecondVideoPreview = 1; - verifyAdjacentVideoSwipe(surfaceIdForFirstVideoPreview, surfaceIdForSecondVideoPreview, - CLOUD_ID1); + verifyAdjacentVideoSwipe(surfaceIdForSecondVideoPreview, CLOUD_ID1); // Swipe right in preview mode and go to first video, but the surface id will have // increased monotonically swipeRightAndWait(); final int surfaceIdForThirdVideoPreview = 2; - verifyAdjacentVideoSwipe(surfaceIdForSecondVideoPreview, surfaceIdForThirdVideoPreview, - CLOUD_ID2); + verifyAdjacentVideoSwipe(surfaceIdForThirdVideoPreview, CLOUD_ID2); final UiObject addButton = findPreviewAddButton(); addButton.click(); @@ -264,19 +255,17 @@ public class RemoteVideoPreviewTest extends PhotoPickerBaseTest { * Verify surface controller interactions on swiping from one video to another. * Note: This test assumes that the first video is in playing state. * - * @param oldSurfaceId the Surface ID which we are swiping away from * @param newSurfaceId the Surface ID to which we are swiping * @param newMediaId the media ID of the video we are swiping to */ - private void verifyAdjacentVideoSwipe(int oldSurfaceId, int newSurfaceId, String newMediaId) + private void verifyAdjacentVideoSwipe(int newSurfaceId, String newMediaId) throws Exception { + // We cannot be sure of the order of onSurfaceDestroyed(oldSurfaceId) and + // onSurfaceCreated(newSurfaceId) calls since the Surface lifecycle is not in our control, + // hence we cannot verify the two calls were made using InOrder mock. mAssertInOrder.verify(mSurfaceControllerListener).onSurfaceCreated(eq(newSurfaceId), any(), eq(newMediaId)); - // The surface for the first video is destroyed when it is no longer visible on the screen - // (swipe is complete). - mAssertInOrder.verify(mSurfaceControllerListener).onSurfaceDestroyed(eq(oldSurfaceId)); - verifyPlaybackStartedWhenPlayerReady(newSurfaceId); } diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java index 5cdb5927ea3..49a4eb40e1a 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java @@ -105,7 +105,7 @@ public class PhotoPickerUiUtils { public static UiObject findSettingsOverflowMenuItem(UiDevice uiDevice) throws Exception { final UiObject overflowMenu = getOverflowMenuObject(uiDevice); clickAndWait(uiDevice, overflowMenu); - return new UiObject(new UiSelector().textContains("Settings")); + return new UiObject(new UiSelector().textContains("Cloud media app")); } public static UiObject getOverflowMenuObject(UiDevice uiDevice) { @@ -114,7 +114,12 @@ public class PhotoPickerUiUtils { return new UiObject(new UiSelector().description("More options")); } - public static void verifyActionBarExists(UiDevice uiDevice) { + public static boolean isPhotoPickerVisible() { + return new UiObject(new UiSelector().resourceIdMatches( + PhotoPickerUiUtils.REGEX_PACKAGE_NAME + ":id/bottom_sheet")).waitForExists(TIMEOUT); + } + + public static void verifyActionBarExists() { assertWithMessage("Timed out waiting for action bar to appear") .that(new UiObject(new UiSelector() .resourceIdMatches(REGEX_PACKAGE_NAME + ":id/action_bar")) diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml index 98189620bab..caf9428f9c5 100644 --- a/tests/tests/bluetooth/AndroidTest.xml +++ b/tests/tests/bluetooth/AndroidTest.xml @@ -34,5 +34,6 @@ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> <option name="mainline-module-package-name" value="com.android.btservices" /> + <option name="mainline-module-package-name" value="com.google.android.btservices" /> </object> </configuration> diff --git a/tests/uwb/Android.bp b/tests/tests/hibernation/Android.bp index 55e7ba628d2..3bb187f5d60 100644 --- a/tests/uwb/Android.bp +++ b/tests/tests/hibernation/Android.bp @@ -1,4 +1,4 @@ -// Copyright (C) 2021 The Android Open Source Project +// Copyright (C) 2022 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. @@ -17,27 +17,49 @@ package { } android_test { - name: "CtsUwbTestCases", + name: "CtsHibernationTestCases", defaults: [ "cts_defaults", - "framework-uwb-cts-defaults", + "mts-target-sdk-version-current", ], + compile_multilib: "both", + static_libs: [ + "androidx.test.core", + "androidx.test.ext.junit", + "androidx.test.rules", + "androidx.test.uiautomator_uiautomator", + "compatibility-device-util-axt", + "ctstestrunner-axt", + "testng", + "truth-prebuilt", + "guava", + "junit", + "hamcrest-library", + "modules-utils-build_system", + "safety-center-internal-data", + ], + srcs: [ + "src/**/*.kt", + ], + test_config: "AndroidTest.xml", // Tag this module as a cts test artifact test_suites: [ "cts", "general-tests", - "mts-uwb", + "mts-permission", ], - libs: ["android.test.runner"], - static_libs: [ - "androidx.test.ext.junit", - "ctstestrunner-axt", - "compatibility-device-util-axt", - "mockito-target-minus-junit4", - "com.uwb.support.fira", - "com.uwb.support.multichip", - "com.uwb.support.oemextension", + sdk_version: "test_current", + libs: [ + "android.test.runner", + "android.test.base", + ], + // Do not compress minijail policy files. + aaptflags: ["-0 .policy"], + min_sdk_version: "29", + data: [ + ":CtsAutoRevokeQApp", + ":CtsAutoRevokeSApp", + ":CtsAutoRevokeRApp", ], - srcs: ["src/**/*.java"], - platform_apis: true, + per_testcase_directory: true, } diff --git a/tests/tests/hibernation/AndroidManifest.xml b/tests/tests/hibernation/AndroidManifest.xml new file mode 100644 index 00000000000..80ccd376851 --- /dev/null +++ b/tests/tests/hibernation/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (C) 2022 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.hibernation.cts"> + + <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.hibernation.cts" + android:label="CTS tests of android.hibernation"> + <meta-data android:name="listener" + android:value="com.android.cts.runner.CtsTestRunListener"/> + </instrumentation> + +</manifest> diff --git a/tests/tests/hibernation/AndroidTest.xml b/tests/tests/hibernation/AndroidTest.xml new file mode 100644 index 00000000000..b5b82d27c14 --- /dev/null +++ b/tests/tests/hibernation/AndroidTest.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 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. +--> +<configuration description="Configuration for Hibernation Tests"> + <option name="test-suite-tag" value="cts" /> + <option name="config-descriptor:metadata" key="component" value="framework" /> + <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" /> + <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> + <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> + <option name="config-descriptor:metadata" key="parameter" value="multiuser" /> + <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.permission.apex" /> + <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" /> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="CtsHibernationTestCases.apk" /> + </target_preparer> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="android.hibernation.cts" /> + <option name="runtime-hint" value="3m15s" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + </test> + + <!-- Create Place to store apks --> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="run-command" value="mkdir -p /data/local/tmp/cts/hibernation" /> + <option name="run-command" value="am wait-for-broadcast-idle" /> + <option name="teardown-command" value="rm -rf /data/local/tmp/cts/hibernation" /> + </target_preparer> + <!-- Load additional APKs onto device --> + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="push" value="CtsAutoRevokeSApp.apk->/data/local/tmp/cts/hibernation/CtsAutoRevokeSApp.apk" /> + <option name="push" value="CtsAutoRevokeRApp.apk->/data/local/tmp/cts/hibernation/CtsAutoRevokeRApp.apk" /> + <option name="push" value="CtsAutoRevokeQApp.apk->/data/local/tmp/cts/hibernation/CtsAutoRevokeQApp.apk" /> + </target_preparer> +</configuration> diff --git a/tests/tests/os/AutoRevokeQApp/Android.bp b/tests/tests/hibernation/AutoRevokeQApp/Android.bp index 5c7d4b926d4..a4a57fa5b89 100644 --- a/tests/tests/os/AutoRevokeQApp/Android.bp +++ b/tests/tests/hibernation/AutoRevokeQApp/Android.bp @@ -33,5 +33,8 @@ android_test_helper_app { "general-tests", "sts", ], - srcs: ["src/**/*.java", "src/**/*.kt"], + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], } diff --git a/tests/tests/os/AutoRevokeQApp/AndroidManifest.xml b/tests/tests/hibernation/AutoRevokeQApp/AndroidManifest.xml index c6355eb693a..c307b8476a6 100644 --- a/tests/tests/os/AutoRevokeQApp/AndroidManifest.xml +++ b/tests/tests/hibernation/AutoRevokeQApp/AndroidManifest.xml @@ -16,12 +16,12 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="android.os.cts.autorevokeqapp"> + package="android.hibernation.cts.autorevokeqapp"> <uses-permission android:name="android.permission.READ_CALENDAR" /> <application> - <activity android:name="android.os.cts.autorevokeqapp.MainActivity" + <activity android:name="android.hibernation.cts.autorevokeqapp.MainActivity" android:exported="true" android:visibleToInstantApps="true" > <intent-filter> diff --git a/tests/tests/os/AutoRevokeQApp/src/android/os/cts/autorevokeqapp/MainActivity.kt b/tests/tests/hibernation/AutoRevokeQApp/src/android/hibernation/cts/autorevokeqapp/MainActivity.kt index 101f2008d64..22feb544188 100644 --- a/tests/tests/os/AutoRevokeQApp/src/android/os/cts/autorevokeqapp/MainActivity.kt +++ b/tests/tests/hibernation/AutoRevokeQApp/src/android/hibernation/cts/autorevokeqapp/MainActivity.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.os.cts.autorevokeqapp +package android.hibernation.cts.autorevokeqapp import android.app.Activity import android.os.Bundle diff --git a/tests/tests/os/AutoRevokeRApp/Android.bp b/tests/tests/hibernation/AutoRevokeRApp/Android.bp index 8e013887a1e..f1d92ca038a 100644 --- a/tests/tests/os/AutoRevokeRApp/Android.bp +++ b/tests/tests/hibernation/AutoRevokeRApp/Android.bp @@ -32,5 +32,8 @@ android_test_helper_app { "general-tests", "sts", ], - srcs: ["src/**/*.java", "src/**/*.kt"], + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], } diff --git a/tests/tests/os/AutoRevokeRApp/AndroidManifest.xml b/tests/tests/hibernation/AutoRevokeRApp/AndroidManifest.xml index 91777a0d262..1c2cbb0ab20 100644 --- a/tests/tests/os/AutoRevokeRApp/AndroidManifest.xml +++ b/tests/tests/hibernation/AutoRevokeRApp/AndroidManifest.xml @@ -16,14 +16,14 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="android.os.cts.autorevokerapp"> + package="android.hibernation.cts.autorevokerapp"> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <application> - <activity android:name="android.os.cts.autorevokerapp.MainActivity" + <activity android:name="android.hibernation.cts.autorevokerapp.MainActivity" android:exported="true" android:visibleToInstantApps="true" > <intent-filter> diff --git a/tests/tests/os/AutoRevokeRApp/src/android/os/cts/autorevokerapp/MainActivity.kt b/tests/tests/hibernation/AutoRevokeRApp/src/android/hibernation/cts/autorevokerapp/MainActivity.kt index c97f88369a7..5f3d0ae4f53 100644 --- a/tests/tests/os/AutoRevokeRApp/src/android/os/cts/autorevokerapp/MainActivity.kt +++ b/tests/tests/hibernation/AutoRevokeRApp/src/android/hibernation/cts/autorevokerapp/MainActivity.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.os.cts.autorevokerapp +package android.hibernation.cts.autorevokerapp import android.app.Activity import android.content.Intent diff --git a/tests/tests/os/AutoRevokeSApp/Android.bp b/tests/tests/hibernation/AutoRevokeSApp/Android.bp index 60ca80fabb2..11255920315 100644 --- a/tests/tests/os/AutoRevokeSApp/Android.bp +++ b/tests/tests/hibernation/AutoRevokeSApp/Android.bp @@ -32,5 +32,8 @@ android_test_helper_app { "general-tests", "sts", ], - srcs: ["src/**/*.java", "src/**/*.kt"], + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], } diff --git a/tests/tests/os/AutoRevokeSApp/AndroidManifest.xml b/tests/tests/hibernation/AutoRevokeSApp/AndroidManifest.xml index 08478e80bd8..b33a5461793 100644 --- a/tests/tests/os/AutoRevokeSApp/AndroidManifest.xml +++ b/tests/tests/hibernation/AutoRevokeSApp/AndroidManifest.xml @@ -16,13 +16,13 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="android.os.cts.autorevokesapp"> + package="android.hibernation.cts.autorevokesapp"> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <application> - <activity android:name="android.os.cts.autorevokesapp.MainActivity" + <activity android:name="android.hibernation.cts.autorevokesapp.MainActivity" android:exported="true" android:visibleToInstantApps="true" > <intent-filter> diff --git a/tests/tests/os/AutoRevokeSApp/src/android/os/cts/autorevokesapp/MainActivity.kt b/tests/tests/hibernation/AutoRevokeSApp/src/android/hibernation/cts/autorevokesapp/MainActivity.kt index c04efb23cad..e1f5842d404 100644 --- a/tests/tests/os/AutoRevokeSApp/src/android/os/cts/autorevokesapp/MainActivity.kt +++ b/tests/tests/hibernation/AutoRevokeSApp/src/android/hibernation/cts/autorevokesapp/MainActivity.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.os.cts.autorevokesapp +package android.hibernation.cts.autorevokesapp import android.app.Activity import android.content.Intent diff --git a/tests/tests/hibernation/OWNERS b/tests/tests/hibernation/OWNERS new file mode 100644 index 00000000000..002ca5d8681 --- /dev/null +++ b/tests/tests/hibernation/OWNERS @@ -0,0 +1,5 @@ +# Bug component: 1051079 +include platform/frameworks/base:/core/java/android/apphibernation/OWNERS +include platform/frameworks/base:/core/java/android/permission/OWNERS + +per-file *AppHibernationIntegration* = file:platform/frameworks/base:/core/java/android/apphibernation/OWNERS
\ No newline at end of file diff --git a/tests/tests/hibernation/TEST_MAPPING b/tests/tests/hibernation/TEST_MAPPING new file mode 100644 index 00000000000..742357e1051 --- /dev/null +++ b/tests/tests/hibernation/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "CtsHibernationTestCases" + } + ] +} diff --git a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationIntegrationTest.kt index 26473eda4b7..e5b93282b47 100644 --- a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt +++ b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationIntegrationTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.os.cts +package android.hibernation.cts import android.app.ActivityManager import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE @@ -46,11 +46,13 @@ import androidx.test.runner.AndroidJUnit4 import com.android.compatibility.common.util.DisableAnimationRule import com.android.compatibility.common.util.FreezeRotationRule import com.android.compatibility.common.util.SystemUtil +import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity import com.android.compatibility.common.util.SystemUtil.eventually import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity -import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity import com.android.compatibility.common.util.UiAutomatorUtils +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit import org.hamcrest.CoreMatchers import org.hamcrest.Matchers import org.junit.After @@ -62,11 +64,10 @@ import org.junit.Assert.assertTrue import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.BeforeClass +import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit /** * Integration test for app hibernation. diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt index f49e06548d6..485a4efe431 100644 --- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt +++ b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.os.cts +package android.hibernation.cts import android.app.Activity import android.app.ActivityManager @@ -78,12 +78,12 @@ const val VIEW_WAIT_TIMEOUT = 3000L const val CMD_EXPAND_NOTIFICATIONS = "cmd statusbar expand-notifications" const val CMD_COLLAPSE = "cmd statusbar collapse" -const val APK_PATH_S_APP = "/data/local/tmp/cts/os/CtsAutoRevokeSApp.apk" -const val APK_PACKAGE_NAME_S_APP = "android.os.cts.autorevokesapp" -const val APK_PATH_R_APP = "/data/local/tmp/cts/os/CtsAutoRevokeRApp.apk" -const val APK_PACKAGE_NAME_R_APP = "android.os.cts.autorevokerapp" -const val APK_PATH_Q_APP = "/data/local/tmp/cts/os/CtsAutoRevokeQApp.apk" -const val APK_PACKAGE_NAME_Q_APP = "android.os.cts.autorevokeqapp" +const val APK_PATH_S_APP = "/data/local/tmp/cts/hibernation/CtsAutoRevokeSApp.apk" +const val APK_PACKAGE_NAME_S_APP = "android.hibernation.cts.autorevokesapp" +const val APK_PATH_R_APP = "/data/local/tmp/cts/hibernation/CtsAutoRevokeRApp.apk" +const val APK_PACKAGE_NAME_R_APP = "android.hibernation.cts.autorevokerapp" +const val APK_PATH_Q_APP = "/data/local/tmp/cts/hibernation/CtsAutoRevokeQApp.apk" +const val APK_PACKAGE_NAME_Q_APP = "android.hibernation.cts.autorevokeqapp" fun runBootCompleteReceiver(context: Context, testTag: String) { val pkgManager = context.packageManager diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt index fdfda50bda9..543c0cb94f0 100644 --- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt +++ b/tests/tests/hibernation/src/android/hibernation/cts/AutoRevokeTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.os.cts +package android.hibernation.cts import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING import android.app.Instrumentation diff --git a/tests/tests/os/Android.bp b/tests/tests/os/Android.bp index c50c6a70dd7..7645ce7747b 100644 --- a/tests/tests/os/Android.bp +++ b/tests/tests/os/Android.bp @@ -18,10 +18,7 @@ package { android_test { name: "CtsOsTestCases", - defaults: [ - "cts_defaults", - "mts-target-sdk-version-current", - ], + defaults: ["cts_defaults"], compile_multilib: "both", static_libs: [ "android.hidl.manager-V1.0-java", @@ -40,7 +37,6 @@ android_test { "hamcrest-library", "modules-utils-build_system", "platformprotosnano", - "safety-center-internal-data", ], jni_uses_platform_apis: true, jni_libs: [ @@ -64,7 +60,6 @@ android_test { test_suites: [ "cts", "general-tests", - "mts-permission", "sts", ], sdk_version: "test_current", @@ -76,9 +71,6 @@ android_test { aaptflags: ["-0 .policy"], min_sdk_version: "29", data: [ - ":CtsAutoRevokeQApp", - ":CtsAutoRevokeSApp", - ":CtsAutoRevokeRApp", ":CtsCompanionTestApp", ], per_testcase_directory: true, diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml index 631b627f693..e0a13b1a31a 100644 --- a/tests/tests/os/CtsOsTestCases.xml +++ b/tests/tests/os/CtsOsTestCases.xml @@ -48,9 +48,6 @@ </target_preparer> <!-- Load additional APKs onto device --> <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> - <option name="push" value="CtsAutoRevokeSApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeSApp.apk" /> - <option name="push" value="CtsAutoRevokeRApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeRApp.apk" /> - <option name="push" value="CtsAutoRevokeQApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeQApp.apk" /> <option name="push" value="CtsCompanionTestApp.apk->/data/local/tmp/cts/os/CtsCompanionTestApp.apk" /> </target_preparer> </configuration> diff --git a/tests/tests/os/OWNERS b/tests/tests/os/OWNERS index 5c286aace47..8ab70d2ac5e 100644 --- a/tests/tests/os/OWNERS +++ b/tests/tests/os/OWNERS @@ -1,5 +1,3 @@ -per-file *AutoRevoke* = file:platform/frameworks/base:/core/java/android/permission/OWNERS -per-file *AppHibernation* = file:platform/frameworks/base:/core/java/android/permission/OWNERS per-file *Companion* = file:platform/frameworks/base:/core/java/android/permission/OWNERS per-file *Vibrat* = file:platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS per-file *AndroidManifest.xml = file:platform/frameworks/base:/core/java/android/permission/OWNERS diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt index b398affc3df..bcdecdb2845 100644 --- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt +++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt @@ -16,8 +16,12 @@ package android.os.cts +import android.app.ActivityManager +import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING import android.app.Instrumentation +import android.app.UiAutomation import android.companion.CompanionDeviceManager +import android.content.Context import android.content.pm.PackageManager import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP @@ -31,22 +35,30 @@ import android.platform.test.annotations.AppModeFull import android.util.Size import android.util.SizeF import android.util.SparseArray +import android.view.accessibility.AccessibilityNodeInfo import androidx.test.InstrumentationRegistry 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 android.support.test.uiautomator.By +import android.support.test.uiautomator.BySelector +import android.support.test.uiautomator.UiDevice +import android.support.test.uiautomator.UiObject2 +import android.support.test.uiautomator.Until import com.android.compatibility.common.util.MatcherUtils.hasIdThat +import com.android.compatibility.common.util.SystemUtil import com.android.compatibility.common.util.SystemUtil.getEventually import com.android.compatibility.common.util.SystemUtil.runShellCommand import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity import com.android.compatibility.common.util.ThrowingSupplier -import com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject +import com.android.compatibility.common.util.UI_ROOT +import com.android.compatibility.common.util.UiAutomatorUtils import com.android.compatibility.common.util.click +import com.android.compatibility.common.util.depthFirstSearch +import com.android.compatibility.common.util.textAsString +import com.android.compatibility.common.util.uiDump import org.hamcrest.CoreMatchers.containsString +import org.hamcrest.Matcher +import org.hamcrest.Matchers import org.junit.After import org.junit.Assert.assertFalse import org.junit.Assert.assertThat @@ -58,6 +70,8 @@ import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import java.io.Serializable +import java.util.concurrent.atomic.AtomicReference +import java.util.regex.Pattern /** * Test for [CompanionDeviceManager] @@ -226,14 +240,112 @@ class CompanionDeviceManagerTest { MacAddress.fromString(macAddress), context.user) }, *permissions) } -} -private fun UiDevice.waitAndFind(selector: BySelector): UiObject2 = - wait(Until.findObject(selector), 1000) + private fun UiDevice.waitAndFind(selector: BySelector): UiObject2 = + wait(Until.findObject(selector), 1000) -private fun click(label: String) { - waitFindObject(byTextIgnoreCase(label)).click() - waitForIdle() + private fun click(label: String) { + waitFindObject(byTextIgnoreCase(label)).click() + waitForIdle() + } + + private fun uninstallAppWithoutAssertion(packageName: String) { + runShellCommandOrThrow("pm uninstall $packageName") + } + + private fun installApk(apk: String) { + assertThat(runShellCommandOrThrow("pm install -r $apk"), containsString("Success")) + } + + /** + * For some reason waitFindObject sometimes fails to find UI that is present in the view hierarchy + */ + private fun waitFindNode( + matcher: Matcher<AccessibilityNodeInfo>, + failMsg: String? = null, + timeoutMs: Long = 10_000 + ): AccessibilityNodeInfo { + return getEventually({ + val ui = UI_ROOT + ui.depthFirstSearch { node -> + matcher.matches(node) + }.assertNotNull { + buildString { + if (failMsg != null) { + appendLine(failMsg) + } + appendLine("No view found matching $matcher:\n\n${uiDump(ui)}") + } + } + }, timeoutMs) + } + + private fun waitFindObject(selector: BySelector): UiObject2 { + return waitFindObject(instrumentation.uiAutomation, selector) + } + + private fun waitFindObject(uiAutomation: UiAutomation, selector: BySelector): UiObject2 { + try { + return UiAutomatorUtils.waitFindObject(selector) + } catch (e: RuntimeException) { + val ui = uiAutomation.rootInActiveWindow + + val title = ui.depthFirstSearch { node -> + node.viewIdResourceName?.contains("alertTitle") == true + } + val okButton = ui.depthFirstSearch { node -> + node.textAsString?.equals("OK", ignoreCase = true) ?: false + } + + if (title?.text?.toString() == "Android System" && okButton != null) { + // Auto dismiss occasional system dialogs to prevent interfering with the test + okButton.click() + return UiAutomatorUtils.waitFindObject(selector) + } else { + throw e + } + } + } + + private fun byTextIgnoreCase(txt: String): BySelector { + return By.text(Pattern.compile(txt, Pattern.CASE_INSENSITIVE)) + } + + private fun waitForIdle() { + InstrumentationRegistry.getInstrumentation().uiAutomation.waitForIdle(1000, 10000) + } + + private inline fun <T> eventually(crossinline action: () -> T): T { + val res = AtomicReference<T>() + SystemUtil.eventually { + res.set(action()) + } + return res.get() + } + + private fun awaitAppState(pkg: String, stateMatcher: Matcher<Int>) { + val context: Context = InstrumentationRegistry.getTargetContext() + eventually { + runWithShellPermissionIdentity { + val packageImportance = context + .getSystemService(ActivityManager::class.java)!! + .getPackageImportance(pkg) + assertThat(packageImportance, stateMatcher) + } + } + } + + private fun startApp(packageName: String) { + val context = InstrumentationRegistry.getTargetContext() + val intent = context.packageManager.getLaunchIntentForPackage(packageName) + context.startActivity(intent) + awaitAppState(packageName, Matchers.lessThanOrEqualTo(IMPORTANCE_TOP_SLEEPING)) + waitForIdle() + } + + private inline fun <T> T?.assertNotNull(errorMsg: () -> String): T { + return if (this == null) throw AssertionError(errorMsg()) else this + } } operator fun Bundle.set(key: String, value: Any?) { diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp index 27ccdc3d7d7..53263d4ec8b 100644 --- a/tests/tests/permission/Android.bp +++ b/tests/tests/permission/Android.bp @@ -49,6 +49,7 @@ android_test { "bluetooth-test-util-lib", "CtsAccessibilityCommon", "safety-center-internal-data", + "sts-device-util", ], jni_libs: [ "libctspermission_jni", @@ -115,7 +116,6 @@ android_test { ":CtsVictimPermissionDefinerApp", ":CtsAppThatRequestsSystemAlertWindow22", ":CtsAppThatRequestsSystemAlertWindow23", - ":CtsAppThatRequestCustomCameraPermission", ], per_testcase_directory: true, } diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml index 368f94ef7b9..eafc6a6389c 100644 --- a/tests/tests/permission/AndroidTest.xml +++ b/tests/tests/permission/AndroidTest.xml @@ -94,7 +94,6 @@ <option name="push" value="CtsAppThatHasNotificationListener.apk->/data/local/tmp/cts/permissions/CtsAppThatHasNotificationListener.apk" /> <option name="push" value="CtsAppThatRequestsSystemAlertWindow22.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsSystemAlertWindow22.apk" /> <option name="push" value="CtsAppThatRequestsSystemAlertWindow23.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsSystemAlertWindow23.apk" /> - <option name="push" value="CtsAppThatRequestCustomCameraPermission.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk" /> </target_preparer> <!-- Remove additional apps if installed --> diff --git a/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java b/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java index 8dd3e96280a..b88b9aef7df 100644 --- a/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java +++ b/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java @@ -16,6 +16,8 @@ package android.permission.cts; +import static com.android.compatibility.common.util.SystemUtil.runShellCommand; + import android.app.UiAutomation; import android.os.Process; import android.util.Log; @@ -23,8 +25,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.compatibility.common.util.SystemUtil; - import org.junit.Assert; /** Common test utilities */ @@ -151,21 +151,30 @@ public class TestUtils { UiAutomation automation) { String runJobCmd = "cmd jobscheduler run -u " + Process.myUserHandle().getIdentifier() + " -f " + packageName + " " + jobId; + try { + runShellCommand(automation, runJobCmd); + } catch (Throwable e) { + throw new RuntimeException(e); + } + // waiting state is expected after completion for the periodic jobs. + awaitJobUntilRequestedState(packageName, jobId, timeout, automation, "waiting"); + } + + public static void awaitJobUntilRequestedState( + String packageName, + int jobId, + long timeout, + UiAutomation automation, + String requestedState) { String statusCmd = "cmd jobscheduler get-job-state -u " + Process.myUserHandle().getIdentifier() + " " + packageName + " " + jobId; - - SystemUtil.runWithShellPermissionIdentity(automation, () -> { - SystemUtil.runShellCommand(automation, runJobCmd); - Thread.sleep(500); - try { - eventually(() -> Assert.assertEquals( - "The job is probably still running", - "waiting", - SystemUtil.runShellCommand(automation, statusCmd).trim()), - timeout); - } catch (Throwable e) { - throw new RuntimeException(e); - } - }); + try { + eventually(() -> Assert.assertTrue( + "The job doesn't have requested state " + requestedState + " yet", + runShellCommand(automation, statusCmd).trim().startsWith(requestedState)), + timeout); + } catch (Throwable e) { + throw new RuntimeException(e); + } } } diff --git a/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt b/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt index 513e1dfebf4..41a24db3523 100644 --- a/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt +++ b/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt @@ -43,10 +43,8 @@ import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.test.runner.AndroidJUnit4 import com.android.compatibility.common.util.DeviceConfigStateChangerRule -import com.android.compatibility.common.util.ProtoUtils import com.android.compatibility.common.util.SystemUtil.runShellCommand import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity -import com.android.server.job.nano.JobSchedulerServiceDumpProto import org.junit.After import org.junit.Assert import org.junit.Assume @@ -159,18 +157,22 @@ class AccessibilityPrivacySourceTest { @Test fun testAccessibilityListenerSendsIssueToSafetyCenter() { setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString()) - val automation = getAutomation() - mAccessibilityServiceRule.enableService() - TestUtils.eventually( - { - assertSafetyCenterIssueExist( - SC_ACCESSIBILITY_SOURCE_ID, - safetyCenterIssueId, - SC_ACCESSIBILITY_ISSUE_TYPE_ID, - automation) - }, - TIMEOUT_MILLIS) - automation.destroy() + try { + val automation = getAutomation() + mAccessibilityServiceRule.enableService() + TestUtils.eventually( + { + assertSafetyCenterIssueExist( + SC_ACCESSIBILITY_SOURCE_ID, + safetyCenterIssueId, + SC_ACCESSIBILITY_ISSUE_TYPE_ID, + automation) + }, + TIMEOUT_MILLIS) + automation.destroy() + } finally { + setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString()) + } } @Test @@ -246,25 +248,18 @@ class AccessibilityPrivacySourceTest { @Throws(Throwable::class) private fun resetPermissionController() { PermissionUtils.clearAppState(permissionControllerPackage) - val currentUserId = Process.myUserHandle().identifier - - // Wait until jobs are cleared - TestUtils.eventually( - { - val dump = getJobSchedulerDump() - for (job in dump!!.registeredJobs) { - if (job.dump.sourceUserId == currentUserId && - job.dump.sourcePackageName == permissionControllerPackage) { - Assert.assertFalse( - job.dump.jobInfo.service.className.contains("AccessibilityJobService")) - } - } - }, - TIMEOUT_MILLIS) + TestUtils.awaitJobUntilRequestedState( + permissionControllerPackage, + ACCESSIBILITY_JOB_ID, + TIMEOUT_MILLIS, + getAutomation(), + "unknown" + ) runShellCommand( "cmd jobscheduler reset-execution-quota -u " + "${Process.myUserHandle().identifier} $permissionControllerPackage") + runShellCommand("cmd jobscheduler reset-schedule-quota") // Setup up permission controller again (simulate a reboot) val permissionControllerSetupIntent = @@ -288,28 +283,13 @@ class AccessibilityPrivacySourceTest { }) } - // Wait until jobs are set up - TestUtils.eventually( - { - val dump = getJobSchedulerDump() - for (job in dump!!.registeredJobs) { - if (job.dump.sourceUserId == currentUserId && - job.dump.sourcePackageName == permissionControllerPackage && - job.dump.jobInfo.service.className.contains("AccessibilityJobService")) { - return@eventually - } - } - Assert.fail("accessibility job not found") - }, - TIMEOUT_MILLIS) - } - - @Throws(Exception::class) - private fun getJobSchedulerDump(): JobSchedulerServiceDumpProto? { - return ProtoUtils.getProto( + TestUtils.awaitJobUntilRequestedState( + permissionControllerPackage, + ACCESSIBILITY_JOB_ID, + TIMEOUT_MILLIS, getAutomation(), - JobSchedulerServiceDumpProto::class.java, - ProtoUtils.DUMPSYS_JOB_SCHEDULER) + "waiting" + ) } companion object { diff --git a/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java index 67bb9166370..6880e222e14 100644 --- a/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java +++ b/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java @@ -24,18 +24,13 @@ import static android.permission.cts.TestUtils.eventually; import static com.android.compatibility.common.util.SystemUtil.runShellCommand; import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; -import static com.android.server.job.nano.JobPackageHistoryProto.START_PERIODIC_JOB; -import static com.android.server.job.nano.JobPackageHistoryProto.STOP_PERIODIC_JOB; +import static com.android.compatibility.common.util.SystemUtil.waitForBroadcasts; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; -import static java.lang.Math.max; import static java.util.concurrent.TimeUnit.SECONDS; import android.app.NotificationManager; @@ -57,10 +52,6 @@ import androidx.test.filters.SdkSuppress; import androidx.test.runner.AndroidJUnit4; import com.android.compatibility.common.util.DeviceConfigStateChangerRule; -import com.android.compatibility.common.util.ProtoUtils; -import com.android.server.job.nano.JobPackageHistoryProto; -import com.android.server.job.nano.JobSchedulerServiceDumpProto; -import com.android.server.job.nano.JobSchedulerServiceDumpProto.RegisteredJob; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -105,13 +96,7 @@ public class BaseNotificationListenerCheckTest { "notification_listener_check_interval_millis"; protected static final Long OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS = - SECONDS.toMillis(1); - - private static final String PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW = - "qc_max_job_count_per_rate_limiting_window"; - - private static final String PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS = - "qc_rate_limiting_window_ms"; + SECONDS.toMillis(0); private static final String ACTION_SET_UP_NOTIFICATION_LISTENER_CHECK = "com.android.permissioncontroller.action.SET_UP_NOTIFICATION_LISTENER_CHECK"; @@ -161,22 +146,6 @@ public class BaseNotificationListenerCheckTest { PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS, Long.toString(OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS)); - // Disable job scheduler throttling by allowing 300000 jobs per 30 sec - @Rule - public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig1 = - new DeviceConfigStateChangerRule(sContext, - DeviceConfig.NAMESPACE_JOB_SCHEDULER, - PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW, - Integer.toString(3000000)); - - // Disable job scheduler throttling by allowing 300000 jobs per 30 sec - @Rule - public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig2 = - new DeviceConfigStateChangerRule(sContext, - DeviceConfig.NAMESPACE_JOB_SCHEDULER, - PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS, - Integer.toString(30000)); - @Rule public CtsNotificationListenerHelperRule ctsNotificationListenerHelper = new CtsNotificationListenerHelperRule(sContext); @@ -264,65 +233,23 @@ public class BaseNotificationListenerCheckTest { } /** - * Get the state of the job scheduler - */ - private static JobSchedulerServiceDumpProto getJobSchedulerDump() throws Exception { - return ProtoUtils.getProto(sUiAutomation, JobSchedulerServiceDumpProto.class, - ProtoUtils.DUMPSYS_JOB_SCHEDULER); - } - - /** - * Get the last time the NOTIFICATION_LISTENER_CHECK_JOB_ID job was started/stopped for - * permission - * controller. - * - * @param event the job event (start/stop) - * @return the last time the event happened. - */ - private static long getLastJobTime(int event) throws Exception { - int permControllerUid = sPackageManager.getPackageUid(PERMISSION_CONTROLLER_PKG, 0); - - long lastTime = -1; - - for (JobPackageHistoryProto.HistoryEvent historyEvent : - getJobSchedulerDump().history.historyEvent) { - if (historyEvent.uid == permControllerUid - && historyEvent.jobId == NOTIFICATION_LISTENER_CHECK_JOB_ID - && historyEvent.event == event) { - lastTime = max(lastTime, - System.currentTimeMillis() - historyEvent.timeSinceEventMs); - } - } - - return lastTime; - } - - /** * Force a run of the notification listener check. */ protected static void runNotificationListenerCheck() throws Throwable { - // Sleep a little to make sure we don't have overlap in timing - Thread.sleep(1000); - - long beforeJob = System.currentTimeMillis(); - - // Sleep a little to avoid raciness in time keeping - Thread.sleep(1000); - - runShellCommand("cmd jobscheduler run -u " + myUserHandle().getIdentifier() + " -f " - + PERMISSION_CONTROLLER_PKG + " " + NOTIFICATION_LISTENER_CHECK_JOB_ID); - - eventually(() -> { - long startTime = getLastJobTime(START_PERIODIC_JOB); - assertTrue(startTime + " !> " + beforeJob, startTime > beforeJob); - }, UNEXPECTED_TIMEOUT_MILLIS); + TestUtils.awaitJobUntilRequestedState( + PERMISSION_CONTROLLER_PKG, + NOTIFICATION_LISTENER_CHECK_JOB_ID, + UNEXPECTED_TIMEOUT_MILLIS, + sUiAutomation, + "waiting" + ); - // We can't simply require startTime <= endTime because the time being reported isn't - // accurate, and sometimes the end time may come before the start time by around 100 ms. - eventually(() -> { - long stopTime = getLastJobTime(STOP_PERIODIC_JOB); - assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob); - }, UNEXPECTED_TIMEOUT_MILLIS); + TestUtils.runJobAndWaitUntilCompleted( + PERMISSION_CONTROLLER_PKG, + NOTIFICATION_LISTENER_CHECK_JOB_ID, + UNEXPECTED_TIMEOUT_MILLIS, + sUiAutomation + ); } /** @@ -357,6 +284,7 @@ public class BaseNotificationListenerCheckTest { runShellCommand( "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG); + runShellCommand("cmd jobscheduler reset-schedule-quota"); } /** @@ -364,18 +292,15 @@ public class BaseNotificationListenerCheckTest { */ private static void resetPermissionController() throws Throwable { clearAppState(PERMISSION_CONTROLLER_PKG); - int currentUserId = myUserHandle().getIdentifier(); // Wait until jobs are cleared - eventually(() -> { - JobSchedulerServiceDumpProto dump = getJobSchedulerDump(); - - for (RegisteredJob job : dump.registeredJobs) { - if (job.dump.sourceUserId == currentUserId) { - assertNotEquals(job.dump.sourcePackageName, PERMISSION_CONTROLLER_PKG); - } - } - }, UNEXPECTED_TIMEOUT_MILLIS); + TestUtils.awaitJobUntilRequestedState( + PERMISSION_CONTROLLER_PKG, + NOTIFICATION_LISTENER_CHECK_JOB_ID, + UNEXPECTED_TIMEOUT_MILLIS, + sUiAutomation, + "unknown" + ); // Setup up permission controller again (simulate a reboot) Intent permissionControllerSetupIntent = new Intent( @@ -394,22 +319,16 @@ public class BaseNotificationListenerCheckTest { .setFlags(FLAG_RECEIVER_FOREGROUND) .setPackage(PERMISSION_CONTROLLER_PKG)); } + waitForBroadcasts(); // Wait until jobs are set up - eventually(() -> { - JobSchedulerServiceDumpProto dump = getJobSchedulerDump(); - - for (RegisteredJob job : dump.registeredJobs) { - if (job.dump.sourceUserId == currentUserId - && job.dump.sourcePackageName.equals(PERMISSION_CONTROLLER_PKG) - && job.dump.jobInfo.service.className.contains( - "NotificationListenerCheck")) { - return; - } - } - - fail("Permission controller jobs not found"); - }, UNEXPECTED_TIMEOUT_MILLIS); + TestUtils.awaitJobUntilRequestedState( + PERMISSION_CONTROLLER_PKG, + NOTIFICATION_LISTENER_CHECK_JOB_ID, + UNEXPECTED_TIMEOUT_MILLIS, + sUiAutomation, + "waiting" + ); } /** diff --git a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java index ceb4ede242b..8acf1200665 100644 --- a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java +++ b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java @@ -31,19 +31,14 @@ import static android.provider.Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MI import static com.android.compatibility.common.util.SystemUtil.runShellCommand; import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; -import static com.android.server.job.nano.JobPackageHistoryProto.START_PERIODIC_JOB; -import static com.android.server.job.nano.JobPackageHistoryProto.STOP_JOB; -import static com.android.server.job.nano.JobPackageHistoryProto.STOP_PERIODIC_JOB; +import static com.android.compatibility.common.util.SystemUtil.waitForBroadcasts; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; -import static java.lang.Math.max; import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.app.ActivityManager; @@ -65,30 +60,24 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.permission.cts.appthataccesseslocation.IAccessLocationOnCommand; import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.AsbSecurityTest; import android.platform.test.annotations.SystemUserOnly; import android.provider.DeviceConfig; import android.provider.Settings; -import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SdkSuppress; import androidx.test.runner.AndroidJUnit4; import com.android.compatibility.common.util.DeviceConfigStateChangerRule; -import com.android.compatibility.common.util.ProtoUtils; import com.android.compatibility.common.util.mainline.MainlineModule; import com.android.compatibility.common.util.mainline.ModuleDetector; -import com.android.modules.utils.build.SdkLevel; -import com.android.server.job.nano.JobPackageHistoryProto; -import com.android.server.job.nano.JobSchedulerServiceDumpProto; -import com.android.server.job.nano.JobSchedulerServiceDumpProto.RegisteredJob; import org.junit.After; import org.junit.AfterClass; @@ -98,7 +87,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -133,10 +121,6 @@ public class LocationAccessCheckTest { private static final String PROPERTY_LOCATION_ACCESS_PERIODIC_INTERVAL_MILLIS = "location_access_check_periodic_interval_millis"; private static final String PROPERTY_BG_LOCATION_CHECK_ENABLED = "bg_location_check_is_enabled"; - private static final String PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW = - "qc_max_job_count_per_rate_limiting_window"; - private static final String PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS = - "qc_rate_limiting_window_ms"; private static final long UNEXPECTED_TIMEOUT_MILLIS = 10000; private static final long EXPECTED_TIMEOUT_MILLIS = 15000; @@ -212,27 +196,17 @@ public class LocationAccessCheckTest { PROPERTY_LOCATION_ACCESS_CHECK_DELAY_MILLIS, "50"); - // Disable job scheduler throttling by allowing 300000 jobs per 30 sec - @Rule - public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig1 = - new DeviceConfigStateChangerRule(sContext, - DeviceConfig.NAMESPACE_JOB_SCHEDULER, - PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW, - Integer.toString(3000000)); - - // Disable job scheduler throttling by allowing 300000 jobs per 30 sec - @Rule - public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig2 = - new DeviceConfigStateChangerRule(sContext, - DeviceConfig.NAMESPACE_JOB_SCHEDULER, - PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS, - Integer.toString(30000)); + @BeforeClass + public static void beforeClassSetup() throws Exception { + reduceDelays(); + allowNotificationAccess(); + installBackgroundAccessApp(); + } /** * Change settings so that permission controller can show location access notifications more * often. */ - @BeforeClass public static void reduceDelays() { runWithShellPermissionIdentity(() -> { ContentResolver cr = sContext.getContentResolver(); @@ -242,10 +216,16 @@ public class LocationAccessCheckTest { }); } + @AfterClass + public static void cleanupAfterClass() throws Throwable { + resetDelays(); + uninstallBackgroundAccessApp(); + disallowNotificationAccess(); + } + /** * Reset settings so that permission controller runs normally. */ - @AfterClass public static void resetDelays() throws Throwable { runWithShellPermissionIdentity(() -> { ContentResolver cr = sContext.getContentResolver(); @@ -347,14 +327,6 @@ public class LocationAccessCheckTest { } /** - * Get the state of the job scheduler - */ - public static JobSchedulerServiceDumpProto getJobSchedulerDump() throws Exception { - return ProtoUtils.getProto(sUiAutomation, JobSchedulerServiceDumpProto.class, - ProtoUtils.DUMPSYS_JOB_SCHEDULER); - } - - /** * Clear all data of a package including permissions and files. * * @param pkg The name of the package to be cleared @@ -364,85 +336,35 @@ public class LocationAccessCheckTest { runShellCommand("pm clear --user -2 " + pkg); } - /** - * Get the last time the LOCATION_ACCESS_CHECK_JOB_ID job was started/stopped for permission - * controller. - * - * @param event the job event (start/stop) - * @return the last time the event happened. - */ - private static long getLastJobTime(int event) throws Exception { - int permControllerUid = sPackageManager.getPackageUid(PERMISSION_CONTROLLER_PKG, 0); - - long lastTime = -1; - - for (JobPackageHistoryProto.HistoryEvent historyEvent : - getJobSchedulerDump().history.historyEvent) { - if (historyEvent.uid == permControllerUid - && historyEvent.jobId == LOCATION_ACCESS_CHECK_JOB_ID - && historyEvent.event == event) { - lastTime = max(lastTime, - System.currentTimeMillis() - historyEvent.timeSinceEventMs); - } - } - - return lastTime; + private static boolean isJobReady() { + String jobStatus = runShellCommand("cmd jobscheduler get-job-state -u " + + Process.myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG + + " " + LOCATION_ACCESS_CHECK_JOB_ID); + return jobStatus.contains("waiting"); } /** * Force a run of the location check. */ private static void runLocationCheck() throws Throwable { - // If the job isn't setup, do it before running a location check - if (!isLocationAccessJobSetup(myUserHandle().getIdentifier())) { + if (!isJobReady()) { setupLocationAccessCheckJob(); } - // Sleep a little bit to make sure we don't have overlap in timing - Thread.sleep(1000); - - long beforeJob = System.currentTimeMillis(); - - // Sleep a little bit to avoid raciness in time keeping - Thread.sleep(1000); - - runShellCommand( - "cmd jobscheduler run -u " + android.os.Process.myUserHandle().getIdentifier() - + " -f " + PERMISSION_CONTROLLER_PKG + " 0"); - - eventually(() -> { - long startTime = getLastJobTime(START_PERIODIC_JOB); - assertTrue(startTime + " !> " + beforeJob, startTime > beforeJob); - }, EXPECTED_TIMEOUT_MILLIS); + TestUtils.awaitJobUntilRequestedState( + PERMISSION_CONTROLLER_PKG, + LOCATION_ACCESS_CHECK_JOB_ID, + EXPECTED_TIMEOUT_MILLIS, + sUiAutomation, + "waiting" + ); - // We can't simply require startTime <= endTime because the time being reported isn't - // accurate, and sometimes the end time may come before the start time by around 100 ms. - eventually(() -> { - long stopTime; - if (SdkLevel.isAtLeastT()) { - stopTime = getLastJobTime(STOP_PERIODIC_JOB); - } else { - stopTime = getLastJobTime(STOP_JOB); - } - assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob); - }, EXPECTED_TIMEOUT_MILLIS); - } - - /** - * Get a notification thrown by the permission controller that is currently visible. - * - * @return The notification or {@code null} if there is none - */ - private @Nullable StatusBarNotification getPermissionControllerNotification() throws Exception { - NotificationListenerService notificationService = NotificationListener.getInstance(); - - for (StatusBarNotification notification : notificationService.getActiveNotifications()) { - if (notification.getPackageName().equals(PERMISSION_CONTROLLER_PKG)) { - return notification; - } - } - - return null; + TestUtils.runJobAndWaitUntilCompleted( + PERMISSION_CONTROLLER_PKG, + LOCATION_ACCESS_CHECK_JOB_ID, + EXPECTED_TIMEOUT_MILLIS, + sUiAutomation + ); } /** @@ -452,29 +374,8 @@ public class LocationAccessCheckTest { * @return The notification or {@code null} if there is none */ private StatusBarNotification getNotification(boolean cancelNotification) throws Throwable { - NotificationListenerService notificationService = NotificationListener.getInstance(); - - StatusBarNotification notification = getPermissionControllerNotification(); - if (notification == null) { - return null; - } - - if (notification.getId() == LOCATION_ACCESS_CHECK_NOTIFICATION_ID) { - if (cancelNotification) { - notificationService.cancelNotification(notification.getKey()); - - // Wait for notification to get canceled - eventually(() -> assertFalse( - Arrays.asList(notificationService.getActiveNotifications()).contains( - notification)), UNEXPECTED_TIMEOUT_MILLIS); - } - - return notification; - } - - Log.d(LOG_TAG, "Bad notification " + notification); - - return null; + return NotificationListenerUtils.getNotificationForPackageAndId(PERMISSION_CONTROLLER_PKG, + LOCATION_ACCESS_CHECK_NOTIFICATION_ID, cancelNotification); } /** @@ -489,13 +390,11 @@ public class LocationAccessCheckTest { /** * Register {@link NotificationListener}. */ - @BeforeClass public static void allowNotificationAccess() { runShellCommand("cmd notification allow_listener " + (new ComponentName(sContext, NotificationListener.class).flattenToString())); } - @BeforeClass public static void installBackgroundAccessApp() throws Exception { installBackgroundAccessApp(false); } @@ -511,7 +410,6 @@ public class LocationAccessCheckTest { Thread.sleep(5000); } - @AfterClass public static void uninstallBackgroundAccessApp() { unbindService(); runShellCommand("pm uninstall " + TEST_APP_PKG); @@ -555,18 +453,15 @@ public class LocationAccessCheckTest { /** * Skip each test for low ram device */ - @Before public void assumeIsNotLowRamDevice() { assumeFalse(sActivityManager.isLowRamDevice()); } - @Before public void wakeUpAndDismissKeyguard() { runShellCommand("input keyevent KEYCODE_WAKEUP"); runShellCommand("wm dismiss-keyguard"); } - @Before public void bindService() { sConnection = new ServiceConnection() { @Override @@ -587,11 +482,20 @@ public class LocationAccessCheckTest { sContext.bindService(testAppService, sConnection, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND); } + @Before + public void beforeEachTestSetup() throws Throwable { + assumeIsNotLowRamDevice(); + wakeUpAndDismissKeyguard(); + bindService(); + resetPermissionControllerBeforeEachTest(); + assumeCanGetFineLocation(); + } + /** * Reset the permission controllers state before each test */ - @Before public void resetPermissionControllerBeforeEachTest() throws Throwable { + //setupLocationAccessCheckJob(); // Has to be before resetPermissionController to make sure enablement time is the reset time // of permission controller enableLocationAccessCheck(); @@ -604,6 +508,7 @@ public class LocationAccessCheckTest { runShellCommand( "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG); + runShellCommand("cmd jobscheduler reset-schedule-quota"); } /** @@ -629,7 +534,6 @@ public class LocationAccessCheckTest { /** * Make sure fine location can be accessed at all. */ - @Before public void assumeCanGetFineLocation() { if (sCanAccessFineLocation == null) { Criteria crit = new Criteria(); @@ -672,38 +576,22 @@ public class LocationAccessCheckTest { */ private static void resetPermissionController() throws Throwable { clearPackageData(PERMISSION_CONTROLLER_PKG); - int currentUserId = myUserHandle().getIdentifier(); - - // Wait until jobs are cleared - eventually(() -> { - JobSchedulerServiceDumpProto dump = getJobSchedulerDump(); - - for (RegisteredJob job : dump.registeredJobs) { - if (job.dump.sourceUserId == currentUserId) { - assertNotEquals(job.dump.sourcePackageName, PERMISSION_CONTROLLER_PKG); - } - } - }, UNEXPECTED_TIMEOUT_MILLIS); + TestUtils.awaitJobUntilRequestedState( + PERMISSION_CONTROLLER_PKG, + LOCATION_ACCESS_CHECK_JOB_ID, + UNEXPECTED_TIMEOUT_MILLIS, + sUiAutomation, + "unknown" + ); setupLocationAccessCheckJob(); - - // Wait until jobs are set up - eventually(() -> { - assertTrue("LocationAccessCheck job not found", - isLocationAccessJobSetup(currentUserId)); - }, UNEXPECTED_TIMEOUT_MILLIS); - } - - private static boolean isLocationAccessJobSetup(int currentUserId) throws Exception { - JobSchedulerServiceDumpProto dump = getJobSchedulerDump(); - for (RegisteredJob job : dump.registeredJobs) { - if (job.dump.sourceUserId == currentUserId - && job.dump.sourcePackageName.equals(PERMISSION_CONTROLLER_PKG) - && job.dump.jobInfo.service.className.contains("LocationAccessCheck")) { - return true; - } - } - return false; + TestUtils.awaitJobUntilRequestedState( + PERMISSION_CONTROLLER_PKG, + LOCATION_ACCESS_CHECK_JOB_ID, + UNEXPECTED_TIMEOUT_MILLIS, + sUiAutomation, + "waiting" + ); } private static void setupLocationAccessCheckJob() { @@ -724,27 +612,31 @@ public class LocationAccessCheckTest { .setFlags(FLAG_RECEIVER_FOREGROUND) .setPackage(PERMISSION_CONTROLLER_PKG)); } + waitForBroadcasts(); } /** * Unregister {@link NotificationListener}. */ - @AfterClass public static void disallowNotificationAccess() { runShellCommand("cmd notification disallow_listener " + (new ComponentName(sContext, NotificationListener.class)).flattenToString()); } + @After + public void cleanupAfterEachTest() throws Throwable { + resetPrivacyConfig(); + locationUnbind(); + } + /** * Reset location access check */ - @After public void resetPrivacyConfig() throws Throwable { // Run a location access check to update enabled state inside permission controller runLocationCheck(); } - @After public void locationUnbind() throws Throwable { unbindService(); } @@ -786,6 +678,7 @@ public class LocationAccessCheckTest { // Wait until package is cleared and permission controller has cleared the state Thread.sleep(10000); + waitForBroadcasts(); // Clearing removed the permissions, hence grant them again grantPermissionToTestApp(ACCESS_FINE_LOCATION); @@ -811,7 +704,7 @@ public class LocationAccessCheckTest { Thread.sleep(2000); installBackgroundAccessApp(); - + waitForBroadcasts(); accessLocation(); runLocationCheck(); @@ -829,12 +722,14 @@ public class LocationAccessCheckTest { eventually(() -> assertNotNull(getNotification(false)), EXPECTED_TIMEOUT_MILLIS); uninstallBackgroundAccessApp(); + // wait for permission controller (broadcast receiver) to clean up things + Thread.sleep(5000); + waitForBroadcasts(); try { eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS); } finally { installBackgroundAccessApp(); - getNotification(true); } } @@ -887,6 +782,7 @@ public class LocationAccessCheckTest { assertNull(getNotification(false)); enableLocationAccessCheck(); + Thread.sleep(2000); // Trigger update of location enable time. In the real world it enabling happens on the // first location check. I.e. accesses before this location check are ignored. @@ -935,6 +831,7 @@ public class LocationAccessCheckTest { @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu") public void notificationOnClickOpensSafetyCenter() throws Throwable { + assumeTrue(SafetyCenterUtils.deviceSupportsSafetyCenter(sContext)); accessLocation(); runLocationCheck(); diff --git a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java index 88006b999a7..8999a93f633 100644 --- a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java +++ b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java @@ -109,7 +109,6 @@ public class NotificationListenerCheckTest extends BaseNotificationListenerCheck eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS); runNotificationListenerCheck(); - ensure(() -> assertNull("Expected no notifications", getNotification(false)), ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS); } @@ -117,11 +116,9 @@ public class NotificationListenerCheckTest extends BaseNotificationListenerCheck @Test public void notificationIsShownAgainAfterClear() throws Throwable { runNotificationListenerCheck(); - eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS); clearAppState(TEST_APP_PKG); - // Wait until package is cleared and permission controller has cleared the state Thread.sleep(2000); diff --git a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java index 05bc54246b4..6c6f3cbb6ba 100644 --- a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java +++ b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java @@ -17,7 +17,6 @@ package android.permission.cts; import static android.Manifest.permission.ACCESS_FINE_LOCATION; -import static android.Manifest.permission.CAMERA; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; @@ -32,7 +31,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.platform.test.annotations.AsbSecurityTest; import android.provider.DeviceConfig; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiDevice; @@ -98,7 +96,6 @@ public class OneTimePermissionTest { @Before public void installApp() { runShellCommand("pm install -r " + APK); - runShellCommand("pm install -r " + CUSTOM_CAMERA_PERM_APK); } @Before @@ -119,7 +116,6 @@ public class OneTimePermissionTest { @After public void uninstallApp() { runShellCommand("pm uninstall " + APP_PKG_NAME); - runShellCommand("pm uninstall " + CUSTOM_CAMERA_PERM_APP_PKG_NAME); } @After @@ -226,33 +222,6 @@ public class OneTimePermissionTest { })); } - @Test - @AsbSecurityTest(cveBugId = 237405974L) - public void testCustomPermissionIsGrantedOneTime() throws Throwable { - Intent startApp = new Intent() - .setComponent(new ComponentName(CUSTOM_CAMERA_PERM_APP_PKG_NAME, - CUSTOM_CAMERA_PERM_APP_PKG_NAME + ".RequestCameraPermission")) - .addFlags(FLAG_ACTIVITY_NEW_TASK); - - mContext.startActivity(startApp); - - // We're only manually granting CAMERA, but the app will later request CUSTOM and get it - // granted silently. This is intentional since it's in the same group but both should - // eventually be revoked - clickOneTimeButton(); - - // Just waiting for the revocation - eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED, - mContext.getPackageManager() - .checkPermission(CAMERA, CUSTOM_CAMERA_PERM_APP_PKG_NAME))); - - // This checks the vulnerability - eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED, - mContext.getPackageManager() - .checkPermission(CUSTOM_PERMISSION, CUSTOM_CAMERA_PERM_APP_PKG_NAME))); - - } - private void assertGrantedState(String s, int permissionGranted, long timeoutMillis) { eventually(() -> Assert.assertEquals(s, permissionGranted, mPackageManager diff --git a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java index 3dc5f03e9dd..75da42fc4e5 100644 --- a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java +++ b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java @@ -39,8 +39,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + @AppModeFull(reason = "Instant apps cannot read state of other packages.") -public class RemovePermissionTest { +public class RemovePermissionTest extends StsExtraBusinessLogicTestCase { private static final String APP_PKG_NAME_BASE = "android.permission.cts.revokepermissionwhenremoved"; private static final String ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME = diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml index 71442c757da..6a02041da47 100644 --- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml +++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml @@ -15,9 +15,13 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - package="com.android.car.updatable" > + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" > + <!-- + This file contains the permissions defined by CarService-Builtin(com.android.car) + and CarService-updatable(com.[google.]?android.car.updatable). As this is only a + resource file, permissions from both packages can be added here. + --> <permission-group android:name="android.car.permission-group.CAR_MONITORING" android:icon="@drawable/perm_group_car" android:description="@string/car_permission_desc" diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java index ca4794dbe0c..752a79454ea 100644 --- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java +++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java @@ -133,6 +133,35 @@ public class PermissionPolicyTest { declaredPermissionsMap.putAll( getPermissionsForPackage(sContext, carServicePackageName)); + + // Load signature permission declared in CarService-builtin + String carServiceBuiltInPackageName = "com.android.car"; + Map<String, PermissionInfo> carServiceBuiltInPermissionsMap = getPermissionsForPackage( + sContext, carServiceBuiltInPackageName); + // carServiceBuiltInPermissionsMap should only have signature permissions and those + // permissions should not be defined in car service updatable. + for (Map.Entry<String, PermissionInfo> permissionData : carServiceBuiltInPermissionsMap + .entrySet()) { + PermissionInfo carServiceBuiltInDeclaredPermission = permissionData.getValue(); + String carServiceBuiltInDeclaredPermissionName = permissionData.getKey(); + + // Signature only permission should be defined in built-in car service + if ((carServiceBuiltInDeclaredPermission + .getProtection() != PermissionInfo.PROTECTION_SIGNATURE) + || (carServiceBuiltInDeclaredPermission.getProtectionFlags() != 0)) { + offendingList.add("Permission " + carServiceBuiltInDeclaredPermissionName + + " should be signature only permission to be declared in" + + " carServiceBuiltIn package."); + continue; + } + + if (declaredPermissionsMap.get(carServiceBuiltInDeclaredPermissionName) != null) { + offendingList.add("Permission " + carServiceBuiltInDeclaredPermissionName + + " from car service builtin is already declared in other packages."); + continue; + } + } + declaredPermissionsMap.putAll(carServiceBuiltInPermissionsMap); } for (ExpectedPermissionInfo expectedPermission : expectedPermissions) { diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt index 266b4861bf0..40feeb4585b 100644 --- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt +++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt @@ -202,5 +202,7 @@ abstract class BasePermissionTest { protected fun startActivityForFuture( intent: Intent ): CompletableFuture<Instrumentation.ActivityResult> = - activityRule.launchActivity(null).startActivityForFuture(intent) + CompletableFuture<Instrumentation.ActivityResult>().also { + activityRule.launchActivity(null).startActivityForFuture(intent, it) + } } diff --git a/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt b/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt index 19cf11534c2..1774030f3f5 100644 --- a/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt +++ b/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt @@ -22,17 +22,22 @@ import android.content.Intent import java.util.concurrent.CompletableFuture class StartForFutureActivity : Activity() { - private val future = CompletableFuture<Instrumentation.ActivityResult>() - - fun startActivityForFuture(intent: Intent): CompletableFuture<Instrumentation.ActivityResult> { + fun startActivityForFuture( + intent: Intent, + future: CompletableFuture<Instrumentation.ActivityResult> + ) { startActivityForResult(intent, 1) - return future + StartForFutureActivity.future = future } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - - future.complete(Instrumentation.ActivityResult(resultCode, data)) + future!!.complete(Instrumentation.ActivityResult(resultCode, data)) + future = null finish() } + + companion object { + private var future: CompletableFuture<Instrumentation.ActivityResult>? = null + } } diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp index b88fcf56cd6..7abf096a3a6 100644 --- a/tests/tests/provider/Android.bp +++ b/tests/tests/provider/Android.bp @@ -32,6 +32,7 @@ android_test { "mockito-target-minus-junit4", // TODO: remove testng once Android migrates to JUnit 4.12, which provides assertThrows "testng", + "sts-device-util", ], jni_libs: [ diff --git a/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java b/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java index be6ff87b0bf..eaddc098954 100644 --- a/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java +++ b/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java @@ -16,24 +16,20 @@ package android.provider.cts; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import com.android.compatibility.common.util.SystemUtil; - import android.app.ActivityManager; -import android.app.Instrumentation; import android.content.ContentProviderClient; import android.content.ContentResolver; -import android.content.Context; -import android.provider.SearchIndexableResource; -import androidx.test.filters.SmallTest; import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.After; +import com.android.compatibility.common.util.SystemUtil; + +import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,26 +42,24 @@ public class MultiAuthorityTest { private static final String PROVIDER2 = "android.provider.apps.cts.multi2"; private static final String PROVIDER_NONEXISTENT = "android.provider.apps.cts.multi3"; - private Context mContext; - private ActivityManager mAm; private ContentResolver mContentResolver; @Before public void setUp() { - mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - mContentResolver = mContext.getContentResolver(); - mAm = mContext.getSystemService(ActivityManager.class); + mContentResolver = InstrumentationRegistry.getInstrumentation() + .getTargetContext().getContentResolver(); } - @After - public void shutDown() { + @AfterClass + public static void shutDown() { killProviderProcess(); } - private void killProviderProcess() { - SystemUtil.runWithShellPermissionIdentity(() -> { - mAm.forceStopPackage("android.provider.apps.cts.multiauthority"); - }); + private static void killProviderProcess() { + final ActivityManager am = InstrumentationRegistry.getInstrumentation() + .getTargetContext().getSystemService(ActivityManager.class); + SystemUtil.runWithShellPermissionIdentity(() -> + am.forceStopPackage("android.provider.apps.cts.multiauthority")); } @Test diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java index 2f5155ad427..9c603f8ede3 100644 --- a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java +++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java @@ -40,8 +40,10 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + @RunWith(AndroidJUnit4.class) -public class Settings_SystemTest { +public class Settings_SystemTest extends StsExtraBusinessLogicTestCase { private static final String INT_FIELD = System.END_BUTTON_BEHAVIOR; private static final String LONG_FIELD = System.SCREEN_OFF_TIMEOUT; private static final String FLOAT_FIELD = System.FONT_SCALE; diff --git a/tests/tests/sdksandbox/webkit/Android.bp b/tests/tests/sdksandbox/webkit/Android.bp index 5eb4236e60f..47af4008a0b 100644 --- a/tests/tests/sdksandbox/webkit/Android.bp +++ b/tests/tests/sdksandbox/webkit/Android.bp @@ -27,6 +27,7 @@ android_test { "compatibility-device-util-axt", "ctstestrunner-axt", "CtsSdkSandboxTestScenario", + "ctswebkitsharedenv", ], data: [ ":EmptySdkProviderApp", diff --git a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp index d6f6b101ad2..625d304837e 100644 --- a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp +++ b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp @@ -28,6 +28,8 @@ android_test_helper_app { "CtsSdkSandboxTestRunner", "compatibility-device-util-axt", "ctsdeviceutillegacy-axt", + "ctswebkitsharedenv", + "CtsWebkitTestCasesSharedWithSdk", ], libs: [ "android.test.base", diff --git a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java index 7a1c8274a18..427a8158a55 100644 --- a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java +++ b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java @@ -16,33 +16,41 @@ package com.android.cts.sdksidetests.webviewsandboxtest; - -import static com.google.common.truth.Truth.assertThat; - import android.app.sdksandbox.testutils.testscenario.SdkSandboxTestScenarioRunner; import android.content.Context; import android.os.Bundle; import android.view.View; import android.webkit.WebView; - -import org.junit.Test; - +import android.webkit.cts.IHostAppInvoker; +import android.webkit.cts.SharedWebViewTestEnvironment; +import android.webkit.cts.WebViewOnUiThread; +import android.webkit.cts.WebViewTest; public class WebViewSandboxTestSdk extends SdkSandboxTestScenarioRunner { + private WebViewTest mTestInstance = new WebViewTest(); private WebView mWebView; + private WebViewOnUiThread mOnUiThread; + + @Override + public Object getTestInstance() { + return mTestInstance; + } @Override public View beforeEachTest(Context windowContext, Bundle params, int width, int height) { mWebView = new WebView(windowContext); - return mWebView; - } + mOnUiThread = new WebViewOnUiThread(mWebView); - @Test - public void testScrollBarOverlay() { - mWebView.setHorizontalScrollbarOverlay(true); - mWebView.setVerticalScrollbarOverlay(false); + SharedWebViewTestEnvironment testEnvironment = + new SharedWebViewTestEnvironment.Builder() + .setContext(getContext()) + .setWebView(mWebView) + .setWebViewOnUiThread(mOnUiThread) + .setHostAppInvoker(IHostAppInvoker.Stub.asInterface(getCustomInterface())) + .build(); - assertThat(mWebView.overlayHorizontalScrollbar()).isTrue(); - assertThat(mWebView.overlayVerticalScrollbar()).isFalse(); + mTestInstance.setTestEnvironment(testEnvironment); + + return mWebView; } } diff --git a/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java b/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java index 98295b70b8a..a960cce0b38 100755 --- a/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java +++ b/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java @@ -16,10 +16,14 @@ package android.sdksandbox.webkit.cts; +import static android.app.sdksandbox.testutils.testscenario.SdkSandboxScenarioRule.ENABLE_LIFE_CYCLE_ANNOTATIONS; + import android.app.sdksandbox.testutils.testscenario.KeepSdkSandboxAliveRule; import android.app.sdksandbox.testutils.testscenario.SdkSandboxScenarioRule; +import android.webkit.cts.SharedWebViewTestEnvironment; import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.MediumTest; import org.junit.ClassRule; import org.junit.Rule; @@ -30,15 +34,25 @@ import org.junit.runner.RunWith; public class WebViewSandboxTest { @ClassRule - public static final KeepSdkSandboxAliveRule sSdkTestSuiteSetup = new KeepSdkSandboxAliveRule( - "com.android.emptysdkprovider"); + public static final KeepSdkSandboxAliveRule sSdkTestSuiteSetup = + new KeepSdkSandboxAliveRule("com.android.emptysdkprovider"); @Rule - public final SdkSandboxScenarioRule sdkTester = new SdkSandboxScenarioRule( - "com.android.cts.sdksidetests.webviewsandboxtest"); + public final SdkSandboxScenarioRule sdkTester = + new SdkSandboxScenarioRule( + "com.android.cts.sdksidetests.webviewsandboxtest", + SharedWebViewTestEnvironment.createHostAppInvoker(), + ENABLE_LIFE_CYCLE_ANNOTATIONS); @Test + @MediumTest public void testScrollBarOverlay() throws Exception { sdkTester.assertSdkTestRunPasses("testScrollBarOverlay"); } + + @Test + @MediumTest + public void testFlingScroll() throws Exception { + sdkTester.assertSdkTestRunPasses("testFlingScroll"); + } } diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp index 9f4cda5752c..56d02d21ee3 100644 --- a/tests/tests/security/Android.bp +++ b/tests/tests/security/Android.bp @@ -91,7 +91,8 @@ android_test { ":CtsPermissionBackupAppCert34", ":CtsPermissionBackupAppCert123", ":CtsPermissionBackupAppCert4History124", - ], + ":CtsAppThatRequestCustomCameraPermission", + ], } android_test_helper_app { diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml index 73e6bc7ece8..6a6dc92888a 100644 --- a/tests/tests/security/AndroidTest.xml +++ b/tests/tests/security/AndroidTest.xml @@ -62,6 +62,7 @@ <option name="push" value="CtsPermissionBackupAppCert123.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert123.apk" /> <option name="push" value="CtsPermissionBackupAppCert34.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert34.apk" /> <option name="push" value="CtsPermissionBackupAppCert4History124.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert4History124.apk" /> + <option name="push" value="CtsAppThatRequestCustomCameraPermission.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk" /> </target_preparer> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/Android.bp b/tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp index 873733d0777..873733d0777 100644 --- a/tests/tests/permission/AppThatRequestCustomCameraPermission/Android.bp +++ b/tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml b/tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml index a8143a78e62..a8143a78e62 100644 --- a/tests/tests/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml +++ b/tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml b/tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml index 8de46384b23..8de46384b23 100644 --- a/tests/tests/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml +++ b/tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java b/tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java index 4bbeb53c5e2..4bbeb53c5e2 100644 --- a/tests/tests/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java +++ b/tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java diff --git a/tests/tests/security/res/raw/cve_2022_33234.mkv b/tests/tests/security/res/raw/cve_2022_33234.mkv Binary files differnew file mode 100644 index 00000000000..752e3cd749b --- /dev/null +++ b/tests/tests/security/res/raw/cve_2022_33234.mkv diff --git a/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt b/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt index b449451bcff..201df173368 100644 --- a/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt +++ b/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt @@ -263,7 +263,9 @@ abstract class BasePermissionUiTest : StsExtraBusinessLogicTestCase() { private fun startActivityForFuture( intent: Intent ): CompletableFuture<Instrumentation.ActivityResult> = - activityRule.launchActivity(null).startActivityForFuture(intent) + CompletableFuture<Instrumentation.ActivityResult>().also { + activityRule.launchActivity(null).startActivityForFuture(intent, it) + } protected fun assertAppHasPermission(permissionName: String, expectPermission: Boolean) { assertEquals( @@ -301,4 +303,4 @@ abstract class BasePermissionUiTest : StsExtraBusinessLogicTestCase() { click(By.res(ALLOW_BUTTON), timeoutMillis) } } -}
\ No newline at end of file +} diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20482.java b/tests/tests/security/src/android/security/cts/CVE_2022_20482.java new file mode 100644 index 00000000000..a0df88cdffe --- /dev/null +++ b/tests/tests/security/src/android/security/cts/CVE_2022_20482.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 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 static androidx.test.core.app.ApplicationProvider.getApplicationContext; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeNoException; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.platform.test.annotations.AsbSecurityTest; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; + +@RunWith(AndroidJUnit4.class) +public class CVE_2022_20482 extends StsExtraBusinessLogicTestCase { + + /** + * b/240422263 + * Vulnerable library : services.jar + * Vulnerable module : Not applicable + * Is Play managed : No + */ + @AsbSecurityTest(cveBugId = 240422263) + @Test + public void testPocCVE_2022_20482() { + final int notificationChannelLimit = 10000; // 2 * NOTIFICATION_CHANNEL_COUNT_LIMIT + final String notificationChannelId = "NotificationChannelId"; + final String notificationChannelName = "NotificationChannelName"; + boolean isVulnerable = true; + int notificationChannelCount = 0; + NotificationManager notificationManager = null; + ArrayList<String> notificationChannelIds = new ArrayList<>(); + try { + Context context = getApplicationContext(); + notificationManager = context.getSystemService(NotificationManager.class); + + // Store total number of notification channels present before test run + notificationChannelCount = notificationManager.getNotificationChannels().size(); + + // Create 'notificationChannelLimit' notification channels + for (int i = 0; i < notificationChannelLimit; ++i) { + String uniqueNotificationChannelId = notificationChannelId + i; + NotificationChannel notificationChannel = + new NotificationChannel(uniqueNotificationChannelId, + notificationChannelName, NotificationManager.IMPORTANCE_DEFAULT); + + // Create notification channel + notificationManager.createNotificationChannel(notificationChannel); + + // Add notification channel id in list(for deleting notification channel later) + notificationChannelIds.add(uniqueNotificationChannelId); + } + } catch (Exception e) { + isVulnerable = false; + if (!(e instanceof IllegalStateException) + || !e.getMessage().contains("Limit exceed; cannot create more channels")) { + assumeNoException("Unexpected exception occurred!", e); + } + } finally { + try { + // Retrieve total number of notification channels added by test so that the + // test fails only if all notification channels from test were added successfully + notificationChannelCount = notificationManager.getNotificationChannels().size() + - notificationChannelCount; + boolean flagAllNotificationChannelsAdded = + notificationChannelCount == notificationChannelLimit; + + // Delete notification channels created earlier + for (String id : notificationChannelIds) { + notificationManager.deleteNotificationChannel(id); + } + + // Fail if all notification channels from test were added successfully without + // any occurrence of IllegalStateException + assertFalse( + "Device is vulnerable to b/240422263! Permanent denial of service" + + " possible via NotificationManager#createNotificationChannel", + isVulnerable && flagAllNotificationChannelsAdded); + } catch (Exception ignoredException) { + } + } + } +} diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20493.java b/tests/tests/security/src/android/security/cts/CVE_2022_20493.java new file mode 100644 index 00000000000..4933dc6eb07 --- /dev/null +++ b/tests/tests/security/src/android/security/cts/CVE_2022_20493.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 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 static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeNoException; + +import android.net.Uri; +import android.os.Parcel; +import android.platform.test.annotations.AsbSecurityTest; +import android.service.notification.Condition; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + +import java.lang.reflect.Field; +import java.util.Collections; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/* + * This CTS test has been created taking reference from the tests present in + * frameworks/base/core/tests/coretests/src/android/service/notification/ConditionTest.java + */ + +@RunWith(AndroidJUnit4.class) +public class CVE_2022_20493 extends StsExtraBusinessLogicTestCase { + private static final int INPUT_STRING_LENGTH = 2000; + private String mLongString; + private String mValidString; + private Uri mLongUri; + private Uri mValidUri; + + private boolean checkFields(Condition condition, boolean checkLine) { + // Check all fields + boolean status = (mLongUri.toString().length() <= condition.id.toString().length()) + || (INPUT_STRING_LENGTH <= condition.summary.length()); + if (checkLine) { + status = status || (INPUT_STRING_LENGTH <= condition.line1.length()) + || (INPUT_STRING_LENGTH <= condition.line2.length()); + } + return status; + } + + private boolean testLongFieldsInConstructors() { + // Confirm strings are truncated via short constructor + Condition firstCondition = new Condition(mLongUri, mLongString, Condition.STATE_TRUE); + + // Confirm strings are truncated via long constructor + Condition secondCondition = new Condition(mLongUri, mLongString, mLongString, mLongString, + -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS); + return checkFields(firstCondition, false) || checkFields(secondCondition, true); + } + + private boolean setFieldsUsingReflection(boolean setLine) + throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { + // Set fields via reflection to force them to be long, then parcel and unparcel to make sure + // it gets truncated upon unparcelling. + Condition condition; + if (setLine) { + condition = new Condition(mValidUri, mValidString, mValidString, mValidString, -1, + Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS); + } else { + condition = new Condition(mValidUri, mValidString, Condition.STATE_TRUE); + } + + Class conditionClass = Class.forName("android.service.notification.Condition"); + Field id = conditionClass.getDeclaredField("id"); + id.setAccessible(true); + id.set(condition, mLongUri); + Field summary = conditionClass.getDeclaredField("summary"); + summary.setAccessible(true); + summary.set(condition, mLongString); + if (setLine) { + Field line1 = conditionClass.getDeclaredField("line1"); + line1.setAccessible(true); + line1.set(condition, mLongString); + Field line2 = conditionClass.getDeclaredField("line2"); + line2.setAccessible(true); + line2.set(condition, mLongString); + } + + Parcel parcel = Parcel.obtain(); + condition.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + Condition conditionFromParcel = new Condition(parcel); + return checkFields(conditionFromParcel, setLine); + } + + private boolean testLongFieldsFromParcel() + throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { + return setFieldsUsingReflection(true) || setFieldsUsingReflection(false); + } + + /** + * b/242846316 + * Vulnerable library : framework.jar + * Vulnerable module : Not applicable + * Is Play managed : No + */ + @AsbSecurityTest(cveBugId = 242846316) + @Test + public void testPocCVE_2022_20493() { + try { + mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A")); + mLongUri = Uri.parse("condition://" + mLongString); + mValidUri = Uri.parse("condition://android"); + mValidString = "placeholder"; + boolean firstResult = testLongFieldsInConstructors(); + boolean secondResult = testLongFieldsFromParcel(); + assertFalse("Device is vulnerable to b/242846316!", firstResult || secondResult); + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/tests/tests/security/src/android/security/cts/MediaSessionTest.java b/tests/tests/security/src/android/security/cts/MediaSessionTest.java new file mode 100644 index 00000000000..d74179eddc3 --- /dev/null +++ b/tests/tests/security/src/android/security/cts/MediaSessionTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 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 static org.junit.Assert.assertThrows; + +import android.content.ComponentName; +import android.content.ContextWrapper; +import android.media.session.MediaSession; +import android.platform.test.annotations.AppModeFull; +import android.platform.test.annotations.AsbSecurityTest; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@AppModeFull +@RunWith(AndroidJUnit4.class) +public class MediaSessionTest extends StsExtraBusinessLogicTestCase { + private static final String TAG = "MediaSessionTest"; + + private static final String TEST_SESSION_TAG_FOREIGN_PACKAGE = + "test-session-tag-foreign-package"; + private static final String TEST_FOREIGN_PACKAGE_NAME = "fakepackage"; + private static final String TEST_FOREIGN_PACKAGE_CLASS = "com.fakepackage.media.FakeReceiver"; + + @Test + @AsbSecurityTest(cveBugId = 238177121) + public void setMediaButtonBroadcastReceiver_withForeignPackageName_fails() throws Exception { + // Create Media Session + MediaSession mediaSession = new MediaSession(new ContextWrapper(getContext()) { + @Override + public String getPackageName() { + return TEST_FOREIGN_PACKAGE_NAME; + } + }, TEST_SESSION_TAG_FOREIGN_PACKAGE); + + assertThrows("Component name with different package name was registered.", + IllegalArgumentException.class, + () -> mediaSession.setMediaButtonBroadcastReceiver( + new ComponentName(TEST_FOREIGN_PACKAGE_NAME, TEST_FOREIGN_PACKAGE_CLASS))); + + mediaSession.release(); + } +} diff --git a/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java b/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java new file mode 100644 index 00000000000..eafef736914 --- /dev/null +++ b/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2022 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 static android.Manifest.permission.CAMERA; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; + +import static com.android.compatibility.common.util.SystemUtil.eventually; +import static com.android.compatibility.common.util.SystemUtil.runShellCommand; +import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.platform.test.annotations.AsbSecurityTest; +import android.provider.DeviceConfig; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.UiObject2; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.compatibility.common.util.SystemUtil; +import com.android.compatibility.common.util.UiAutomatorUtils; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class OneTimePermissionTest { + + private static final String CUSTOM_CAMERA_PERM_APP_PKG_NAME = + "android.permission.cts.appthatrequestcustomcamerapermission"; + private static final String CUSTOM_CAMERA_PERM_APK = + "/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk"; + + public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM"; + + private static final long ONE_TIME_TIMEOUT_MILLIS = 5000; + private static final long ONE_TIME_KILLED_DELAY_MILLIS = 5000; + + private final Context mContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + + private String mOldOneTimePermissionTimeoutValue; + private String mOldOneTimePermissionKilledDelayValue; + + @Before + public void wakeUpScreen() { + SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP"); + + SystemUtil.runShellCommand("input keyevent 82"); + } + + @Before + public void installApp() { + runShellCommand("pm install -r " + CUSTOM_CAMERA_PERM_APK); + } + + @Before + public void prepareDeviceForOneTime() { + runWithShellPermissionIdentity(() -> { + mOldOneTimePermissionTimeoutValue = DeviceConfig.getProperty("permissions", + "one_time_permissions_timeout_millis"); + mOldOneTimePermissionKilledDelayValue = DeviceConfig.getProperty("permissions", + "one_time_permissions_killed_delay_millis"); + DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis", + Long.toString(ONE_TIME_TIMEOUT_MILLIS), false); + DeviceConfig.setProperty("permissions", + "one_time_permissions_killed_delay_millis", + Long.toString(ONE_TIME_KILLED_DELAY_MILLIS), false); + }); + } + + @After + public void uninstallApp() { + runShellCommand("pm uninstall " + CUSTOM_CAMERA_PERM_APP_PKG_NAME); + } + + @After + public void restoreDeviceForOneTime() { + runWithShellPermissionIdentity( + () -> { + DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis", + mOldOneTimePermissionTimeoutValue, false); + DeviceConfig.setProperty("permissions", + "one_time_permissions_killed_delay_millis", + mOldOneTimePermissionKilledDelayValue, false); + }); + } + + @Test + @AsbSecurityTest(cveBugId = 237405974L) + public void testCustomPermissionIsGrantedOneTime() throws Throwable { + Intent startApp = new Intent() + .setComponent(new ComponentName(CUSTOM_CAMERA_PERM_APP_PKG_NAME, + CUSTOM_CAMERA_PERM_APP_PKG_NAME + ".RequestCameraPermission")) + .addFlags(FLAG_ACTIVITY_NEW_TASK); + + mContext.startActivity(startApp); + + // We're only manually granting CAMERA, but the app will later request CUSTOM and get it + // granted silently. This is intentional since it's in the same group but both should + // eventually be revoked + clickOneTimeButton(); + + // Just waiting for the revocation + eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED, + mContext.getPackageManager() + .checkPermission(CAMERA, CUSTOM_CAMERA_PERM_APP_PKG_NAME))); + + // This checks the vulnerability + eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED, + mContext.getPackageManager() + .checkPermission(CUSTOM_PERMISSION, CUSTOM_CAMERA_PERM_APP_PKG_NAME))); + + } + + private void clickOneTimeButton() throws Throwable { + final UiObject2 uiObject = UiAutomatorUtils.waitFindObject(By.res( + "com.android.permissioncontroller:id/permission_allow_one_time_button"), 10000); + Thread.sleep(500); + uiObject.click(); + } +} diff --git a/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt b/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt index 28d004f53cd..3b20d458354 100644 --- a/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt +++ b/tests/tests/security/src/android/security/cts/SplitPermissionAutoGrantTest.kt @@ -18,7 +18,10 @@ package android.security.cts import android.platform.test.annotations.AsbSecurityTest import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.compatibility.common.util.mainline.MainlineModule +import com.android.compatibility.common.util.mainline.ModuleDetector import org.junit.After +import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -35,6 +38,8 @@ class SplitPermissionAutoGrantTest : BasePermissionUiTest() { @Test @AsbSecurityTest(cveBugId = [223907044]) fun testAutoGrant() { + assumeFalse(ModuleDetector.moduleIsPlayManaged( + mContext.getPackageManager(), MainlineModule.PERMISSION_CONTROLLER)) installPackage(SPLIT_PERMISSION_APK_PATH) assertAppHasPermission(android.Manifest.permission.BLUETOOTH, true) assertAppHasPermission(android.Manifest.permission.BLUETOOTH_CONNECT, true) diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java index 9fd10146c1c..4facc062759 100644 --- a/tests/tests/security/src/android/security/cts/StagefrightTest.java +++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java @@ -1811,6 +1811,12 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { before any existing test methods ***********************************************************/ @Test + @AsbSecurityTest(cveBugId = 240971780) + public void testStagefright_cve_2022_33234() throws Exception { + doStagefrightTest(R.raw.cve_2022_33234); + } + + @Test @AsbSecurityTest(cveBugId = 235102508) public void testStagefright_cve_2022_25669() throws Exception { doStagefrightTest(R.raw.cve_2022_25669); diff --git a/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt b/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt index ed2c8e814f4..d5c535d2496 100644 --- a/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt +++ b/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt @@ -22,17 +22,22 @@ import android.content.Intent import java.util.concurrent.CompletableFuture class StartForFutureActivity : Activity() { - private val future = CompletableFuture<Instrumentation.ActivityResult>() - - fun startActivityForFuture(intent: Intent): CompletableFuture<Instrumentation.ActivityResult> { + fun startActivityForFuture( + intent: Intent, + future: CompletableFuture<Instrumentation.ActivityResult> + ) { startActivityForResult(intent, 1) - return future + StartForFutureActivity.future = future } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - - future.complete(Instrumentation.ActivityResult(resultCode, data)) + future!!.complete(Instrumentation.ActivityResult(resultCode, data)) + future = null finish() } -}
\ No newline at end of file + + companion object { + private var future: CompletableFuture<Instrumentation.ActivityResult>? = null + } +} diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java index 12574e27695..226cc809a0e 100644 --- a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java +++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java @@ -16,7 +16,8 @@ package android.telecom.cts; -import static android.telecom.cts.TestUtils.*; +import static android.telecom.cts.TestUtils.InvokeCounter; +import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS; import android.os.Bundle; import android.os.Handler; @@ -29,7 +30,6 @@ import android.telecom.PhoneAccountHandle; import android.telecom.RemoteConference; import android.telecom.RemoteConnection; import android.telecom.TelecomManager; -import android.util.Log; import java.util.ArrayList; import java.util.List; @@ -59,6 +59,13 @@ public class RemoteConferenceTest extends BaseRemoteTelecomTest { MockConference mConference, mRemoteConference; RemoteConference mRemoteConferenceObject; + @Override + public void tearDown() throws Exception { + mRemoteConference.destroy(); + mConference.destroy(); + super.tearDown(); + } + public void testRemoteConferenceCreate() { if (!mShouldTestTelecom) { return; diff --git a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java index c8908890906..60b03b72c58 100644 --- a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java +++ b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java @@ -16,8 +16,18 @@ package android.telecom.cts; +import static android.media.AudioManager.MODE_IN_CALL; +import static android.media.AudioManager.MODE_IN_COMMUNICATION; +import static android.telecom.cts.TestUtils.SELF_MANAGED_ACCOUNT_LABEL; +import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1; +import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS; +import static android.telecom.cts.TestUtils.waitOnAllHandlers; + +import static org.junit.Assert.assertNotEquals; + import android.content.Context; import android.database.Cursor; +import android.graphics.Color; import android.media.AudioManager; import android.net.Uri; import android.provider.CallLog; @@ -35,14 +45,6 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.function.Predicate; -import static android.media.AudioManager.MODE_IN_COMMUNICATION; -import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1; -import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_4; -import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS; -import static android.telecom.cts.TestUtils.waitOnAllHandlers; - -import static org.junit.Assert.assertNotEquals; - /** * CTS tests for the self-managed {@link android.telecom.ConnectionService} APIs. * For more information about these APIs, see {@link android.telecom}, and @@ -123,6 +125,33 @@ public class SelfManagedConnectionServiceTest extends BaseTelecomTestWithMockSer TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_3); } + public void testSelfManagedConnectionServiceRegistrationUnmodifiable() { + if (!mShouldTestTelecom) { + return; + } + + verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_1, + TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1); + PhoneAccount newPhoneAccount = PhoneAccount.builder( + TEST_SELF_MANAGED_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL) + .setAddress(Uri.parse("sip:test@test.com")) + .setSubscriptionAddress(Uri.parse("sip:test@test.com")) + .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER + | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING + | PhoneAccount.CAPABILITY_VIDEO_CALLING) + .setHighlightColor(Color.BLUE) + .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL) + .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) + .addSupportedUriScheme(PhoneAccount.SCHEME_SIP) + .build(); + try { + mTelecomManager.registerPhoneAccount(newPhoneAccount); + fail("Self-managed phone account can be replaced to a call provider phone account!"); + } catch (IllegalArgumentException e) { + // expected + } + } + private void verifyAccountRegistration(PhoneAccountHandle handle, PhoneAccount phoneAccount) { // The phone account is registered in the setup method. assertPhoneAccountRegistered(handle); diff --git a/tests/tests/webkit/Android.bp b/tests/tests/webkit/Android.bp index a046dae6fe3..0b206ff019c 100644 --- a/tests/tests/webkit/Android.bp +++ b/tests/tests/webkit/Android.bp @@ -16,9 +16,11 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } -android_test { - name: "CtsWebkitTestCases", +android_library { + name: "CtsWebkitTestCasesSharedWithSdk", defaults: ["cts_defaults"], + manifest: "shared/AndroidManifest.xml", + resource_dirs: ["shared/res"], libs: [ "android.test.runner", "org.apache.http.legacy", @@ -31,11 +33,24 @@ android_test { "ctstestserver", "ctstestrunner-axt", "hamcrest-library", + "ctswebkitsharedenv", ], srcs: [ "src/**/*.java", "src/**/*.aidl", ], + // uncomment when dalvik.annotation.Test* are removed or part of SDK + //sdk_version: "current" + platform_apis: true, +} + +android_test { + name: "CtsWebkitTestCases", + defaults: ["cts_defaults"], + resource_dirs: ["res"], + static_libs: [ + "CtsWebkitTestCasesSharedWithSdk", + ], // Tag this module as a cts test artifact test_suites: [ "cts", diff --git a/tests/uwb/AndroidManifest.xml b/tests/tests/webkit/shared/AndroidManifest.xml index adecade4144..fc3e5cd97b3 100644 --- a/tests/uwb/AndroidManifest.xml +++ b/tests/tests/webkit/shared/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 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. @@ -16,13 +16,5 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="android.uwb.cts"> - - <!-- self-instrumenting test package. --> - <instrumentation - android:name="androidx.test.runner.AndroidJUnitRunner" - android:label="CTS tests for android.uwb" - android:targetPackage="android.uwb.cts" > - </instrumentation> + package="android.webkit.cts"> </manifest> - diff --git a/tests/tests/webkit/shared/README.md b/tests/tests/webkit/shared/README.md new file mode 100644 index 00000000000..73054f4c600 --- /dev/null +++ b/tests/tests/webkit/shared/README.md @@ -0,0 +1,7 @@ +# Shared with SDK resources + +This directory contains any resources that +should be shared with the WebView SDK Runtime tests. + +It also contains the AndroidManifest.xml that will be used +to create a shared library.
\ No newline at end of file diff --git a/tests/tests/webkit/res/layout/webview_layout.xml b/tests/tests/webkit/shared/res/layout/webview_layout.xml index d266d21305b..d266d21305b 100644 --- a/tests/tests/webkit/res/layout/webview_layout.xml +++ b/tests/tests/webkit/shared/res/layout/webview_layout.xml diff --git a/tests/tests/webkit/res/raw/trustedcert.crt b/tests/tests/webkit/shared/res/raw/trustedcert.crt index d9fad3584d0..d9fad3584d0 100644 --- a/tests/tests/webkit/res/raw/trustedcert.crt +++ b/tests/tests/webkit/shared/res/raw/trustedcert.crt diff --git a/tests/tests/webkit/res/raw/trustedkey.der b/tests/tests/webkit/shared/res/raw/trustedkey.der Binary files differindex 5ac993a4ed1..5ac993a4ed1 100644 --- a/tests/tests/webkit/res/raw/trustedkey.der +++ b/tests/tests/webkit/shared/res/raw/trustedkey.der diff --git a/tests/tests/webkit/res/raw/untrustedcert.crt b/tests/tests/webkit/shared/res/raw/untrustedcert.crt index c75e8938302..c75e8938302 100644 --- a/tests/tests/webkit/res/raw/untrustedcert.crt +++ b/tests/tests/webkit/shared/res/raw/untrustedcert.crt diff --git a/tests/tests/webkit/res/raw/untrustedkey.der b/tests/tests/webkit/shared/res/raw/untrustedkey.der Binary files differindex 134bef87868..134bef87868 100644 --- a/tests/tests/webkit/res/raw/untrustedkey.der +++ b/tests/tests/webkit/shared/res/raw/untrustedkey.der diff --git a/tests/tests/webkit/res/xml/network_security_config.xml b/tests/tests/webkit/shared/res/xml/network_security_config.xml index b641eff73c5..b641eff73c5 100644 --- a/tests/tests/webkit/res/xml/network_security_config.xml +++ b/tests/tests/webkit/shared/res/xml/network_security_config.xml diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java index 7ca3f468353..056cce9ff08 100755 --- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java +++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java @@ -78,7 +78,6 @@ import android.webkit.cts.WebViewSyncLoader.WaitForProgressClient; import android.widget.LinearLayout; import androidx.test.InstrumentationRegistry; -import androidx.test.core.app.ActivityScenario; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -123,7 +122,7 @@ import java.util.concurrent.atomic.AtomicReference; @AppModeFull @RunWith(AndroidJUnit4.class) -public class WebViewTest { +public class WebViewTest extends SharedWebViewTest { private static final int INITIAL_PROGRESS = 100; private static final String X_REQUESTED_WITH = "X-Requested-With"; private static final String PRINTER_TEST_FILE = "print.pdf"; @@ -156,36 +155,19 @@ public class WebViewTest { public ActivityScenarioRule mActivityScenarioRule = new ActivityScenarioRule(WebViewCtsActivity.class); - private ActivityScenario mScenario; - private WebViewCtsActivity mActivity; private WebView mWebView; - private CtsTestServer mWebServer; private WebViewOnUiThread mOnUiThread; + + // TODO(bewise): Get rid of all of these member variables + // once all these tests are referencing the test environment. + private WebViewCtsActivity mActivity; + private CtsTestServer mWebServer; private WebIconDatabase mIconDb; @Before public void setUp() throws Exception { - mScenario = mActivityScenarioRule.getScenario(); - mScenario.onActivity( - activity -> { - mActivity = (WebViewCtsActivity) activity; - mWebView = mActivity.getWebView(); - }); - if (mWebView != null) { - new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) { - @Override - protected boolean check() { - return mActivity.hasWindowFocus(); - } - }.run(); - File f = mActivity.getFileStreamPath("snapshot"); - if (f.exists()) { - f.delete(); - } - - mOnUiThread = new WebViewOnUiThread(mWebView); - } - Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable()); + mWebView = getTestEnvironment().getWebView(); + mOnUiThread = getTestEnvironment().getWebViewOnUiThread(); } @After @@ -204,6 +186,46 @@ public class WebViewTest { mActivity = null; } + @Override + protected SharedWebViewTestEnvironment createTestEnvironment() { + Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable()); + + SharedWebViewTestEnvironment.Builder builder = new SharedWebViewTestEnvironment.Builder() + .setHostAppInvoker(SharedWebViewTestEnvironment.createHostAppInvoker()); + + mActivityScenarioRule.getScenario().onActivity(activity -> { + mActivity = (WebViewCtsActivity) activity; + builder.setContext(mActivity); + + WebView webView = mActivity.getWebView(); + builder.setWebView(webView); + + if (webView != null) { + WebViewOnUiThread onUi = new WebViewOnUiThread(webView); + builder.setWebViewOnUiThread(onUi); + } + }); + + SharedWebViewTestEnvironment environment = builder.build(); + + // Wait for window focus and clean up the snapshot before + // returning the test environment. + if (environment.getWebView() != null) { + new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) { + @Override + protected boolean check() { + return mActivity.hasWindowFocus(); + } + }.run(); + File f = mActivity.getFileStreamPath("snapshot"); + if (f.exists()) { + f.delete(); + } + } + + return environment; + } + private void startWebServer(boolean secure) throws Exception { assertNull(mWebServer); mWebServer = new CtsTestServer(mActivity, secure); @@ -1704,7 +1726,8 @@ public class WebViewTest { return mOnUiThread.getContentHeight() >= dimension; } }.run(); - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + + getTestEnvironment().waitForIdleSync(); final int previousScrollX = mOnUiThread.getScrollX(); final int previousScrollY = mOnUiThread.getScrollY(); diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java index 279e2426d59..010711963d8 100644 --- a/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java +++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java @@ -27,6 +27,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assume.assumeTrue; import android.app.UiAutomation; +import android.app.compat.CompatChanges; import android.content.Context; import android.net.IpConfiguration; import android.net.LinkAddress; @@ -91,6 +92,7 @@ public class WifiBackupRestoreTest extends WifiJUnit4TestBase { public static final int EXPECTED_LEGACY_STATIC_PROXY_PORT = 8000; public static final String EXPECTED_LEGACY_STATIC_PROXY_EXCLUSION_LIST = ""; public static final String EXPECTED_LEGACY_PAC_PROXY_LOCATION = "http://"; + private static final long NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE = 234793325L; private Context mContext; private WifiManager mWifiManager; @@ -201,12 +203,10 @@ public class WifiBackupRestoreTest extends WifiJUnit4TestBase { Log.e(TAG, "Need a non-enterprise and non-Passpoint network created by an app " + "holding OVERRIDE_WIFI_CONFIG permission to fully evaluate the " + "functionality"); - } - - // Retrieve backup data. - byte[] backupData = mWifiManager.retrieveBackupData(); + } else { - if (origNetwork != null) { + // Retrieve backup data. + byte[] backupData = mWifiManager.retrieveBackupData(); // Modify the metered bit. final String origNetworkSsid = origNetwork.SSID; WifiConfiguration modNetwork = new WifiConfiguration(origNetwork); @@ -219,19 +219,26 @@ public class WifiBackupRestoreTest extends WifiJUnit4TestBase { .findAny() .get().meteredOverride) .isNotEqualTo(origNetwork.meteredOverride); - } - - // Restore the original backup data & ensure that the metered bit is back to orig. - mWifiManager.restoreBackupData(backupData); - if (origNetwork != null) { - final String origNetworkSsid = origNetwork.SSID; - assertThat(mWifiManager.getConfiguredNetworks() - .stream() - .filter(n -> n.SSID.equals(origNetworkSsid)) - .findAny() - .get().meteredOverride) - .isEqualTo(origNetwork.meteredOverride); + // Restore the original backup data & ensure that the metered bit is back to orig. + mWifiManager.restoreBackupData(backupData); + + if (CompatChanges.isChangeEnabled(NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE)) { + assertThat(mWifiManager.getConfiguredNetworks() + .stream() + .filter(n -> n.SSID.equals(origNetworkSsid)) + .findAny() + .get().meteredOverride) + .isNotEqualTo(origNetwork.meteredOverride); + + } else { + assertThat(mWifiManager.getConfiguredNetworks() + .stream() + .filter(n -> n.SSID.equals(origNetworkSsid)) + .findAny() + .get().meteredOverride) + .isEqualTo(origNetwork.meteredOverride); + } } } finally { // Restore the orig network diff --git a/tests/uwb/AndroidTest.xml b/tests/uwb/AndroidTest.xml deleted file mode 100644 index 3104ec545cd..00000000000 --- a/tests/uwb/AndroidTest.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2021 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<configuration description="Config for CTS UWB test cases"> - <option name="test-suite-tag" value="cts" /> - <option name="config-descriptor:metadata" key="component" value="framework" /> - <option name="config-descriptor:metadata" key="parameter" value="instant_app" /> - <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> - <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> - <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.uwb.apex" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="CtsUwbTestCases.apk" /> - </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="android.uwb.cts" /> - </test> - <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.uwb" /> - </object> -</configuration> diff --git a/tests/uwb/OWNERS b/tests/uwb/OWNERS deleted file mode 100644 index c4ad4164e13..00000000000 --- a/tests/uwb/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# Bug component: 1042770 -include platform/packages/modules/Uwb:/OWNERS diff --git a/tests/uwb/src/android/uwb/cts/AngleMeasurementTest.java b/tests/uwb/src/android/uwb/cts/AngleMeasurementTest.java deleted file mode 100644 index f96b79886d7..00000000000 --- a/tests/uwb/src/android/uwb/cts/AngleMeasurementTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; -import android.uwb.AngleMeasurement; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link AngleMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class AngleMeasurementTest { - @Test - public void testConstructs() { - double radians = 0.1234; - double errorRadians = 0.5678; - double confidence = 0.5; - - AngleMeasurement measurement = new AngleMeasurement(radians, errorRadians, confidence); - assertEquals(measurement.getRadians(), radians, 0); - assertEquals(measurement.getErrorRadians(), errorRadians, 0); - assertEquals(measurement.getConfidenceLevel(), confidence, 0); - } - - @Test - public void testInvalidRadians() { - double radians = Math.PI + 0.01; - double errorRadians = 0.5678; - double confidence = 0.5; - - constructExpectFailure(radians, errorRadians, confidence); - constructExpectFailure(-radians, errorRadians, confidence); - } - - @Test - public void testInvalidErrorRadians() { - double radians = 0.1234; - double confidence = 0.5; - - constructExpectFailure(radians, -0.01, confidence); - constructExpectFailure(-radians, Math.PI + 0.01, confidence); - } - - @Test - public void testInvalidConfidence() { - double radians = 0.1234; - double errorRadians = 0.5678; - - constructExpectFailure(radians, errorRadians, -0.01); - constructExpectFailure(radians, errorRadians, 1.01); - } - - private void constructExpectFailure(double radians, double errorRadians, double confidence) { - try { - new AngleMeasurement(radians, errorRadians, confidence); - fail(); - } catch (IllegalArgumentException e) { - // Expected - } - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - AngleMeasurement measurement = UwbTestUtils.getAngleMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AngleMeasurement fromParcel = AngleMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/tests/uwb/src/android/uwb/cts/AngleOfArrivalMeasurementTest.java b/tests/uwb/src/android/uwb/cts/AngleOfArrivalMeasurementTest.java deleted file mode 100644 index 085ce2e5a23..00000000000 --- a/tests/uwb/src/android/uwb/cts/AngleOfArrivalMeasurementTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; -import android.uwb.AngleMeasurement; -import android.uwb.AngleOfArrivalMeasurement; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link AngleOfArrivalMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class AngleOfArrivalMeasurementTest { - - @Test - public void testBuilder() { - AngleMeasurement azimuth = UwbTestUtils.getAngleMeasurement(); - AngleMeasurement altitude = UwbTestUtils.getAngleMeasurement(); - - AngleOfArrivalMeasurement.Builder builder = new AngleOfArrivalMeasurement.Builder(azimuth); - builder.setAltitude(altitude); - - AngleOfArrivalMeasurement measurement = tryBuild(builder, true); - - assertEquals(azimuth, measurement.getAzimuth()); - assertEquals(altitude, measurement.getAltitude()); - } - - private AngleOfArrivalMeasurement tryBuild(AngleOfArrivalMeasurement.Builder builder, - boolean expectSuccess) { - AngleOfArrivalMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected AngleOfArrivalMeasurement.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected AngleOfArrivalMeasurement.Builder.build() to succeed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - AngleOfArrivalMeasurement measurement = UwbTestUtils.getAngleOfArrivalMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - AngleOfArrivalMeasurement fromParcel = - AngleOfArrivalMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/tests/uwb/src/android/uwb/cts/DistanceMeasurementTest.java b/tests/uwb/src/android/uwb/cts/DistanceMeasurementTest.java deleted file mode 100644 index fdebc78d994..00000000000 --- a/tests/uwb/src/android/uwb/cts/DistanceMeasurementTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; -import android.uwb.DistanceMeasurement; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link DistanceMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class DistanceMeasurementTest { - private static final double EPSILON = 0.00000000001; - - @Test - public void testBuilder() { - double meters = 0.12; - double error = 0.54; - double confidence = 0.99; - - DistanceMeasurement.Builder builder = new DistanceMeasurement.Builder(); - tryBuild(builder, false); - - builder.setMeters(meters); - tryBuild(builder, false); - - builder.setErrorMeters(error); - tryBuild(builder, false); - - builder.setConfidenceLevel(confidence); - DistanceMeasurement measurement = tryBuild(builder, true); - - assertEquals(meters, measurement.getMeters(), 0); - assertEquals(error, measurement.getErrorMeters(), 0); - assertEquals(confidence, measurement.getConfidenceLevel(), 0); - } - - private DistanceMeasurement tryBuild(DistanceMeasurement.Builder builder, - boolean expectSuccess) { - DistanceMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected DistanceMeasurement.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected DistanceMeasurement.Builder.build() to succeed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - DistanceMeasurement measurement = UwbTestUtils.getDistanceMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - DistanceMeasurement fromParcel = - DistanceMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/tests/uwb/src/android/uwb/cts/RangingMeasurementTest.java b/tests/uwb/src/android/uwb/cts/RangingMeasurementTest.java deleted file mode 100644 index bc5c2fd12eb..00000000000 --- a/tests/uwb/src/android/uwb/cts/RangingMeasurementTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.os.Parcel; -import android.os.SystemClock; -import android.uwb.AngleOfArrivalMeasurement; -import android.uwb.DistanceMeasurement; -import android.uwb.RangingMeasurement; -import android.uwb.UwbAddress; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link RangingMeasurement}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class RangingMeasurementTest { - private static final int TEST_RSSI_DBM = -80; - private static final int INVALID_RSSI_DBM = -129; - - @Test - public void testBuilder() { - int status = RangingMeasurement.RANGING_STATUS_SUCCESS; - UwbAddress address = UwbTestUtils.getUwbAddress(false); - long time = SystemClock.elapsedRealtimeNanos(); - AngleOfArrivalMeasurement angleMeasurement = UwbTestUtils.getAngleOfArrivalMeasurement(); - AngleOfArrivalMeasurement destinationAngleMeasurement = - UwbTestUtils.getAngleOfArrivalMeasurement(); - DistanceMeasurement distanceMeasurement = UwbTestUtils.getDistanceMeasurement(); - int los = RangingMeasurement.NLOS; - int measurementFocus = RangingMeasurement.MEASUREMENT_FOCUS_RANGE; - - - RangingMeasurement.Builder builder = new RangingMeasurement.Builder(); - - builder.setStatus(status); - tryBuild(builder, false); - - builder.setElapsedRealtimeNanos(time); - tryBuild(builder, false); - - builder.setAngleOfArrivalMeasurement(angleMeasurement); - tryBuild(builder, false); - - builder.setDestinationAngleOfArrivalMeasurement(destinationAngleMeasurement); - tryBuild(builder, false); - - builder.setDistanceMeasurement(distanceMeasurement); - tryBuild(builder, false); - - builder.setRssiDbm(TEST_RSSI_DBM); - tryBuild(builder, false); - - builder.setRemoteDeviceAddress(address); - tryBuild(builder, true); - - builder.setLineOfSight(los); - tryBuild(builder, true); - - builder.setMeasurementFocus(measurementFocus); - RangingMeasurement measurement = tryBuild(builder, true); - - assertEquals(status, measurement.getStatus()); - assertEquals(address, measurement.getRemoteDeviceAddress()); - assertEquals(time, measurement.getElapsedRealtimeNanos()); - assertEquals(angleMeasurement, measurement.getAngleOfArrivalMeasurement()); - assertEquals(destinationAngleMeasurement, - measurement.getDestinationAngleOfArrivalMeasurement()); - assertEquals(distanceMeasurement, measurement.getDistanceMeasurement()); - assertEquals(los, measurement.getLineOfSight()); - assertEquals(measurementFocus, measurement.getMeasurementFocus()); - assertEquals(TEST_RSSI_DBM, measurement.getRssiDbm()); - } - - @Test - public void testInvalidRssi() { - RangingMeasurement.Builder builder = new RangingMeasurement.Builder(); - try { - builder.setRssiDbm(INVALID_RSSI_DBM); - fail("Expected RangingMeasurement.Builder.setRssiDbm() to fail"); - } catch (Exception e) { - assertTrue(e.getMessage().contains("Invalid")); - } - } - - private RangingMeasurement tryBuild(RangingMeasurement.Builder builder, - boolean expectSuccess) { - RangingMeasurement measurement = null; - try { - measurement = builder.build(); - if (!expectSuccess) { - fail("Expected RangingMeasurement.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected DistanceMeasurement.Builder.build() to succeed"); - } - } - return measurement; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - RangingMeasurement measurement = UwbTestUtils.getRangingMeasurement(); - measurement.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - RangingMeasurement fromParcel = RangingMeasurement.CREATOR.createFromParcel(parcel); - assertEquals(measurement, fromParcel); - } -} diff --git a/tests/uwb/src/android/uwb/cts/RangingReportTest.java b/tests/uwb/src/android/uwb/cts/RangingReportTest.java deleted file mode 100644 index 561568972ed..00000000000 --- a/tests/uwb/src/android/uwb/cts/RangingReportTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.Parcel; -import android.os.PersistableBundle; -import android.uwb.RangingMeasurement; -import android.uwb.RangingReport; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.google.uwb.support.oemextension.RangingReportMetadata; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -/** - * Test of {@link RangingReport}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class RangingReportTest { - - @Test - public void testBuilder() { - List<RangingMeasurement> measurements = UwbTestUtils.getRangingMeasurements(5); - long sessionId = 1; - byte[] rawNtf = new byte[]{0x01, 0x02, 0x02}; - PersistableBundle rangingReportMetadata = new RangingReportMetadata.Builder() - .setSessionId(sessionId) - .setRawNtfData(rawNtf) - .build() - .toBundle(); - - RangingReport.Builder builder = new RangingReport.Builder(); - builder.addMeasurements(measurements); - RangingReport report = tryBuild(builder, true); - verifyMeasurementsEqual(measurements, report.getMeasurements()); - builder = new RangingReport.Builder(); - for (RangingMeasurement measurement : measurements) { - builder.addMeasurement(measurement); - } - report = tryBuild(builder, true); - verifyMeasurementsEqual(measurements, report.getMeasurements()); - - builder.addRangingReportMetadata(rangingReportMetadata); - report = tryBuild(builder, true); - - assertEquals(rangingReportMetadata, report.getRangingReportMetadata()); - } - - private void verifyMeasurementsEqual(List<RangingMeasurement> expected, - List<RangingMeasurement> actual) { - assertEquals(expected.size(), actual.size()); - for (int i = 0; i < expected.size(); i++) { - assertEquals(expected.get(i), actual.get(i)); - } - } - - private RangingReport tryBuild(RangingReport.Builder builder, - boolean expectSuccess) { - RangingReport report = null; - try { - report = builder.build(); - if (!expectSuccess) { - fail("Expected RangingReport.Builder.build() to fail"); - } - } catch (IllegalStateException e) { - if (expectSuccess) { - fail("Expected RangingReport.Builder.build() to succeed"); - } - } - return report; - } - - @Test - public void testParcel() { - Parcel parcel = Parcel.obtain(); - RangingReport report = UwbTestUtils.getRangingReports(5); - report.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - RangingReport fromParcel = RangingReport.CREATOR.createFromParcel(parcel); - assertEquals(report, fromParcel); - } -} diff --git a/tests/uwb/src/android/uwb/cts/UwbAddressTest.java b/tests/uwb/src/android/uwb/cts/UwbAddressTest.java deleted file mode 100644 index d2f42286c0b..00000000000 --- a/tests/uwb/src/android/uwb/cts/UwbAddressTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static org.junit.Assert.assertEquals; - -import android.os.Parcel; -import android.uwb.UwbAddress; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test of {@link UwbAddress}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public class UwbAddressTest { - - @Test - public void testFromBytes_Short() { - runFromBytes(UwbAddress.SHORT_ADDRESS_BYTE_LENGTH); - } - - @Test - public void testFromBytes_Extended() { - runFromBytes(UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH); - } - - private void runFromBytes(int len) { - byte[] addressBytes = getByteArray(len); - UwbAddress address = UwbAddress.fromBytes(addressBytes); - assertEquals(address.size(), len); - assertEquals(addressBytes, address.toBytes()); - } - - private byte[] getByteArray(int len) { - byte[] res = new byte[len]; - for (int i = 0; i < len; i++) { - res[i] = (byte) i; - } - return res; - } - - @Test - public void testParcel_Short() { - runParcel(true); - } - - @Test - public void testParcel_Extended() { - runParcel(false); - } - - private void runParcel(boolean useShortAddress) { - Parcel parcel = Parcel.obtain(); - UwbAddress address = UwbTestUtils.getUwbAddress(useShortAddress); - address.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - UwbAddress fromParcel = UwbAddress.CREATOR.createFromParcel(parcel); - assertEquals(address, fromParcel); - } -} diff --git a/tests/uwb/src/android/uwb/cts/UwbFrameworkInitializerTest.java b/tests/uwb/src/android/uwb/cts/UwbFrameworkInitializerTest.java deleted file mode 100644 index ddd22c6c8ea..00000000000 --- a/tests/uwb/src/android/uwb/cts/UwbFrameworkInitializerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.uwb.cts; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.content.Context; -import android.platform.test.annotations.AppModeFull; -import android.uwb.UwbFrameworkInitializer; -import android.uwb.UwbManager; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import androidx.test.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -/** - * Test of {@link UwbManager}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -@AppModeFull(reason = "Cannot get UwbManager in instant app mode") -public class UwbFrameworkInitializerTest { - private final Context mContext = InstrumentationRegistry.getContext(); - private UwbManager mUwbManager; - - @Before - public void setup() throws Exception { - mUwbManager = mContext.getSystemService(UwbManager.class); - assumeTrue(UwbTestUtils.isUwbSupported(mContext)); - assertThat(mUwbManager).isNotNull(); - } - - /** - * UwbFrameworkInitializer.registerServiceWrappers() should only be called by - * SystemServiceRegistry during boot up when Uwb is first initialized. Calling this API at - * any other time should throw an exception. - */ - @Test - public void testRegisterServiceWrappers_failsWhenCalledOutsideOfSystemServiceRegistry() { - try { - UwbFrameworkInitializer.registerServiceWrappers(); - fail("Expected exception when calling " - + "UwbFrameworkInitializer.registerServiceWrappers() outside of " - + "SystemServiceRegistry!"); - } catch (IllegalStateException expected) { } - } -} diff --git a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java b/tests/uwb/src/android/uwb/cts/UwbManagerTest.java deleted file mode 100644 index f10eb11d018..00000000000 --- a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java +++ /dev/null @@ -1,1350 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import static android.Manifest.permission.UWB_PRIVILEGED; -import static android.Manifest.permission.UWB_RANGING; -import static android.uwb.UwbManager.AdapterStateCallback.STATE_DISABLED; -import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE; -import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import static java.util.Objects.requireNonNull; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.UiAutomation; -import android.content.AttributionSource; -import android.content.Context; -import android.content.ContextParams; -import android.os.CancellationSignal; -import android.os.PersistableBundle; -import android.os.Process; -import android.permission.PermissionManager; -import android.platform.test.annotations.AppModeFull; -import android.util.Log; -import android.uwb.RangingReport; -import android.uwb.RangingSession; -import android.uwb.UwbAddress; -import android.uwb.UwbManager; - -import androidx.test.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.compatibility.common.util.CddTest; -import com.android.compatibility.common.util.ShellIdentityUtils; -import com.android.modules.utils.build.SdkLevel; - -import com.google.uwb.support.fira.FiraControleeParams; -import com.google.uwb.support.fira.FiraOpenSessionParams; -import com.google.uwb.support.fira.FiraParams; -import com.google.uwb.support.fira.FiraProtocolVersion; -import com.google.uwb.support.fira.FiraSpecificationParams; -import com.google.uwb.support.multichip.ChipInfoParams; -import com.google.uwb.support.oemextension.DeviceStatus; -import com.google.uwb.support.oemextension.RangingReportMetadata; -import com.google.uwb.support.oemextension.SessionStatus; - -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.EnumSet; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * Test of {@link UwbManager}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -@AppModeFull(reason = "Cannot get UwbManager in instant app mode") -public class UwbManagerTest { - private static final String TAG = "UwbManagerTest"; - - private final Context mContext = InstrumentationRegistry.getContext(); - private UwbManager mUwbManager; - private String mDefaultChipId; - public static final int UWB_SESSION_STATE_IDLE = 0x03; - public static final byte DEVICE_STATE_ACTIVE = 0x02; - public static final int REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS = 0x00; - - @Before - public void setup() throws Exception { - mUwbManager = mContext.getSystemService(UwbManager.class); - assumeTrue(UwbTestUtils.isUwbSupported(mContext)); - assertThat(mUwbManager).isNotNull(); - - // Ensure UWB is toggled on. - ShellIdentityUtils.invokeWithShellPermissions(() -> { - if (!mUwbManager.isUwbEnabled()) { - try { - setUwbEnabledAndWaitForCompletion(true); - } catch (Exception e) { - fail("Exception while processing UWB toggle " + e); - } - } - mDefaultChipId = mUwbManager.getDefaultChipId(); - }); - } - - // Should be invoked with shell permissions. - private void setUwbEnabledAndWaitForCompletion(boolean enabled) throws Exception { - CountDownLatch countDownLatch = new CountDownLatch(1); - int adapterState = enabled ? STATE_ENABLED_INACTIVE : STATE_DISABLED; - AdapterStateCallback adapterStateCallback = - new AdapterStateCallback(countDownLatch, adapterState); - try { - mUwbManager.registerAdapterStateCallback( - Executors.newSingleThreadExecutor(), adapterStateCallback); - mUwbManager.setUwbEnabled(enabled); - assertThat(countDownLatch.await(2, TimeUnit.SECONDS)).isTrue(); - assertThat(mUwbManager.isUwbEnabled()).isEqualTo(enabled); - assertThat(adapterStateCallback.state).isEqualTo(adapterState); - } finally { - mUwbManager.unregisterAdapterStateCallback(adapterStateCallback); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetSpecificationInfo() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - PersistableBundle persistableBundle = mUwbManager.getSpecificationInfo(); - assertThat(persistableBundle).isNotNull(); - assertThat(persistableBundle.isEmpty()).isFalse(); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetSpecificationInfoWithChipId() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - PersistableBundle persistableBundle = - mUwbManager.getSpecificationInfo(mDefaultChipId); - assertThat(persistableBundle).isNotNull(); - assertThat(persistableBundle.isEmpty()).isFalse(); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetChipInfos() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - List<PersistableBundle> chipInfos = mUwbManager.getChipInfos(); - assertThat(chipInfos).hasSize(1); - ChipInfoParams chipInfoParams = ChipInfoParams.fromBundle(chipInfos.get(0)); - assertThat(chipInfoParams.getChipId()).isEqualTo(mDefaultChipId); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetSpecificationInfoWithInvalidChipId() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - assertThrows(IllegalArgumentException.class, - () -> mUwbManager.getSpecificationInfo("invalidChipId")); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetSpecificationInfoWithoutUwbPrivileged() { - try { - mUwbManager.getSpecificationInfo(); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetSpecificationInfoWithChipIdWithoutUwbPrivileged() { - try { - mUwbManager.getSpecificationInfo(mDefaultChipId); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testElapsedRealtimeResolutionNanos() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - assertThat(mUwbManager.elapsedRealtimeResolutionNanos() >= 0L).isTrue(); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testElapsedRealtimeResolutionNanosWithChipId() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - assertThat(mUwbManager.elapsedRealtimeResolutionNanos(mDefaultChipId) >= 0L) - .isTrue(); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testElapsedRealtimeResolutionNanosWithInvalidChipId() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - assertThrows(IllegalArgumentException.class, - () -> mUwbManager.elapsedRealtimeResolutionNanos("invalidChipId")); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testElapsedRealtimeResolutionNanosWithoutUwbPrivileged() { - try { - mUwbManager.elapsedRealtimeResolutionNanos(); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testElapsedRealtimeResolutionNanosWithChipIdWithoutUwbPrivileged() { - try { - mUwbManager.elapsedRealtimeResolutionNanos(mDefaultChipId); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testAddServiceProfileWithoutUwbPrivileged() { - try { - mUwbManager.addServiceProfile(new PersistableBundle()); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testRemoveServiceProfileWithoutUwbPrivileged() { - try { - mUwbManager.removeServiceProfile(new PersistableBundle()); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetAllServiceProfilesWithoutUwbPrivileged() { - try { - mUwbManager.getAllServiceProfiles(); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetAdfProvisioningAuthoritiesWithoutUwbPrivileged() { - try { - mUwbManager.getAdfProvisioningAuthorities(new PersistableBundle()); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetAdfCertificateInfoWithoutUwbPrivileged() { - try { - mUwbManager.getAdfCertificateInfo(new PersistableBundle()); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testGetChipInfosWithoutUwbPrivileged() { - try { - mUwbManager.getChipInfos(); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testSendVendorUciWithoutUwbPrivileged() { - try { - mUwbManager.sendVendorUciMessage(10, 0, new byte[0]); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - private class AdfProvisionStateCallback extends UwbManager.AdfProvisionStateCallback { - private final CountDownLatch mCountDownLatch; - - public boolean onSuccessCalled; - public boolean onFailedCalled; - - AdfProvisionStateCallback(@NonNull CountDownLatch countDownLatch) { - mCountDownLatch = countDownLatch; - } - - @Override - public void onProfileAdfsProvisioned(@NonNull PersistableBundle params) { - onSuccessCalled = true; - mCountDownLatch.countDown(); - } - - @Override - public void onProfileAdfsProvisionFailed(int reason, @NonNull PersistableBundle params) { - onFailedCalled = true; - mCountDownLatch.countDown(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testProvisionProfileAdfByScriptWithoutUwbPrivileged() { - CountDownLatch countDownLatch = new CountDownLatch(1); - AdfProvisionStateCallback adfProvisionStateCallback = - new AdfProvisionStateCallback(countDownLatch); - try { - mUwbManager.provisionProfileAdfByScript( - new PersistableBundle(), - Executors.newSingleThreadExecutor(), - adfProvisionStateCallback); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testRemoveProfileAdfWithoutUwbPrivileged() { - try { - mUwbManager.removeProfileAdf(new PersistableBundle()); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - private class UwbVendorUciCallback implements UwbManager.UwbVendorUciCallback { - private final CountDownLatch mRspCountDownLatch; - private final CountDownLatch mNtfCountDownLatch; - - public int gid; - public int oid; - public byte[] payload; - - UwbVendorUciCallback( - @NonNull CountDownLatch rspCountDownLatch, - @NonNull CountDownLatch ntfCountDownLatch) { - mRspCountDownLatch = rspCountDownLatch; - mNtfCountDownLatch = ntfCountDownLatch; - } - - @Override - public void onVendorUciResponse(int gid, int oid, byte[] payload) { - this.gid = gid; - this.oid = oid; - this.payload = payload; - mRspCountDownLatch.countDown(); - } - - @Override - public void onVendorUciNotification(int gid, int oid, byte[] payload) { - this.gid = gid; - this.oid = oid; - this.payload = payload; - mNtfCountDownLatch.countDown(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testRegisterVendorUciCallbackWithoutUwbPrivileged() { - UwbManager.UwbVendorUciCallback cb = - new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1)); - try { - mUwbManager.registerUwbVendorUciCallback( - Executors.newSingleThreadExecutor(), cb); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testUnregisterVendorUciCallbackWithoutUwbPrivileged() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - UwbManager.UwbVendorUciCallback cb = - new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1)); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.registerUwbVendorUciCallback( - Executors.newSingleThreadExecutor(), cb); - } catch (SecurityException e) { - /* pass */ - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - try { - mUwbManager.unregisterUwbVendorUciCallback(cb); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - try { - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.unregisterUwbVendorUciCallback(cb); - /* pass */ - } catch (SecurityException e) { - /* fail */ - fail(); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testInvalidCallbackUnregisterVendorUciCallback() { - UwbManager.UwbVendorUciCallback cb = - new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1)); - try { - mUwbManager.registerUwbVendorUciCallback( - Executors.newSingleThreadExecutor(), cb); - } catch (SecurityException e) { - /* registration failed */ - } - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.unregisterUwbVendorUciCallback(cb); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - private class RangingSessionCallback implements RangingSession.Callback { - private CountDownLatch mCtrlCountDownLatch; - private CountDownLatch mResultCountDownLatch; - - public boolean onOpenedCalled; - public boolean onOpenFailedCalled; - public boolean onStartedCalled; - public boolean onStartFailedCalled; - public boolean onReconfiguredCalled; - public boolean onReconfiguredFailedCalled; - public boolean onClosedCalled; - public RangingSession rangingSession; - public RangingReport rangingReport; - - RangingSessionCallback( - @NonNull CountDownLatch ctrlCountDownLatch) { - this(ctrlCountDownLatch, null /* resultCountDownLaynch */); - } - - RangingSessionCallback( - @NonNull CountDownLatch ctrlCountDownLatch, - @Nullable CountDownLatch resultCountDownLatch) { - mCtrlCountDownLatch = ctrlCountDownLatch; - mResultCountDownLatch = resultCountDownLatch; - } - - public void replaceCtrlCountDownLatch(@NonNull CountDownLatch countDownLatch) { - mCtrlCountDownLatch = countDownLatch; - } - - public void onOpened(@NonNull RangingSession session) { - onOpenedCalled = true; - rangingSession = session; - mCtrlCountDownLatch.countDown(); - } - - public void onOpenFailed(@Reason int reason, @NonNull PersistableBundle params) { - onOpenFailedCalled = true; - mCtrlCountDownLatch.countDown(); - } - - public void onStarted(@NonNull PersistableBundle sessionInfo) { - onStartedCalled = true; - mCtrlCountDownLatch.countDown(); - } - - public void onStartFailed(@Reason int reason, @NonNull PersistableBundle params) { - onStartFailedCalled = true; - mCtrlCountDownLatch.countDown(); - } - - public void onReconfigured(@NonNull PersistableBundle params) { - onReconfiguredCalled = true; - mCtrlCountDownLatch.countDown(); - } - - public void onReconfigureFailed(@Reason int reason, @NonNull PersistableBundle params) { - onReconfiguredFailedCalled = true; - mCtrlCountDownLatch.countDown(); - } - - public void onStopped(@Reason int reason, @NonNull PersistableBundle parameters) { } - - public void onStopFailed(@Reason int reason, @NonNull PersistableBundle params) { } - - public void onClosed(@Reason int reason, @NonNull PersistableBundle parameters) { - onClosedCalled = true; - mCtrlCountDownLatch.countDown(); - } - - public void onReportReceived(@NonNull RangingReport rangingReport) { - if (mResultCountDownLatch != null) { - this.rangingReport = rangingReport; - mResultCountDownLatch.countDown(); - } - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithInvalidChipId() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CountDownLatch countDownLatch = new CountDownLatch(1); - RangingSessionCallback rangingSessionCallback = new RangingSessionCallback(countDownLatch); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - // Try to start a ranging session with invalid params, should fail. - assertThrows(IllegalArgumentException.class, () -> mUwbManager.openRangingSession( - new PersistableBundle(), - Executors.newSingleThreadExecutor(), - rangingSessionCallback, - "invalidChipId")); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithChipIdWithBadParams() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CancellationSignal cancellationSignal = null; - CountDownLatch countDownLatch = new CountDownLatch(1); - RangingSessionCallback rangingSessionCallback = new RangingSessionCallback(countDownLatch); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - // Try to start a ranging session with invalid params, should fail. - cancellationSignal = mUwbManager.openRangingSession( - new PersistableBundle(), - Executors.newSingleThreadExecutor(), - rangingSessionCallback, - mDefaultChipId); - // Wait for the on start failed callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onOpenedCalled).isFalse(); - assertThat(rangingSessionCallback.onOpenFailedCalled).isTrue(); - } finally { - if (cancellationSignal != null) { - cancellationSignal.cancel(); - } - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithInvalidChipIdWithBadParams() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CancellationSignal cancellationSignal = null; - CountDownLatch countDownLatch = new CountDownLatch(1); - RangingSessionCallback rangingSessionCallback = new RangingSessionCallback(countDownLatch); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - // Try to start a ranging session with invalid params, should fail. - cancellationSignal = mUwbManager.openRangingSession( - new PersistableBundle(), - Executors.newSingleThreadExecutor(), - rangingSessionCallback, - mDefaultChipId); - // Wait for the on start failed callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onOpenedCalled).isFalse(); - assertThat(rangingSessionCallback.onOpenFailedCalled).isTrue(); - } finally { - if (cancellationSignal != null) { - cancellationSignal.cancel(); - } - uiAutomation.dropShellPermissionIdentity(); - } - } - - /** - * Simulates the app holding UWB_RANGING permission, but not UWB_PRIVILEGED. - */ - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithoutUwbPrivileged() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Only hold UWB_RANGING permission - uiAutomation.adoptShellPermissionIdentity(UWB_RANGING); - mUwbManager.openRangingSession(new PersistableBundle(), - Executors.newSingleThreadExecutor(), - new RangingSessionCallback(new CountDownLatch(1))); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithChipIdWithoutUwbPrivileged() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Only hold UWB_RANGING permission - uiAutomation.adoptShellPermissionIdentity(UWB_RANGING); - mUwbManager.openRangingSession(new PersistableBundle(), - Executors.newSingleThreadExecutor(), - new RangingSessionCallback(new CountDownLatch(1)), - mDefaultChipId); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - /** - * Simulates the app holding UWB_PRIVILEGED permission, but not UWB_RANGING. - */ - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithoutUwbRanging() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(UWB_PRIVILEGED); - mUwbManager.openRangingSession(new PersistableBundle(), - Executors.newSingleThreadExecutor(), - new RangingSessionCallback(new CountDownLatch(1))); - // should fail if the call was successful without UWB_RANGING permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testOpenRangingSessionWithChipIdWithoutUwbRanging() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(UWB_PRIVILEGED); - mUwbManager.openRangingSession(new PersistableBundle(), - Executors.newSingleThreadExecutor(), - new RangingSessionCallback(new CountDownLatch(1)), - mDefaultChipId); - // should fail if the call was successful without UWB_RANGING permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - private AttributionSource getShellAttributionSourceWithRenouncedPermissions( - @Nullable Set<String> renouncedPermissions) { - try { - AttributionSource shellAttributionSource = - new AttributionSource.Builder(Process.SHELL_UID) - .setPackageName("com.android.shell") - .setRenouncedPermissions(renouncedPermissions) - .build(); - PermissionManager permissionManager = - mContext.getSystemService(PermissionManager.class); - permissionManager.registerAttributionSource(shellAttributionSource); - return shellAttributionSource; - } catch (SecurityException e) { - fail("Failed to create shell attribution source" + e); - return null; - } - } - - private Context createShellContextWithRenouncedPermissionsAndAttributionSource( - @Nullable Set<String> renouncedPermissions) { - return mContext.createContext(new ContextParams.Builder() - .setRenouncedPermissions(renouncedPermissions) - .setNextAttributionSource( - getShellAttributionSourceWithRenouncedPermissions(renouncedPermissions)) - .build()); - } - - /** - * Simulates the calling app holding UWB_PRIVILEGED permission and UWB_RANGING permission, but - * the proxied app not holding UWB_RANGING permission. - */ - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"}) - public void testOpenRangingSessionWithoutUwbRangingInNextAttributeSource() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Only hold UWB_PRIVILEGED permission - uiAutomation.adoptShellPermissionIdentity(); - Context shellContextWithUwbRangingRenounced = - createShellContextWithRenouncedPermissionsAndAttributionSource( - Set.of(UWB_RANGING)); - UwbManager uwbManagerWithUwbRangingRenounced = - shellContextWithUwbRangingRenounced.getSystemService(UwbManager.class); - uwbManagerWithUwbRangingRenounced.openRangingSession(new PersistableBundle(), - Executors.newSingleThreadExecutor(), - new RangingSessionCallback(new CountDownLatch(1))); - // should fail if the call was successful without UWB_RANGING permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"}) - public void testOpenRangingSessionWithChipIdWithoutUwbRangingInNextAttributeSource() { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Only hold UWB_PRIVILEGED permission - uiAutomation.adoptShellPermissionIdentity(); - Context shellContextWithUwbRangingRenounced = - createShellContextWithRenouncedPermissionsAndAttributionSource( - Set.of(UWB_RANGING)); - UwbManager uwbManagerWithUwbRangingRenounced = - shellContextWithUwbRangingRenounced.getSystemService(UwbManager.class); - uwbManagerWithUwbRangingRenounced.openRangingSession(new PersistableBundle(), - Executors.newSingleThreadExecutor(), - new RangingSessionCallback(new CountDownLatch(1)), - mDefaultChipId); - // should fail if the call was successful without UWB_RANGING permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"}) - public void testFiraRangingSession() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CancellationSignal cancellationSignal = null; - CountDownLatch countDownLatch = new CountDownLatch(1); - CountDownLatch resultCountDownLatch = new CountDownLatch(1); - RangingSessionCallback rangingSessionCallback = - new RangingSessionCallback(countDownLatch, resultCountDownLatch); - FiraOpenSessionParams firaOpenSessionParams = new FiraOpenSessionParams.Builder() - .setProtocolVersion(new FiraProtocolVersion(1, 1)) - .setSessionId(1) - .setStsConfig(FiraParams.STS_CONFIG_STATIC) - .setVendorId(new byte[]{0x5, 0x6}) - .setStaticStsIV(new byte[]{0x5, 0x6, 0x9, 0xa, 0x4, 0x6}) - .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER) - .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR) - .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST) - .setDeviceAddress(UwbAddress.fromBytes(new byte[] {0x5, 6})) - .setDestAddressList(List.of(UwbAddress.fromBytes(new byte[] {0x5, 6}))) - .build(); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - // Try to start a ranging session with invalid params, should fail. - cancellationSignal = mUwbManager.openRangingSession( - firaOpenSessionParams.toBundle(), - Executors.newSingleThreadExecutor(), - rangingSessionCallback, - mDefaultChipId); - // Wait for the on opened callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onOpenedCalled).isTrue(); - assertThat(rangingSessionCallback.onOpenFailedCalled).isFalse(); - assertThat(rangingSessionCallback.rangingSession).isNotNull(); - - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - rangingSessionCallback.rangingSession.start(new PersistableBundle()); - // Wait for the on started callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onStartedCalled).isTrue(); - assertThat(rangingSessionCallback.onStartFailedCalled).isFalse(); - - // Wait for the on ranging report callback. - assertThat(resultCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.rangingReport).isNotNull(); - - // Check the UWB state. - assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_ACTIVE); - - // Stop ongoing session. - rangingSessionCallback.rangingSession.stop(); - } finally { - if (cancellationSignal != null) { - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - - // Close session. - cancellationSignal.cancel(); - - // Wait for the on closed callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onClosedCalled).isTrue(); - } - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"}) - public void testFiraRangingSessionWithProvisionedSTS() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - CancellationSignal cancellationSignal = null; - CountDownLatch countDownLatch = new CountDownLatch(1); - CountDownLatch resultCountDownLatch = new CountDownLatch(1); - RangingSessionCallback rangingSessionCallback = - new RangingSessionCallback(countDownLatch, resultCountDownLatch); - PersistableBundle bundle = mUwbManager.getSpecificationInfo(); - if (bundle.keySet().contains(FiraParams.PROTOCOL_NAME)) { - bundle = requireNonNull(bundle.getPersistableBundle(FiraParams.PROTOCOL_NAME)); - } - FiraSpecificationParams params = - FiraSpecificationParams.fromBundle(bundle); - EnumSet<FiraParams.StsCapabilityFlag> stsCapabilities = EnumSet.of( - FiraParams.StsCapabilityFlag.HAS_STATIC_STS_SUPPORT, - FiraParams.StsCapabilityFlag.HAS_PROVISIONED_STS_SUPPORT); - assumeTrue(params.getStsCapabilities() == stsCapabilities); - - FiraOpenSessionParams firaOpenSessionParams = new FiraOpenSessionParams.Builder() - .setProtocolVersion(new FiraProtocolVersion(1, 1)) - .setSessionId(1) - .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED) - .setSessionKey(new byte[]{ - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 - }) - .setSubsessionKey(new byte[]{ - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, - 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 - }) - .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER) - .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR) - .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST) - .setDeviceAddress(UwbAddress.fromBytes(new byte[] {0x5, 6})) - .setDestAddressList(List.of(UwbAddress.fromBytes(new byte[] {0x5, 6}))) - .build(); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - cancellationSignal = mUwbManager.openRangingSession( - firaOpenSessionParams.toBundle(), - Executors.newSingleThreadExecutor(), - rangingSessionCallback, - mDefaultChipId); - // Wait for the on opened callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onOpenedCalled).isTrue(); - assertThat(rangingSessionCallback.onOpenFailedCalled).isFalse(); - assertThat(rangingSessionCallback.rangingSession).isNotNull(); - - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - rangingSessionCallback.rangingSession.start(new PersistableBundle()); - // Wait for the on started callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onStartedCalled).isTrue(); - assertThat(rangingSessionCallback.onStartFailedCalled).isFalse(); - - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - UwbAddress uwbAddress = UwbAddress.fromBytes(new byte[] {0x5, 5}); - rangingSessionCallback.rangingSession.addControlee( - new FiraControleeParams.Builder() - .setAddressList(new UwbAddress[] {uwbAddress}) - .setSubSessionIdList(new int[] {1}) - .build().toBundle() - ); - // Wait for the on reconfigured callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onReconfiguredCalled).isTrue(); - assertThat(rangingSessionCallback.onReconfiguredFailedCalled).isFalse(); - - // Wait for the on ranging report callback. - assertThat(resultCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.rangingReport).isNotNull(); - - // Check the UWB state. - assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_ACTIVE); - - // Stop ongoing session. - rangingSessionCallback.rangingSession.stop(); - } finally { - if (cancellationSignal != null) { - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - - // Close session. - cancellationSignal.cancel(); - - // Wait for the on closed callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onClosedCalled).isTrue(); - } - uiAutomation.dropShellPermissionIdentity(); - } - } - - private class AdapterStateCallback implements UwbManager.AdapterStateCallback { - private final CountDownLatch mCountDownLatch; - private final @State Integer mWaitForState; - public int state; - public int reason; - - AdapterStateCallback(@NonNull CountDownLatch countDownLatch, - @Nullable @State Integer waitForState) { - mCountDownLatch = countDownLatch; - mWaitForState = waitForState; - } - - public void onStateChanged(@State int state, @StateChangedReason int reason) { - this.state = state; - this.reason = reason; - if (mWaitForState != null) { - if (mWaitForState == state) { - mCountDownLatch.countDown(); - } - } else { - mCountDownLatch.countDown(); - } - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-4"}) - public void testUwbStateToggle() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - try { - // Needs UWB_PRIVILEGED permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - assertThat(mUwbManager.isUwbEnabled()).isTrue(); - assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_INACTIVE); - // Toggle the state - setUwbEnabledAndWaitForCompletion(false); - assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_DISABLED); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testSendVendorUciMessage() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CountDownLatch rspCountDownLatch = new CountDownLatch(1); - CountDownLatch ntfCountDownLatch = new CountDownLatch(1); - UwbVendorUciCallback cb = - new UwbVendorUciCallback(rspCountDownLatch, ntfCountDownLatch); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.registerUwbVendorUciCallback( - Executors.newSingleThreadExecutor(), cb); - - // Send random payload with a vendor gid. - byte[] payload = new byte[100]; - new Random().nextBytes(payload); - int gid = 9; - int oid = 1; - mUwbManager.sendVendorUciMessage(gid, oid, payload); - - // Wait for response. - assertThat(rspCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(cb.gid).isEqualTo(gid); - assertThat(cb.oid).isEqualTo(oid); - assertThat(cb.payload).isNotEmpty(); - } catch (SecurityException e) { - /* pass */ - } finally { - mUwbManager.unregisterUwbVendorUciCallback(cb); - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testSendVendorUciMessageWithFragmentedPackets() throws Exception { - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CountDownLatch rspCountDownLatch = new CountDownLatch(1); - CountDownLatch ntfCountDownLatch = new CountDownLatch(1); - UwbVendorUciCallback cb = - new UwbVendorUciCallback(rspCountDownLatch, ntfCountDownLatch); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.registerUwbVendorUciCallback( - Executors.newSingleThreadExecutor(), cb); - - // Send random payload > 255 bytes with a vendor gid. - byte[] payload = new byte[400]; - new Random().nextBytes(payload); - int gid = 9; - int oid = 1; - mUwbManager.sendVendorUciMessage(gid, oid, payload); - - // Wait for response. - assertThat(rspCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(cb.gid).isEqualTo(gid); - assertThat(cb.oid).isEqualTo(oid); - assertThat(cb.payload).isNotEmpty(); - } catch (SecurityException e) { - /* pass */ - } finally { - mUwbManager.unregisterUwbVendorUciCallback(cb); - uiAutomation.dropShellPermissionIdentity(); - } - } - - private class UwbOemExtensionCallback implements UwbManager.UwbOemExtensionCallback { - public PersistableBundle mSessionChangeNtf; - public PersistableBundle mDeviceStatusNtf; - public PersistableBundle mSessionConfig; - public RangingReport mRangingReport; - public boolean onSessionConfigCompleteCalled = false; - public boolean onRangingReportReceivedCalled = false; - public boolean onSessionChangedCalled = false; - public boolean onDeviceStatusNtfCalled = false; - - @Override - public void onSessionStatusNotificationReceived( - @NonNull PersistableBundle sessionStatusBundle) { - mSessionChangeNtf = sessionStatusBundle; - onSessionChangedCalled = true; - } - - @Override - public void onDeviceStatusNotificationReceived(PersistableBundle deviceStatusBundle) { - mDeviceStatusNtf = deviceStatusBundle; - onDeviceStatusNtfCalled = true; - } - - @NonNull - @Override - public int onSessionConfigurationComplete(@NonNull PersistableBundle openSessionBundle) { - mSessionConfig = openSessionBundle; - onSessionConfigCompleteCalled = true; - return 0; - } - - @NonNull - @Override - public RangingReport onRangingReportReceived( - @NonNull RangingReport rangingReport) { - onRangingReportReceivedCalled = true; - mRangingReport = rangingReport; - return mRangingReport; - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"}) - public void testOemCallbackExtension() throws Exception { - Assume.assumeTrue(SdkLevel.isAtLeastU()); - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - CancellationSignal cancellationSignal = null; - CountDownLatch countDownLatch = new CountDownLatch(1); - CountDownLatch resultCountDownLatch = new CountDownLatch(1); - UwbOemExtensionCallback uwbOemExtensionCallback = new UwbOemExtensionCallback(); - - int sessionId = 1; - RangingSessionCallback rangingSessionCallback = - new RangingSessionCallback(countDownLatch, resultCountDownLatch); - FiraOpenSessionParams firaOpenSessionParams = new FiraOpenSessionParams.Builder() - .setProtocolVersion(new FiraProtocolVersion(1, 1)) - .setSessionId(sessionId) - .setStsConfig(FiraParams.STS_CONFIG_STATIC) - .setVendorId(new byte[]{0x5, 0x6}) - .setStaticStsIV(new byte[]{0x5, 0x6, 0x9, 0xa, 0x4, 0x6}) - .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER) - .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR) - .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST) - .setDeviceAddress(UwbAddress.fromBytes(new byte[] {0x5, 6})) - .setDestAddressList(List.of(UwbAddress.fromBytes(new byte[] {0x5, 6}))) - .build(); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.registerUwbOemExtensionCallback( - Executors.newSingleThreadExecutor(), uwbOemExtensionCallback); - // Try to start a ranging session with invalid params, should fail. - cancellationSignal = mUwbManager.openRangingSession( - firaOpenSessionParams.toBundle(), - Executors.newSingleThreadExecutor(), - rangingSessionCallback, - mDefaultChipId); - // Wait for the on opened callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(uwbOemExtensionCallback.onSessionConfigCompleteCalled).isTrue(); - assertThat(uwbOemExtensionCallback.mSessionConfig).isNotNull(); - - FiraOpenSessionParams openSessionParamsBundle = FiraOpenSessionParams - .fromBundle(uwbOemExtensionCallback.mSessionConfig); - assertEquals(openSessionParamsBundle.getSessionId(), sessionId); - assertEquals(openSessionParamsBundle.getStsConfig(), FiraParams.STS_CONFIG_STATIC); - assertEquals(openSessionParamsBundle.getDeviceType(), - FiraParams.RANGING_DEVICE_TYPE_CONTROLLER); - - assertThat(uwbOemExtensionCallback.onSessionChangedCalled).isTrue(); - assertThat(uwbOemExtensionCallback.mSessionChangeNtf).isNotNull(); - - SessionStatus sessionStatusBundle = SessionStatus - .fromBundle(uwbOemExtensionCallback.mSessionChangeNtf); - assertEquals(sessionStatusBundle.getSessionId(), sessionId); - assertEquals(sessionStatusBundle.getState(), UWB_SESSION_STATE_IDLE); - assertEquals(sessionStatusBundle.getReasonCode(), - REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS); - - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - rangingSessionCallback.rangingSession.start(new PersistableBundle()); - // Wait for the on started callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(uwbOemExtensionCallback.onSessionChangedCalled).isTrue(); - assertThat(uwbOemExtensionCallback.mSessionChangeNtf).isNotNull(); - assertThat(uwbOemExtensionCallback.onDeviceStatusNtfCalled).isTrue(); - assertThat(uwbOemExtensionCallback.mDeviceStatusNtf).isNotNull(); - - DeviceStatus deviceStatusBundle = DeviceStatus - .fromBundle(uwbOemExtensionCallback.mDeviceStatusNtf); - assertEquals(deviceStatusBundle.getDeviceState(), DEVICE_STATE_ACTIVE); - - // Wait for the on ranging report callback. - assertThat(resultCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.rangingReport).isNotNull(); - assertThat(uwbOemExtensionCallback.onRangingReportReceivedCalled).isTrue(); - assertThat(uwbOemExtensionCallback.mRangingReport).isNotNull(); - PersistableBundle reportMetadataBundle = uwbOemExtensionCallback - .mRangingReport.getRangingReportMetadata(); - RangingReportMetadata reportMetadata = RangingReportMetadata - .fromBundle(reportMetadataBundle); - assertEquals(reportMetadata.getSessionId(), sessionId); - assertThat(reportMetadata.getRawNtfData()).isNotEmpty(); - - // Check the UWB state. - assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_ACTIVE); - - // Stop ongoing session. - rangingSessionCallback.rangingSession.stop(); - } finally { - if (cancellationSignal != null) { - countDownLatch = new CountDownLatch(1); - rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch); - - // Close session. - cancellationSignal.cancel(); - - // Wait for the on closed callback. - assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue(); - assertThat(rangingSessionCallback.onClosedCalled).isTrue(); - } - try { - mUwbManager.unregisterUwbOemExtensionCallback(uwbOemExtensionCallback); - } catch (SecurityException e) { - /* pass */ - fail(); - } - uiAutomation.dropShellPermissionIdentity(); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testRegisterUwbOemExtensionCallbackWithoutUwbPrivileged() { - Assume.assumeTrue(SdkLevel.isAtLeastU()); - UwbManager.UwbOemExtensionCallback cb = new UwbOemExtensionCallback(); - try { - mUwbManager.registerUwbOemExtensionCallback( - Executors.newSingleThreadExecutor(), cb); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - } - - @Test - @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"}) - public void testUnregisterUwbOemExtensionCallbackWithoutUwbPrivileged() { - Assume.assumeTrue(SdkLevel.isAtLeastU()); - UiAutomation uiAutomation = getInstrumentation().getUiAutomation(); - UwbManager.UwbOemExtensionCallback cb = new UwbOemExtensionCallback(); - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.registerUwbOemExtensionCallback( - Executors.newSingleThreadExecutor(), cb); - } catch (SecurityException e) { - /* fail */ - fail(); - } finally { - uiAutomation.dropShellPermissionIdentity(); - } - try { - mUwbManager.unregisterUwbOemExtensionCallback(cb); - // should fail if the call was successful without UWB_PRIVILEGED permission. - fail(); - } catch (SecurityException e) { - /* pass */ - Log.i(TAG, "Failed with expected security exception: " + e); - } - try { - // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell. - uiAutomation.adoptShellPermissionIdentity(); - mUwbManager.unregisterUwbOemExtensionCallback(cb); - } catch (SecurityException e) { - /* pass */ - fail(); - } - } -} diff --git a/tests/uwb/src/android/uwb/cts/UwbTestUtils.java b/tests/uwb/src/android/uwb/cts/UwbTestUtils.java deleted file mode 100644 index a7689deec46..00000000000 --- a/tests/uwb/src/android/uwb/cts/UwbTestUtils.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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. - */ - -package android.uwb.cts; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.PersistableBundle; -import android.os.SystemClock; -import android.uwb.AngleMeasurement; -import android.uwb.AngleOfArrivalMeasurement; -import android.uwb.DistanceMeasurement; -import android.uwb.RangingMeasurement; -import android.uwb.RangingReport; -import android.uwb.UwbAddress; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; - -public class UwbTestUtils { - private UwbTestUtils() {} - - public static boolean isUwbSupported(Context context) { - PackageManager packageManager = context.getPackageManager(); - return packageManager.hasSystemFeature(PackageManager.FEATURE_UWB); - } - - public static AngleMeasurement getAngleMeasurement() { - return new AngleMeasurement( - getDoubleInRange(-Math.PI, Math.PI), - getDoubleInRange(0, Math.PI), - getDoubleInRange(0, 1)); - } - - public static AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() { - return new AngleOfArrivalMeasurement.Builder(getAngleMeasurement()) - .setAltitude(getAngleMeasurement()) - .build(); - } - - public static DistanceMeasurement getDistanceMeasurement() { - return new DistanceMeasurement.Builder() - .setMeters(getDoubleInRange(0, 100)) - .setErrorMeters(getDoubleInRange(0, 10)) - .setConfidenceLevel(getDoubleInRange(0, 1)) - .build(); - } - - public static RangingMeasurement getRangingMeasurement() { - return getRangingMeasurement(getUwbAddress(false)); - } - - public static PersistableBundle getTestRangingMetadata() { - PersistableBundle bundle = new PersistableBundle(); - bundle.putInt("TEST_KEY", 1); - return bundle; - } - - public static RangingMeasurement getRangingMeasurement(UwbAddress address) { - return new RangingMeasurement.Builder() - .setDistanceMeasurement(getDistanceMeasurement()) - .setAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement()) - .setDestinationAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement()) - .setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()) - .setRemoteDeviceAddress(address != null ? address : getUwbAddress(false)) - .setStatus(RangingMeasurement.RANGING_STATUS_SUCCESS) - .setLineOfSight(RangingMeasurement.NLOS) - .setMeasurementFocus(RangingMeasurement.MEASUREMENT_FOCUS_RANGE) - .setRssiDbm(-85) - .setRangingMeasurementMetadata(getTestRangingMetadata()) - .build(); - } - - public static List<RangingMeasurement> getRangingMeasurements(int num) { - List<RangingMeasurement> result = new ArrayList<>(); - for (int i = 0; i < num; i++) { - result.add(getRangingMeasurement()); - } - return result; - } - - public static RangingReport getRangingReports(int numMeasurements) { - RangingReport.Builder builder = new RangingReport.Builder(); - for (int i = 0; i < numMeasurements; i++) { - builder.addMeasurement(getRangingMeasurement()); - } - return builder.build(); - } - - private static double getDoubleInRange(double min, double max) { - return min + (max - min) * Math.random(); - } - - public static UwbAddress getUwbAddress(boolean isShortAddress) { - byte[] addressBytes = new byte[isShortAddress ? UwbAddress.SHORT_ADDRESS_BYTE_LENGTH : - UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH]; - for (int i = 0; i < addressBytes.length; i++) { - addressBytes[i] = (byte) getDoubleInRange(1, 255); - } - return UwbAddress.fromBytes(addressBytes); - } - - public static Executor getExecutor() { - return new Executor() { - @Override - public void execute(Runnable command) { - command.run(); - } - }; - } -} |