Merge "Add test for tapjacking permission review screen" into qt-dev
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index dfda8b7..395efa9 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -31,6 +31,10 @@
<option name="teardown-command"
value="pm uninstall --user 0 android.security.cts" />
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="CtsUsePermissionApp22_2.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp22_2.apk" />
+ <option name="push" value="CtsHelperAppOverlay.apk->/data/local/tmp/cts/permission3/CtsHelperAppOverlay.apk" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.security.cts" />
<option name="runtime-hint" value="1h40m18s" />
diff --git a/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.java b/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.java
new file mode 100644
index 0000000..43cd1a3
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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 android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.Settings;
+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 androidx.test.InstrumentationRegistry;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.lang.Exception;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Tests permission review screen can't be tapjacked
+ */
+public class PermissionReviewTapjackingTest {
+
+ private static String APK_DIRECTORY = "/data/local/tmp/cts/permission3";
+ private static long IDLE_TIMEOUT_MILLIS = 1000;
+ private static long TIMEOUT_MILLIS = 20000;
+
+ private static String APP_APK_PATH_22 = APK_DIRECTORY + "/CtsUsePermissionApp22_2.apk";
+ private static String APP_PACKAGE_NAME = "android.permission3.cts.usepermission";
+
+ private static String HELPER_APP_OVERLAY = APK_DIRECTORY + "/CtsHelperAppOverlay.apk";
+ private static String HELPER_PACKAGE_NAME = "android.permission3.cts.helper.overlay";
+
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ Context context = instrumentation.getContext();
+ UiAutomation uiAutomation = instrumentation.getUiAutomation();
+ UiDevice uiDevice = UiDevice.getInstance(instrumentation);
+ PackageManager packageManager = context.getPackageManager();
+
+ private long screenTimeoutBeforeTest = 0;
+
+ private void waitForIdle() throws TimeoutException {
+ uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS);
+ }
+
+ private UiObject2 waitFindObject(BySelector selector) throws TimeoutException {
+ waitForIdle();
+ UiObject2 view = uiDevice.wait(Until.findObject(selector), TIMEOUT_MILLIS);
+ if (view == null) {
+ throw new RuntimeException("View not found after waiting for " + TIMEOUT_MILLIS +
+ "ms: " + selector);
+ }
+ return view;
+ }
+
+ private void installPackage(String apkPath) {
+ String output = runShellCommand("pm install " + apkPath).trim();
+ Assert.assertEquals("Success", output);
+ }
+
+ private void pressHome() throws TimeoutException {
+ uiDevice.pressHome();
+ waitForIdle();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ runWithShellPermissionIdentity(() -> {
+ screenTimeoutBeforeTest = Settings.System.getLong(
+ context.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT
+ );
+ Settings.System.putLong(
+ context.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
+ );
+ });
+
+ uiDevice.wakeUp();
+ runShellCommand(instrumentation, "wm dismiss-keyguard");
+
+ UiObject2 close = uiDevice.findObject(By.text("Close"));
+ if (close != null) {
+ close.click();
+ }
+ }
+
+ @Before
+ public void installApp22AndApprovePermissionReview() {
+ Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled());
+
+ installPackage(APP_APK_PATH_22);
+ installPackage(HELPER_APP_OVERLAY);
+
+ runShellCommand(
+ "appops set " + HELPER_PACKAGE_NAME + " android:system_alert_window allow");
+ }
+
+ @After
+ public void tearDown() throws TimeoutException {
+ runWithShellPermissionIdentity(() -> Settings.System.putLong(
+ context.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT,
+ screenTimeoutBeforeTest
+ ));
+
+ pressHome();
+ }
+
+ @After
+ public void uninstallPackages() {
+ runShellCommand("pm uninstall " + APP_PACKAGE_NAME);
+ runShellCommand("pm uninstall " + HELPER_PACKAGE_NAME);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 176094367)
+ public void testOverlaysAreHidden() throws TimeoutException {
+ context.startActivity(new Intent()
+ .setComponent(new ComponentName(HELPER_PACKAGE_NAME,
+ HELPER_PACKAGE_NAME + ".OverlayActivity"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ findOverlay();
+
+ context.startActivity(new Intent()
+ .setComponent(new ComponentName(APP_PACKAGE_NAME,
+ APP_PACKAGE_NAME + ".FinishOnCreateActivity"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+
+ waitFindObject(By.res("com.android.permissioncontroller:id/permissions_message"));
+
+ try {
+ findOverlay();
+ Assert.fail("Overlay was displayed");
+ } catch (Exception e) {
+ // expected
+ }
+
+ System.out.println("pressHome!");
+ pressHome();
+ findOverlay();
+ }
+
+ private void findOverlay() throws TimeoutException {
+ waitFindObject(By.text("Find me!"));
+ }
+}
diff --git a/tests/tests/security/test-apps/HelperAppOverlay/Android.bp b/tests/tests/security/test-apps/HelperAppOverlay/Android.bp
new file mode 100644
index 0000000..db0eab8
--- /dev/null
+++ b/tests/tests/security/test-apps/HelperAppOverlay/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsHelperAppOverlay",
+ min_sdk_version: "30",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/tests/security/test-apps/HelperAppOverlay/AndroidManifest.xml b/tests/tests/security/test-apps/HelperAppOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..04d5a4b
--- /dev/null
+++ b/tests/tests/security/test-apps/HelperAppOverlay/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission3.cts.helper.overlay">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application>
+ <activity android:name=".OverlayActivity" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/tests/security/test-apps/HelperAppOverlay/src/android/permission3/cts/helper/overlay/OverlayActivity.kt b/tests/tests/security/test-apps/HelperAppOverlay/src/android/permission3/cts/helper/overlay/OverlayActivity.kt
new file mode 100644
index 0000000..2c1497f
--- /dev/null
+++ b/tests/tests/security/test-apps/HelperAppOverlay/src/android/permission3/cts/helper/overlay/OverlayActivity.kt
@@ -0,0 +1,26 @@
+package android.permission3.cts.helper.overlay
+
+import android.app.Activity
+import android.os.Bundle
+import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.WindowManager
+import android.widget.LinearLayout
+import android.widget.TextView
+
+class OverlayActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val mainLayout = LinearLayout(this)
+ mainLayout.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ val textView = TextView(this)
+
+ textView.text = "Find me!"
+ mainLayout.addView(textView)
+
+ val windowParams = WindowManager.LayoutParams()
+ windowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
+ windowManager.addView(mainLayout, windowParams)
+ }
+}
diff --git a/tests/tests/security/test-apps/UsePermissionApp22_2/Android.bp b/tests/tests/security/test-apps/UsePermissionApp22_2/Android.bp
new file mode 100644
index 0000000..f401bcc
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionApp22_2/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp22_2",
+ srcs: [
+ ":CtsUsePermissionAppSrc_2",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "22",
+}
diff --git a/tests/tests/security/test-apps/UsePermissionApp22_2/AndroidManifest.xml b/tests/tests/security/test-apps/UsePermissionApp22_2/AndroidManifest.xml
new file mode 100644
index 0000000..f1ff90d
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionApp22_2/AndroidManifest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2015 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.permission3.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+ <!-- Make sure permission code can handle invalid permissions -->
+ <uses-permission android:name="android.permission3.cts.usepermission.INVALID_PERMISSION_NAME" />
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <!-- Contacts -->
+ <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+
+ <!-- Calendar -->
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+
+ <!-- SMS -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+ <uses-permission android:name="android.permission.READ_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
+ <uses-permission android:name="android.permission.RECEIVE_MMS" />
+ <uses-permission android:name="android.permission.READ_CELL_BROADCASTS" />
+
+ <!-- Storage -->
+ <!-- Special case: WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <!-- Location -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.CALL_PHONE" />
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+ <uses-permission android:name="android.permission.USE_SIP" />
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <!-- Camera -->
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <!-- Body Sensors -->
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/tests/security/test-apps/UsePermissionAppLatest/Android.bp b/tests/tests/security/test-apps/UsePermissionAppLatest/Android.bp
new file mode 100644
index 0000000..d1a6545
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionAppLatest/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2017 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.
+//
+
+filegroup {
+ name: "CtsUsePermissionAppSrc_2",
+ srcs: [
+ "src/**/*.kt",
+ ],
+}
+
diff --git a/tests/tests/security/test-apps/UsePermissionAppLatest/AndroidManifest.xml b/tests/tests/security/test-apps/UsePermissionAppLatest/AndroidManifest.xml
new file mode 100644
index 0000000..531e6dd
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionAppLatest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2017 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.permission3.cts.usepermission">
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/CheckCalendarAccessActivity.kt b/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/CheckCalendarAccessActivity.kt
new file mode 100644
index 0000000..eeb020e
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/CheckCalendarAccessActivity.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission3.cts.usepermission
+
+import android.app.Activity
+import android.content.ContentValues
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.provider.CalendarContract
+
+/**
+ * An activity that can check calendar access.
+ */
+class CheckCalendarAccessActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val supportsRuntimePermissions = applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M
+ val hasAccess: Boolean
+ val uri = try {
+ contentResolver.insert(
+ CalendarContract.Calendars.CONTENT_URI, ContentValues().apply {
+ put(CalendarContract.Calendars.NAME, "cts" + System.nanoTime())
+ put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "cts")
+ put(CalendarContract.Calendars.CALENDAR_COLOR, 0xffff0000)
+ }
+ )!!
+ } catch (e: SecurityException) {
+ null
+ }
+ hasAccess = if (uri != null) {
+ val count = contentResolver.query(uri, null, null, null).use { it!!.count }
+ if (supportsRuntimePermissions) {
+ assert(count == 1)
+ true
+ } else {
+ // Without access we're handed back a "fake" Uri that doesn't contain
+ // any of the data we tried persisting
+ assert(count == 0 || count == 1)
+ count == 1
+ }
+ } else {
+ assert(supportsRuntimePermissions)
+ try {
+ contentResolver.query(CalendarContract.Calendars.CONTENT_URI, null, null, null)
+ .use {}
+ error("Expected SecurityException")
+ } catch (e: SecurityException) {}
+ false
+ }
+ setResult(RESULT_OK, Intent().apply { putExtra("$packageName.HAS_ACCESS", hasAccess) })
+ finish()
+ }
+}
diff --git a/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/FinishOnCreateActivity.kt b/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/FinishOnCreateActivity.kt
new file mode 100644
index 0000000..75c873e
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/FinishOnCreateActivity.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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.permission3.cts.usepermission
+
+import android.app.Activity
+import android.os.Bundle
+
+class FinishOnCreateActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setResult(RESULT_OK)
+ finish()
+ }
+}
diff --git a/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/RequestPermissionsActivity.kt b/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/RequestPermissionsActivity.kt
new file mode 100644
index 0000000..1538acf
--- /dev/null
+++ b/tests/tests/security/test-apps/UsePermissionAppLatest/src/android/permission3/cts/usepermission/RequestPermissionsActivity.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission3.cts.usepermission
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+
+class RequestPermissionsActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState == null) {
+ val permissions = intent.getStringArrayExtra("$packageName.PERMISSIONS")!!
+ requestPermissions(permissions, 1)
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<out String>,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ setResult(RESULT_OK, Intent().apply {
+ putExtra("$packageName.PERMISSIONS", permissions)
+ putExtra("$packageName.GRANT_RESULTS", grantResults)
+ })
+ finish()
+ }
+}