Fix PermissionsHostTest and make activity result capturing more robust

The Activity instance that gets onActivityResult/onPermissionResult in not
always the same as the one that called startActivityForResult/requestPermission.

This was both a cause of some flakes and a recent breakage.

Bug: 128423549
Test: atest android.appsecurity.cts.PermissionsHostTest
Change-Id: Ic85f646020ee61023667d29875e065493e638bc2
diff --git a/.gitignore b/.gitignore
index 33bfd97..ff66172 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,6 @@
 *.iml
 *.class
 *.sw*
+
+# Jars added by Idea's "Konfigure kotlin in project" action
+**/lib/kotlin-*.jar
\ No newline at end of file
diff --git a/common/device-side/util-axt/Android.bp b/common/device-side/util-axt/Android.bp
index fe2b1b7..6f430d8 100644
--- a/common/device-side/util-axt/Android.bp
+++ b/common/device-side/util-axt/Android.bp
@@ -20,6 +20,7 @@
 
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
         "src/**/*.aidl",
     ],
 
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/InstallConfirmDialogStarter.kt b/common/device-side/util-axt/src/com/android/compatibility/common/util/FutureResultActivity.kt
similarity index 62%
rename from tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/InstallConfirmDialogStarter.kt
rename to common/device-side/util-axt/src/com/android/compatibility/common/util/FutureResultActivity.kt
index 4cc4371..49397a5 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/InstallConfirmDialogStarter.kt
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/FutureResultActivity.kt
@@ -14,29 +14,35 @@
  * limitations under the License.
  */
 
-package android.packageinstaller.install.cts
+package com.android.compatibility.common.util
 
 import android.app.Activity
 import android.content.Intent
-import com.android.compatibility.common.util.PollingCheck
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.ConcurrentHashMap
 import java.util.concurrent.atomic.AtomicInteger
 
-/** requestCode -> Future<resultCode> */
-private val requests = ConcurrentHashMap<Int, CompletableFuture<Int>>()
-private val nextRequestCode = AtomicInteger(0)
+/**
+ * An [Activity] that exposes a special [startActivityForResult],
+ * returning future resultCode as a [CompletableFuture]
+ */
+class FutureResultActivity : Activity() {
 
-internal fun doAndAwaitInstallConfirmDialog(act: () -> Unit): CompletableFuture<Int> {
-    val requestCode = nextRequestCode.get()
-    act()
-    PollingCheck.waitFor(TIMEOUT) {
-        nextRequestCode.get() >= requestCode + 1
+    companion object {
+
+        /** requestCode -> Future<resultCode> */
+        private val requests = ConcurrentHashMap<Int, CompletableFuture<Int>>()
+        private val nextRequestCode = AtomicInteger(0)
+
+        fun doAndAwaitStart(act: () -> Unit): CompletableFuture<Int> {
+            val requestCode = nextRequestCode.get()
+            act()
+            PollingCheck.waitFor(60_000) {
+                nextRequestCode.get() >= requestCode + 1
+            }
+            return requests[requestCode]!!
+        }
     }
-    return requests[requestCode]!!
-}
-
-class InstallConfirmDialogStarter : Activity() {
 
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         requests[requestCode]!!.complete(resultCode)
diff --git a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml
index 7b254dc..30d73f5 100644
--- a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml
@@ -19,7 +19,7 @@
         package="com.android.cts.reviewpermissionhelper">
 
     <application>
-        <activity android:name=".ActivityStarter" />
+        <activity android:name="com.android.compatibility.common.util.FutureResultActivity" />
         <uses-library android:name="android.test.runner" />
     </application>
 
diff --git a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ActivityStarter.kt b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ActivityStarter.kt
deleted file mode 100644
index 90dbca9..0000000
--- a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ActivityStarter.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 com.android.cts.reviewpermissionhelper
-
-import android.app.Activity
-import android.content.Intent
-import android.os.Bundle
-import java.util.concurrent.LinkedBlockingQueue
-
-val installDialogResults = LinkedBlockingQueue<Int>()
-
-class ActivityStarter : Activity() {
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-
-        savedInstanceState ?: installDialogResults.clear()
-    }
-
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
-        installDialogResults.offer(resultCode)
-    }
-}
diff --git a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.kt b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.kt
index 15fdff3..b07a4bb 100644
--- a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.kt
+++ b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.kt
@@ -32,11 +32,13 @@
 import android.support.test.uiautomator.By
 import android.support.test.uiautomator.UiDevice
 import android.support.test.uiautomator.Until
+import com.android.compatibility.common.util.FutureResultActivity
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNull
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.util.concurrent.CompletableFuture
 import java.util.concurrent.LinkedBlockingQueue
 import java.util.concurrent.TimeUnit
 
@@ -47,16 +49,22 @@
 @RunWith(AndroidJUnit4::class)
 class ReviewPermissionsTest {
     @get:Rule
-    val activityStarter = ActivityTestRule(ActivityStarter::class.java)
+    val activityStarter = ActivityTestRule(FutureResultActivity::class.java)
 
     val instrumentation = InstrumentationRegistry.getInstrumentation()
     val uiDevice = UiDevice.getInstance(instrumentation)
 
-    fun startActivityInReviewedAp() {
+    fun startActivityInReviewedAp(): CompletableFuture<Int> {
         val startAutoClosingActivity = Intent()
         startAutoClosingActivity.component = ComponentName(USE_PERMISSION_PKG,
                 USE_PERMISSION_PKG + ".AutoClosingActivity")
-        activityStarter.activity.startActivityForResult(startAutoClosingActivity, 42)
+        return activityStarter.activity.startActivityForResult(startAutoClosingActivity)
+    }
+
+    private inline fun startActivityInReviewedAp(expectedResult: Int, runAfterStart: () -> Unit) {
+        val activityResult = startActivityInReviewedAp()
+        runAfterStart()
+        assertEquals(expectedResult, activityResult.get(UI_TIMEOUT, TimeUnit.MILLISECONDS))
     }
 
     fun clickContinue() {
@@ -66,24 +74,23 @@
 
     @Test
     fun approveReviewPermissions() {
-        startActivityInReviewedAp()
-        clickContinue()
-        assertEquals(RESULT_OK, installDialogResults.poll(UI_TIMEOUT, TimeUnit.MILLISECONDS))
+        startActivityInReviewedAp(expectedResult = RESULT_OK) {
+            clickContinue()
+        }
     }
 
     @Test
     fun cancelReviewPermissions() {
-        startActivityInReviewedAp()
-
-        uiDevice.wait(Until.findObject(
-                By.res("com.android.permissioncontroller:id/cancel_button")), UI_TIMEOUT).click()
-        assertEquals(RESULT_CANCELED, installDialogResults.poll(UI_TIMEOUT, TimeUnit.MILLISECONDS))
+        startActivityInReviewedAp(expectedResult = RESULT_CANCELED) {
+            uiDevice.wait(Until.findObject(
+                    By.res("com.android.permissioncontroller:id/cancel_button")), UI_TIMEOUT)
+                    .click()
+        }
     }
 
     @Test
     fun assertNoReviewPermissionsNeeded() {
-        startActivityInReviewedAp()
-        assertEquals(RESULT_OK, installDialogResults.poll(UI_TIMEOUT, TimeUnit.MILLISECONDS))
+        startActivityInReviewedAp(expectedResult = RESULT_OK) {}
     }
 
     @Test
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java
index 20be2cc..a1bd122 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java
@@ -36,7 +36,6 @@
  * Runtime permission behavior tests for apps targeting API 22
  */
 public class UsePermissionTest22 extends BasePermissionsTest {
-    private static final int REQUEST_CODE_PERMISSIONS = 42;
 
     private final Context mContext = getInstrumentation().getContext();
 
@@ -137,11 +136,9 @@
     public void testNoRuntimePrompt() throws Exception {
         // Request the permission and do nothing
         BasePermissionActivity.Result result = requestPermissions(
-                new String[] {Manifest.permission.SEND_SMS}, REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class, null);
+                new String[]{Manifest.permission.SEND_SMS}, null);
 
         // Expect the permission is not granted
-        assertEquals(REQUEST_CODE_PERMISSIONS, result.requestCode);
         assertTrue(Arrays.equals(result.permissions, new String[0]));
         assertTrue(Arrays.equals(result.grantResults, new int[0]));
     }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java
index cacfa80..48dafef 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java
@@ -20,23 +20,33 @@
 import android.os.Bundle;
 import android.view.WindowManager;
 
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class BasePermissionActivity extends Activity {
     private static final long OPERATION_TIMEOUT_MILLIS = 5000;
 
-    private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+    /**
+     * Static to ensure correct behavior if {@link Activity} instance was recreated before
+     * result delivery.
+     *
+     * requestCode -> Future<Result>
+     */
+    private static Map<Integer, CompletableFuture<Result>> sPendingResults =
+            new ConcurrentHashMap<>();
+    private static AtomicInteger sNextRequestCode = new AtomicInteger(0);
+
     private final CountDownLatch mOnCreateSync = new CountDownLatch(1);
 
     public static class Result {
-        public final int requestCode;
         public final String[] permissions;
         public final int[] grantResults;
 
-        public Result(int requestCode, String[] permissions, int[] grantResults) {
-            this.requestCode = requestCode;
+        public Result(String[] permissions, int[] grantResults) {
             this.permissions = permissions;
             this.grantResults = grantResults;
         }
@@ -53,14 +63,18 @@
         mOnCreateSync.countDown();
     }
 
+    public CompletableFuture<Result> requestPermissions(String[] permissions) {
+        int requestCode = sNextRequestCode.getAndIncrement();
+        CompletableFuture<Result> future = new CompletableFuture<>();
+        sPendingResults.put(requestCode, future);
+        requestPermissions(permissions, requestCode);
+        return future;
+    }
+
     @Override
     public void onRequestPermissionsResult(int requestCode, String[] permissions,
             int[] grantResults) {
-        try {
-            mResult.offer(new Result(requestCode, permissions, grantResults), 5, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
+        sPendingResults.get(requestCode).complete(new Result(permissions, grantResults));
     }
 
     public void waitForOnCreate() {
@@ -70,12 +84,4 @@
             throw new RuntimeException(e);
         }
     }
-
-    public Result getResult() {
-        try {
-            return mResult.poll(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
index 86c7e2f..6f2efd1 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -21,6 +21,9 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import android.Manifest;
 import android.app.Activity;
 import android.app.Instrumentation;
@@ -63,6 +66,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.regex.Pattern;
 
@@ -87,11 +92,11 @@
     }
 
     protected static void assertPermissionRequestResult(BasePermissionActivity.Result result,
-            int requestCode, String[] permissions, boolean[] granted) {
-        assertEquals(requestCode, result.requestCode);
+            String[] permissions, boolean[] granted) {
         for (int i = 0; i < permissions.length; i++) {
             assertEquals(permissions[i], result.permissions[i]);
-            assertEquals(granted[i] ? PackageManager.PERMISSION_GRANTED
+            assertEquals(granted[i]
+                    ? PackageManager.PERMISSION_GRANTED
                     : PackageManager.PERMISSION_DENIED, result.grantResults[i]);
 
         }
@@ -273,18 +278,19 @@
     }
 
     protected BasePermissionActivity.Result requestPermissions(
-            String[] permissions, int requestCode, Class<?> clazz,
-            ThrowingRunnable postRequestAction)
+            String[] permissions, ThrowingRunnable postRequestAction)
             throws Exception {
         return ExceptionUtils.wrappingExceptions(UiDumpUtils::wrapWithUiDump, () -> {
             // Start an activity
             BasePermissionActivity activity = (BasePermissionActivity) launchActivity(
-                    getInstrumentation().getTargetContext().getPackageName(), clazz, null);
+                    getInstrumentation().getTargetContext().getPackageName(),
+                    BasePermissionActivity.class, null);
 
             activity.waitForOnCreate();
 
             // Request the permissions
-            activity.requestPermissions(permissions, requestCode);
+            CompletableFuture<BasePermissionActivity.Result> futureResult =
+                    activity.requestPermissions(permissions);
 
             // Define a more conservative idle criteria
             getInstrumentation().getUiAutomation().waitForIdle(
@@ -295,7 +301,8 @@
                 postRequestAction.run();
             }
 
-            BasePermissionActivity.Result result = activity.getResult();
+            BasePermissionActivity.Result result =
+                    futureResult.get(GLOBAL_TIMEOUT_MILLIS, MILLISECONDS);
             activity.finish();
             return result;
         });
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index 6161f14..dc7ec3b 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -30,10 +30,6 @@
 
 import androidx.test.InstrumentationRegistry;
 
-import com.android.compatibility.common.util.ExceptionUtils;
-import com.android.compatibility.common.util.SystemUtil;
-import com.android.compatibility.common.util.UiDumpUtils;
-
 import org.junit.Before;
 import org.junit.Test;
 
@@ -44,7 +40,6 @@
  * Runtime permission behavior tests for apps targeting API 23
  */
 public class UsePermissionTest23 extends BasePermissionsTest {
-    private static final int REQUEST_CODE_PERMISSIONS = 42;
 
     private final Context mContext = getInstrumentation().getContext();
 
@@ -108,17 +103,13 @@
         }
 
         // Go through normal grant flow
-        BasePermissionActivity.Result result = requestPermissions(new String[] {
+        BasePermissionActivity.Result result = requestPermissions(new String[]{
                 Manifest.permission.READ_CALENDAR,
-                Manifest.permission.WRITE_CALENDAR},
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    clickAllowButton();
-                    getUiDevice().waitForIdle();
-                });
+                Manifest.permission.WRITE_CALENDAR}, () -> {
+            clickAllowButton();
+            getUiDevice().waitForIdle();
+        });
 
-        assertEquals(REQUEST_CODE_PERMISSIONS, result.requestCode);
         assertEquals(Manifest.permission.READ_CALENDAR, result.permissions[0]);
         assertEquals(Manifest.permission.WRITE_CALENDAR, result.permissions[1]);
         assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[0]);
@@ -146,17 +137,13 @@
         String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
 
         // request only one permission from the 'contacts' permission group
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    clickAllowButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
+            clickAllowButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {true});
+        assertPermissionRequestResult(result, permissions, new boolean[] {true});
 
         // Make sure no undeclared as used permissions are granted
         assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
@@ -176,17 +163,13 @@
         // request only one permission from the 'SMS' permission group at runtime,
         // but two from this group are <uses-permission> in the manifest
         // request only one permission from the 'contacts' permission group
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    clickAllowButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
+            clickAllowButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {true});
+        assertPermissionRequestResult(result, permissions, new boolean[] {true});
 
         // We should now have been granted both of the permissions from this group.
         assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
@@ -202,17 +185,13 @@
         String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
 
         // Request the permission and cancel the request
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    clickDenyButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
+            clickDenyButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(result, permissions, new boolean[] {false});
     }
 
     @Test
@@ -224,25 +203,20 @@
         String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
 
         // Request the permission and allow it
-        BasePermissionActivity.Result firstResult = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class, () -> {
-                    clickAllowButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result firstResult = requestPermissions(permissions, () -> {
+            clickAllowButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is granted
-        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {true});
+        assertPermissionRequestResult(firstResult, permissions, new boolean[] {true});
 
         // Request the permission and do nothing
-        BasePermissionActivity.Result secondResult = requestPermissions(new String[] {
-                Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 1,
-                BasePermissionActivity.class, null);
+        BasePermissionActivity.Result secondResult = requestPermissions(new String[]{
+                Manifest.permission.WRITE_CONTACTS}, null);
 
         // Expect the permission is granted
-        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
-                permissions, new boolean[] {true});
+        assertPermissionRequestResult(secondResult, permissions, new boolean[] {true});
     }
 
     @Test
@@ -254,37 +228,30 @@
         String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
 
         // Request the permission and deny it
-        BasePermissionActivity.Result firstResult = requestPermissions(
-                permissions, REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class, () -> {
-                    clickDenyButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result firstResult = requestPermissions(permissions, () -> {
+            clickDenyButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(firstResult, permissions, new boolean[] {false});
 
         // Request the permission and choose don't ask again
-        BasePermissionActivity.Result secondResult = requestPermissions(new String[] {
-                        Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 1,
-                BasePermissionActivity.class, () -> {
-                    denyWithPrejudice();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result secondResult = requestPermissions(new String[]{
+                Manifest.permission.WRITE_CONTACTS}, () -> {
+            denyWithPrejudice();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(secondResult, permissions, new boolean[] {false});
 
         // Request the permission and do nothing
-        BasePermissionActivity.Result thirdResult = requestPermissions(new String[] {
-                        Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 2,
-                BasePermissionActivity.class, null);
+        BasePermissionActivity.Result thirdResult = requestPermissions(new String[]{
+                Manifest.permission.WRITE_CONTACTS}, null);
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS + 2,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(thirdResult, permissions, new boolean[] {false});
     }
 
     @Test
@@ -322,28 +289,23 @@
         String[] permissions = new String[] {Manifest.permission.READ_CALENDAR};
 
         // Request the permission and deny it
-        BasePermissionActivity.Result firstResult = requestPermissions(
-                permissions, REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class, () -> {
-                    clickDenyButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result firstResult = requestPermissions(permissions, () -> {
+            clickDenyButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(firstResult, permissions, new boolean[] {false});
 
         // Request the permission and choose don't ask again
-        BasePermissionActivity.Result secondResult = requestPermissions(new String[] {
-                        Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS + 1,
-                BasePermissionActivity.class, () -> {
-                    denyWithPrejudice();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result secondResult = requestPermissions(new String[]{
+                Manifest.permission.READ_CALENDAR}, () -> {
+            denyWithPrejudice();
+            getUiDevice().waitForIdle();
+        });
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(secondResult, permissions, new boolean[] {false});
 
         // Clear the denial with prejudice
         grantPermission(Manifest.permission.READ_CALENDAR);
@@ -359,16 +321,15 @@
                 .checkSelfPermission(Manifest.permission.READ_CALENDAR));
 
         // Request the permission and allow it
-        BasePermissionActivity.Result thirdResult = requestPermissions(new String[] {
-                        Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS + 2,
-                BasePermissionActivity.class, () -> {
-                    clickAllowButton();
-                    getUiDevice().waitForIdle();
-                });
+        BasePermissionActivity.Result thirdResult = requestPermissions(new String[]{
+                Manifest.permission.READ_CALENDAR}, () -> {
+            clickAllowButton();
+            getUiDevice().waitForIdle();
+        });
 
         // Make sure the permission is granted
-        assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS + 2,
-                new String[] {Manifest.permission.READ_CALENDAR}, new boolean[] {true});
+        assertPermissionRequestResult(thirdResult, new String[] {Manifest.permission.READ_CALENDAR},
+                new boolean[] {true});
     }
 
     @Test
@@ -380,12 +341,10 @@
         String[] permissions = new String[] {Manifest.permission.BIND_PRINT_SERVICE};
 
         // Request the permission and do nothing
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, null);
+        BasePermissionActivity.Result result = requestPermissions(permissions, null);
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(result, permissions, new boolean[] {false});
     }
 
     @Test
@@ -397,12 +356,10 @@
         String[] permissions = new String[] {"permission.does.not.exist"};
 
         // Request the permission and do nothing
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, null);
+        BasePermissionActivity.Result result = requestPermissions(permissions, null);
 
         // Expect the permission is not granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(result, permissions, new boolean[] {false});
     }
 
     @Test
@@ -419,8 +376,7 @@
         };
 
         // Request the permission and allow it
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, () -> {
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
             try {
                 clickAllowButton();
                 getUiDevice().waitForIdle();
@@ -432,8 +388,7 @@
         });
 
         // Expect the permission are reported as granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {true, true});
+        assertPermissionRequestResult(result, permissions, new boolean[] {true, true});
 
         // The permissions are granted
         assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
@@ -497,20 +452,19 @@
                 .checkSelfPermission(Manifest.permission.READ_CALENDAR));
 
         // Request the permission and allow it
-        BasePermissionActivity.Result thirdResult = requestPermissions(new String[] {
-                        Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class, () -> {
-                    try {
-                        clickAllowButton();
-                        getUiDevice().waitForIdle();
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-                });
+        BasePermissionActivity.Result thirdResult = requestPermissions(new String[]{
+                Manifest.permission.READ_CALENDAR}, () -> {
+            try {
+                clickAllowButton();
+                getUiDevice().waitForIdle();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
 
         // Make sure the permission is granted
-        assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS,
-                new String[] {Manifest.permission.READ_CALENDAR}, new boolean[] {true});
+        assertPermissionRequestResult(thirdResult, new String[] {Manifest.permission.READ_CALENDAR},
+                new boolean[] {true});
     }
 
     @Test
@@ -534,12 +488,9 @@
 
         // Go through normal grant flow
         BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
                 () -> { /* empty */ });
 
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(result, permissions, new boolean[] {false});
     }
 
     @Test
@@ -558,21 +509,19 @@
         };
 
         // Request the permission and allow it
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, () -> {
-                    try {
-                        clickAllowButton();
-                        getUiDevice().waitForIdle();
-                        clickAllowButton();
-                        getUiDevice().waitForIdle();
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-                });
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
+            try {
+                clickAllowButton();
+                getUiDevice().waitForIdle();
+                clickAllowButton();
+                getUiDevice().waitForIdle();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
 
         // Expect the permission are reported as granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false, true, false, true});
+        assertPermissionRequestResult(result, permissions, new boolean[] {false, true, false, true});
 
         // The permissions are granted
         assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
@@ -589,13 +538,10 @@
 
         // Request the permission and allow it
         BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
                 () -> { /* empty */ });
 
         // Expect the permissions is not granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[] {false});
+        assertPermissionRequestResult(result, permissions, new boolean[] {false});
     }
 
     private void assertAllPermissionsRevoked() {
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp26/src/com/android/cts/usepermission/UsePermissionTest26.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp26/src/com/android/cts/usepermission/UsePermissionTest26.java
index e64838b..85b3529 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp26/src/com/android/cts/usepermission/UsePermissionTest26.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp26/src/com/android/cts/usepermission/UsePermissionTest26.java
@@ -42,21 +42,17 @@
         // request only one permission from the 'SMS' permission group at runtime,
         // but two from this group are <uses-permission> in the manifest
         // request only one permission from the 'contacts' permission group
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    try {
-                        clickAllowButton();
-                        getUiDevice().waitForIdle();
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-                });
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
+            try {
+                clickAllowButton();
+                getUiDevice().waitForIdle();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
 
         // Expect the permission is granted
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, new boolean[]{true});
+        assertPermissionRequestResult(result, permissions, new boolean[]{true});
 
         assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getTargetContext()
                 .checkSelfPermission(Manifest.permission.SEND_SMS));
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp28/src/com/android/cts/usepermission/UsePermissionTest28.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp28/src/com/android/cts/usepermission/UsePermissionTest28.java
index 1c32d39..4dd5349 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp28/src/com/android/cts/usepermission/UsePermissionTest28.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp28/src/com/android/cts/usepermission/UsePermissionTest28.java
@@ -23,9 +23,7 @@
 
 import static junit.framework.Assert.assertEquals;
 
-import android.Manifest;
 import android.content.Context;
-import android.content.pm.PackageManager;
 
 import org.junit.Test;
 
@@ -46,19 +44,15 @@
 
         // request only foreground permission. This should automatically also add the background
         // permission
-        BasePermissionActivity.Result result = requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    try {
-                        clickAllowAlwaysButton();
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-                });
+        BasePermissionActivity.Result result = requestPermissions(permissions, () -> {
+            try {
+                clickAllowAlwaysButton();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
 
-        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, permissions,
-                new boolean[]{true});
+        assertPermissionRequestResult(result, permissions, new boolean[]{true});
 
         assertEquals(PERMISSION_GRANTED, context.checkSelfPermission(ACCESS_FINE_LOCATION));
         assertEquals(PERMISSION_GRANTED, context.checkSelfPermission(ACCESS_BACKGROUND_LOCATION));
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp29/src/com/android/cts/usepermission/UsePermissionTest29.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp29/src/com/android/cts/usepermission/UsePermissionTest29.java
index e0e21eb..4fdc6c8 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp29/src/com/android/cts/usepermission/UsePermissionTest29.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp29/src/com/android/cts/usepermission/UsePermissionTest29.java
@@ -48,25 +48,21 @@
 
     private BasePermissionActivity.Result requestPermissions(String[] permissions,
             UiInteraction... uiInteractions) throws Exception {
-        return super.requestPermissions(permissions,
-                REQUEST_CODE_PERMISSIONS,
-                BasePermissionActivity.class,
-                () -> {
-                    try {
-                        for (UiInteraction uiInteraction : uiInteractions) {
-                            uiInteraction.run();
-                            getUiDevice().waitForIdle();
-                        }
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-                });
+        return requestPermissions(permissions, () -> {
+            try {
+                for (UiInteraction uiInteraction : uiInteractions) {
+                    uiInteraction.run();
+                    getUiDevice().waitForIdle();
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
     }
 
-    private static void assertPermissionRequestResult(BasePermissionActivity.Result result,
+    protected static void assertPermissionRequestResult(BasePermissionActivity.Result result,
             String[] permissions, boolean... granted) {
-        BasePermissionsTest.assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
-                permissions, granted);
+        BasePermissionsTest.assertPermissionRequestResult(result, permissions, granted);
     }
 
     @Before
diff --git a/tests/tests/packageinstaller/install/AndroidManifest.xml b/tests/tests/packageinstaller/install/AndroidManifest.xml
index 7d2e984..eeef252 100644
--- a/tests/tests/packageinstaller/install/AndroidManifest.xml
+++ b/tests/tests/packageinstaller/install/AndroidManifest.xml
@@ -22,7 +22,7 @@
     <application android:label="Cts Package Installer Tests">
         <uses-library android:name="android.test.runner" />
 
-        <activity android:name=".InstallConfirmDialogStarter" />
+        <activity android:name="com.android.compatibility.common.util.FutureResultActivity" />
 
         <provider android:authorities="android.packageinstaller.install.cts.fileprovider"
                   android:name="androidx.core.content.FileProvider"
diff --git a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
index a101ba0..d84ab1b 100644
--- a/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
+++ b/tests/tests/packageinstaller/install/src/android/packageinstaller/install/cts/PackageInstallerTestBase.kt
@@ -38,6 +38,7 @@
 import android.support.test.uiautomator.Until
 import androidx.core.content.FileProvider
 import com.android.compatibility.common.util.AppOpsUtils
+import com.android.compatibility.common.util.FutureResultActivity
 import org.junit.After
 import org.junit.Assert
 import org.junit.Before
@@ -63,7 +64,7 @@
 
 open class PackageInstallerTestBase {
     @get:Rule
-    val installDialogStarter = ActivityTestRule(InstallConfirmDialogStarter::class.java)
+    val installDialogStarter = ActivityTestRule(FutureResultActivity::class.java)
 
     private val context = InstrumentationRegistry.getTargetContext()
     private val pm = context.packageManager
@@ -144,7 +145,7 @@
         }
 
         // Commit session
-        val dialog = doAndAwaitInstallConfirmDialog {
+        val dialog = FutureResultActivity.doAndAwaitStart {
             val pendingIntent = PendingIntent.getBroadcast(context, 0, Intent(INSTALL_ACTION_CB),
                     FLAG_UPDATE_CURRENT)
             session.commit(pendingIntent.intentSender)