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()
+    }
+}