summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yuting Fang <yutingfang@google.com> 2024-03-19 16:15:37 +0000
committer Yuting Fang <yutingfang@google.com> 2024-03-19 18:09:21 +0000
commit16b14bc8ba7fc2bbfa4bd87b722a026b6f24690a (patch)
treef487404f1c1728daaa8a548e89d6672cb3a3fe08
parentfd02606476660e030c090fb6a83b198ec8e63c1d (diff)
Revert^2 "Conditionally show permission grant dialog on a remote device"
This reverts commit fd02606476660e030c090fb6a83b198ec8e63c1d. Reason for revert: Fixed the test failure caused by the original change in ag/26622490. Merge original change again. Change-Id: Ida2f62868f635472ff3fd8a87340683b37c530b3 LOW_COVERAGE_REASON=322876988
-rw-r--r--PermissionController/AndroidManifest.xml7
-rw-r--r--PermissionController/res/values/strings.xml6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java95
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/PermissionDialogStreamingBlockedActivity.kt44
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt29
-rw-r--r--flags/flags.aconfig8
-rw-r--r--tests/cts/permissionmultidevice/AndroidTest.xml7
-rw-r--r--tests/cts/permissionmultidevice/TestUtils/src/android/permissionmultidevice/cts/PermissionUtils.kt15
-rw-r--r--tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt127
10 files changed, 223 insertions, 117 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 4bd7720d0..a0f7563bd 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -283,6 +283,13 @@
</intent-filter>
</activity>
+ <activity android:name="com.android.permissioncontroller.permission.ui.PermissionDialogStreamingBlockedActivity"
+ android:theme="@style/PermissionDialog.FilterTouches"
+ android:excludeFromRecents="true"
+ android:exported="false"
+ android:enabled="@bool/is_at_least_v">
+ </activity>
+
<activity android:name="com.android.permissioncontroller.ecm.EnhancedConfirmationDialog"
android:theme="@style/GrantPermissions.FilterTouches"
android:excludeFromRecents="true"
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 6e8005ad0..a3592bdc4 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1982,4 +1982,10 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="help_url_action_disabled_by_restricted_settings" translatable="false"></string>
<!-- END ENHANCED CONFIRMATION DIALOG -->
+
+ <!-- Title for the warning dialog that shows when permission grant dialog is blocked from streaming to a remote device [CHAR LIMIT=70]-->
+ <string name="permission_grant_dialog_streaming_blocked_title">Permission request suppressed</string>
+
+ <!-- Descriptions for the warning dialog that shows when permission grant dialog is blocked from streaming to a remote device [CHAR LIMIT=200] -->
+ <string name="permission_grant_dialog_streaming_blocked_description">This app is requesting additional permissions, but permissions can’t be granted in a streaming session. Grant the permission on your phone first.</string>
</resources>
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt
index ef0a36583..f97cbed65 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightPackageInfoLiveData.kt
@@ -233,7 +233,7 @@ private constructor(
val deviceContext = ContextCompat.createDeviceContext(app, deviceId)
for ((idx, permName) in requestedPermissions.withIndex()) {
- if (isPermissionDeviceAware(permName)) {
+ if (isPermissionDeviceAware(deviceContext, deviceId, permName)) {
val result = deviceContext.checkPermission(permName, -1, uid)
if (result == PackageManager.PERMISSION_GRANTED) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index 4fd62dc05..ee4318bf0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -20,7 +20,6 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission_group.LOCATION;
import static android.Manifest.permission_group.READ_MEDIA_VISUAL;
-import static android.content.Intent.getIntent;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -37,6 +36,7 @@ import static com.android.permissioncontroller.permission.ui.GrantPermissionsVie
import static com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.APP_PERMISSION_REQUEST_CODE;
import static com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.ECM_REQUEST_CODE;
import static com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.PHOTO_PICKER_REQUEST_CODE;
+import static com.android.permissioncontroller.permission.utils.MultiDeviceUtils.isDeviceAwarePermissionSupported;
import static com.android.permissioncontroller.permission.utils.Utils.getRequestMessage;
import android.Manifest;
@@ -50,7 +50,6 @@ import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
-import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.permission.flags.Flags;
@@ -68,6 +67,8 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -222,6 +223,16 @@ public class GrantPermissionsActivity extends SettingsActivity
/** Which device the permission will affect. Default is the primary device. */
private int mTargetDeviceId = ContextCompat.DEVICE_ID_DEFAULT;
+ private ActivityResultLauncher<Intent> mShowWarningDialog =
+ registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(),
+ result -> {
+ int resultCode = result.getResultCode();
+ if (resultCode == RESULT_OK) {
+ finishAfterTransition();
+ }
+ });
+
@Override
public void onCreate(Bundle icicle) {
if (DeviceUtils.isAuto(this)) {
@@ -241,7 +252,6 @@ public class GrantPermissionsActivity extends SettingsActivity
getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM);
}
- int permissionsSdkLevel;
if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(getIntent().getAction())) {
mIsSystemTriggered = true;
mTargetPackage = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
@@ -251,9 +261,6 @@ public class GrantPermissionsActivity extends SettingsActivity
finishAfterTransition();
return;
}
- // We don't want to do any filtering in this case.
- // These calls are coming from the system on behalf of the app.
- permissionsSdkLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
} else {
// Cache this as this can only read on onCreate, not later.
mTargetPackage = getCallingPackage();
@@ -265,7 +272,6 @@ public class GrantPermissionsActivity extends SettingsActivity
}
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(mTargetPackage, 0);
- permissionsSdkLevel = packageInfo.applicationInfo.targetSdkVersion;
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Unable to get package info for the calling package.", e);
finishAfterTransition();
@@ -281,8 +287,49 @@ public class GrantPermissionsActivity extends SettingsActivity
}
mRequestedPermissions = removeNullOrEmptyPermissions(requestedPermissionsArray);
- if (mIsSystemTriggered) {
- mSystemRequestedPermissions.addAll(mRequestedPermissions);
+ mOriginalRequestedPermissions = mRequestedPermissions.toArray(new String[0]);
+
+ // Do validation if permissions are requested for a remote device or the dialog is being
+ // streamed to a remote device.
+ if (isDeviceAwarePermissionSupported(getApplicationContext())) {
+ mTargetDeviceId = getIntent().getIntExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID,
+ ContextCompat.DEVICE_ID_DEFAULT);
+
+ // When the dialog is streamed to a remote device, verify requested permissions are all
+ // device aware and target device is the same as the remote device. Otherwise show a
+ // warning dialog.
+ if (getDeviceId() != ContextCompat.DEVICE_ID_DEFAULT) {
+ boolean showWarningDialog = mTargetDeviceId != getDeviceId();
+
+ for (String permission : mRequestedPermissions) {
+ if (!MultiDeviceUtils.isPermissionDeviceAware(
+ getApplicationContext(), mTargetDeviceId, permission)) {
+ showWarningDialog = true;
+ }
+ }
+
+ if (showWarningDialog) {
+ mShowWarningDialog.launch(
+ new Intent(this, PermissionDialogStreamingBlockedActivity.class));
+ return;
+ }
+ } else if (mTargetDeviceId != ContextCompat.DEVICE_ID_DEFAULT) {
+ // On the default device, when requested permissions are for a remote device,
+ // filter out non-device aware permissions.
+ for (int i = mRequestedPermissions.size() - 1; i >= 0; i--) {
+ if (!MultiDeviceUtils.isPermissionDeviceAware(
+ getApplicationContext(),
+ mTargetDeviceId,
+ mRequestedPermissions.get(i))) {
+ Log.e(
+ LOG_TAG,
+ "non-device aware permission is requested for a remote device: "
+ + mRequestedPermissions.get(i));
+ mRequestedPermissions.remove(i);
+ }
+ }
+ }
}
if (mRequestedPermissions.isEmpty()) {
@@ -290,36 +337,10 @@ public class GrantPermissionsActivity extends SettingsActivity
return;
}
- if (MultiDeviceUtils.isDeviceAwareGrantFlowEnabled()) {
- mTargetDeviceId =
- getIntent()
- .getIntExtra(
- PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID,
- ContextCompat.DEVICE_ID_DEFAULT);
- }
-
- // If the permissions requested are for a remote device, check if each permission is device
- // aware.
- if (mTargetDeviceId != ContextCompat.DEVICE_ID_DEFAULT) {
- if (!MultiDeviceUtils.isDeviceAwareGrantFlowEnabled()) {
- Log.e(LOG_TAG, "targetDeviceId should be the default device if device aware grant"
- + " flow is not enabled");
- finishAfterTransition();
- return;
- }
-
- for (String permission : mRequestedPermissions) {
- if (!MultiDeviceUtils.isPermissionDeviceAware(permission)) {
- Log.e(LOG_TAG, "When target device is external, permission " + permission
- + " needs to be device aware.");
- finishAfterTransition();
- return;
- }
- }
+ if (mIsSystemTriggered) {
+ mSystemRequestedPermissions.addAll(mRequestedPermissions);
}
- mOriginalRequestedPermissions = mRequestedPermissions.toArray(new String[0]);
-
if (SdkLevel.isAtLeastV() && Flags.enhancedConfirmationModeApisEnabled()) {
EnhancedConfirmationManager ecm = getEnhancedConfirmationManager();
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/PermissionDialogStreamingBlockedActivity.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/PermissionDialogStreamingBlockedActivity.kt
new file mode 100644
index 000000000..29f9ed2c7
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/PermissionDialogStreamingBlockedActivity.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 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.permissioncontroller.permission.ui
+
+import android.app.AlertDialog
+import android.os.Bundle
+import androidx.fragment.app.FragmentActivity
+import com.android.permissioncontroller.R
+
+/**
+ * In some scenarios we want to prevent the permission grant dialog from streaming to a remote
+ * device. If the streaming is blocked show a warning dialog rendered by this activity.
+ */
+class PermissionDialogStreamingBlockedActivity : FragmentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ AlertDialog.Builder(this)
+ .setTitle(R.string.permission_grant_dialog_streaming_blocked_title)
+ .setMessage(R.string.permission_grant_dialog_streaming_blocked_description)
+ .setPositiveButton(R.string.ongoing_usage_dialog_ok, null)
+ .setOnDismissListener() {
+ setResult(RESULT_OK)
+ finish()
+ }
+ .create()
+ .show()
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt
index ba5ba1c23..117a6c8ed 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt
@@ -7,7 +7,7 @@ import android.os.Build
import android.provider.Settings
import androidx.annotation.ChecksSdkIntAtLeast
import com.android.modules.utils.build.SdkLevel
-import com.android.permission.flags.Flags
+import com.android.permissioncontroller.DeviceUtils
object MultiDeviceUtils {
const val DEFAULT_REMOTE_DEVICE_NAME = "remote device"
@@ -21,13 +21,32 @@ object MultiDeviceUtils {
setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
@JvmStatic
- fun isPermissionDeviceAware(permission: String): Boolean =
- permission in DEVICE_AWARE_PERMISSIONS
+ fun isDeviceAwarePermissionSupported(context: Context): Boolean =
+ SdkLevel.isAtLeastV() &&
+ !(DeviceUtils.isTelevision(context) ||
+ DeviceUtils.isAuto(context) ||
+ DeviceUtils.isWear(context))
@JvmStatic
@ChecksSdkIntAtLeast(Build.VERSION_CODES.VANILLA_ICE_CREAM)
- fun isDeviceAwareGrantFlowEnabled(): Boolean {
- return SdkLevel.isAtLeastV() && Flags.deviceAwarePermissionGrantEnabled()
+ fun isPermissionDeviceAware(context: Context, deviceId: Int, permission: String): Boolean {
+ if (!SdkLevel.isAtLeastV()) {
+ return false
+ }
+
+ if (permission !in DEVICE_AWARE_PERMISSIONS) {
+ return false
+ }
+
+ val virtualDevice =
+ context.getSystemService(VirtualDeviceManager::class.java)!!.getVirtualDevice(deviceId)
+ ?: return false
+
+ return when (permission) {
+ Manifest.permission.CAMERA -> virtualDevice.hasCustomCameraSupport()
+ Manifest.permission.RECORD_AUDIO -> virtualDevice.hasCustomAudioInputSupport()
+ else -> false
+ }
}
@JvmStatic
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
index 3077dd290..337936fd4 100644
--- a/flags/flags.aconfig
+++ b/flags/flags.aconfig
@@ -2,14 +2,6 @@ package: "com.android.permission.flags"
container: "com.android.permission"
flag {
- name: "device_aware_permission_grant_enabled"
- is_fixed_read_only: true
- namespace: "permissions"
- description: "Enables device aware grant permission flow"
- bug: "292252664"
-}
-
-flag {
name: "private_profile_supported"
namespace: "permissions"
description: "This flag is used to support private profile in safety center"
diff --git a/tests/cts/permissionmultidevice/AndroidTest.xml b/tests/cts/permissionmultidevice/AndroidTest.xml
index 2b43fd01c..d86bea2d5 100644
--- a/tests/cts/permissionmultidevice/AndroidTest.xml
+++ b/tests/cts/permissionmultidevice/AndroidTest.xml
@@ -37,13 +37,6 @@
<option name="disable-device-config-sync" value="true" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.FeatureFlagTargetPreparer">
- <option name="flag-value"
- value="permissions/com.android.permission.flags.device_aware_permission_grant=true"/>
- <option name="flag-value"
- value="virtual_devices/android.companion.virtual.flags.stream_permissions=true"/>
- </target_preparer>
-
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsPermissionMultiDeviceTestCases.apk" />
diff --git a/tests/cts/permissionmultidevice/TestUtils/src/android/permissionmultidevice/cts/PermissionUtils.kt b/tests/cts/permissionmultidevice/TestUtils/src/android/permissionmultidevice/cts/PermissionUtils.kt
index 0ae0fd8e0..cffc0617c 100644
--- a/tests/cts/permissionmultidevice/TestUtils/src/android/permissionmultidevice/cts/PermissionUtils.kt
+++ b/tests/cts/permissionmultidevice/TestUtils/src/android/permissionmultidevice/cts/PermissionUtils.kt
@@ -1,16 +1,12 @@
package android.permissionmultidevice.cts
import android.content.Context
+import android.content.pm.PackageManager
import android.permission.PermissionManager
import android.permission.PermissionManager.PermissionState
-import android.provider.Settings
import com.android.compatibility.common.util.SystemUtil
object PermissionUtils {
- fun getHostDeviceName(context: Context): String {
- return Settings.Global.getString(context.contentResolver, Settings.Global.DEVICE_NAME)
- }
-
fun getAllPermissionStates(
context: Context,
packageName: String,
@@ -21,4 +17,13 @@ object PermissionUtils {
permissionManager.getAllPermissionStates(packageName, companionDeviceId)
}
}
+
+ fun isAutomotive(context: Context): Boolean =
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+
+ fun isTv(context: Context): Boolean =
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+
+ fun isWatch(context: Context): Boolean =
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
}
diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt
index c199c7660..191e69367 100644
--- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt
+++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt
@@ -17,33 +17,37 @@
package android.permissionmultidevice.cts
import android.Manifest
-import android.app.ActivityOptions
import android.app.Instrumentation
import android.companion.virtual.VirtualDeviceManager
+import android.companion.virtual.VirtualDeviceParams
+import android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM
+import android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA
import android.content.ComponentName
-import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS
+import android.hardware.display.DisplayManager
+import android.hardware.display.VirtualDisplay
import android.os.Build
import android.permission.flags.Flags
import android.permissionmultidevice.cts.PackageManagementUtils.installPackage
import android.permissionmultidevice.cts.PackageManagementUtils.uninstallPackage
-import android.permissionmultidevice.cts.PermissionUtils.getHostDeviceName
import android.permissionmultidevice.cts.UiAutomatorUtils.click
import android.permissionmultidevice.cts.UiAutomatorUtils.findTextForView
import android.permissionmultidevice.cts.UiAutomatorUtils.waitFindObject
+import android.platform.test.annotations.AppModeFull
import android.platform.test.annotations.RequiresFlagsEnabled
-import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.view.Display
+import android.virtualdevice.cts.common.VirtualDeviceRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
-import com.android.compatibility.common.util.AdoptShellPermissionsRule
import com.android.compatibility.common.util.SystemUtil
import com.google.common.truth.Truth
import org.junit.After
import org.junit.Assert
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -51,24 +55,49 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
+@AppModeFull(reason = "VirtualDeviceManager cannot be accessed by instant apps")
class DeviceAwarePermissionGrantTest {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val defaultDeviceContext = instrumentation.targetContext
+ private lateinit var mVirtualDeviceManager: VirtualDeviceManager
+ private lateinit var mVirtualDevice: VirtualDeviceManager.VirtualDevice
+ private lateinit var mVirtualDisplay: VirtualDisplay
+ private lateinit var mDeviceDisplayName: String
- @get:Rule(order = 0)
- val mAdoptShellPermissionsRule =
- AdoptShellPermissionsRule(
- instrumentation.uiAutomation,
- Manifest.permission.CREATE_VIRTUAL_DEVICE
- )
-
- @get:Rule(order = 1) var mFakeVirtualDeviceRule = FakeVirtualDeviceRule()
-
- @Rule @JvmField val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+ @get:Rule var mVirtualDeviceRule = VirtualDeviceRule.createDefault()
@Before
fun setup() {
+ assumeFalse(PermissionUtils.isAutomotive(defaultDeviceContext))
+ assumeFalse(PermissionUtils.isTv(defaultDeviceContext))
+ assumeFalse(PermissionUtils.isWatch(defaultDeviceContext))
+
installPackage(APP_APK_PATH_STREAMING)
+ mVirtualDeviceManager =
+ defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java)!!
+ mVirtualDevice =
+ mVirtualDeviceRule.createManagedVirtualDevice(
+ VirtualDeviceParams.Builder()
+ .setDevicePolicy(POLICY_TYPE_CAMERA, DEVICE_POLICY_CUSTOM)
+ .build()
+ )
+
+ val displayConfig =
+ VirtualDeviceRule.createDefaultVirtualDisplayConfigBuilder(
+ DISPLAY_WIDTH,
+ DISPLAY_HEIGHT
+ )
+ .setFlags(
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC or
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED or
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
+ )
+ .build()
+
+ mVirtualDisplay =
+ mVirtualDeviceRule.createManagedVirtualDisplay(mVirtualDevice, displayConfig)!!
+ mDeviceDisplayName =
+ mVirtualDeviceManager.getVirtualDevice(mVirtualDevice.deviceId)!!.displayName.toString()
}
@After
@@ -100,9 +129,9 @@ class DeviceAwarePermissionGrantTest {
fun onHostDevice_requestPermissionForRemoteDevice_shouldGrantPermission() {
testGrantPermissionForDevice(
Display.DEFAULT_DISPLAY,
- mFakeVirtualDeviceRule.virtualDevice.deviceId,
+ mVirtualDevice.deviceId,
true,
- mFakeVirtualDeviceRule.deviceDisplayName,
+ mDeviceDisplayName,
expectPermissionGrantedOnDefaultDevice = false,
expectPermissionGrantedOnRemoteDevice = true
)
@@ -113,15 +142,11 @@ class DeviceAwarePermissionGrantTest {
Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED
)
@Test
- fun onRemoteDevice_requestPermissionForHostDevice_shouldGrantPermission() {
- testGrantPermissionForDevice(
- mFakeVirtualDeviceRule.virtualDisplayId,
- DEVICE_ID_DEFAULT,
- true,
- getHostDeviceName(defaultDeviceContext),
- expectPermissionGrantedOnDefaultDevice = true,
- expectPermissionGrantedOnRemoteDevice = false
- )
+ fun onRemoteDevice_requestPermissionForHostDevice_shouldShowWarningDialog() {
+ requestPermissionOnDevice(mVirtualDisplay.display.displayId, DEVICE_ID_DEFAULT)
+
+ val displayId = mVirtualDisplay.display.displayId
+ waitFindObject(By.displayId(displayId).textContains("Permission request suppressed"))
}
@RequiresFlagsEnabled(
@@ -131,10 +156,10 @@ class DeviceAwarePermissionGrantTest {
@Test
fun onRemoteDevice_requestPermissionForRemoteDevice_shouldGrantPermission() {
testGrantPermissionForDevice(
- mFakeVirtualDeviceRule.virtualDisplayId,
- mFakeVirtualDeviceRule.virtualDevice.deviceId,
+ mVirtualDisplay.display.displayId,
+ mVirtualDevice.deviceId,
true,
- mFakeVirtualDeviceRule.deviceDisplayName,
+ mDeviceDisplayName,
expectPermissionGrantedOnDefaultDevice = false,
expectPermissionGrantedOnRemoteDevice = true
)
@@ -148,15 +173,12 @@ class DeviceAwarePermissionGrantTest {
expectPermissionGrantedOnDefaultDevice: Boolean,
expectPermissionGrantedOnRemoteDevice: Boolean
) {
- assertAppHasPermissionForDevice(defaultDeviceContext, DEVICE_ID_DEFAULT, false)
-
- assertAppHasPermissionForDevice(
- defaultDeviceContext,
- mFakeVirtualDeviceRule.virtualDevice.deviceId,
- false
- )
+ // Assert no permission granted to either default device or virtual device
+ assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, false)
+ assertAppHasPermissionForDevice(mVirtualDevice.deviceId, false)
requestPermissionOnDevice(displayId, targetDeviceId)
+ mVirtualDeviceRule.waitAndAssertActivityResumed(getPermissionDialogComponentName())
if (showDeviceName) {
assertPermissionMessageContainsDeviceName(displayId, expectedDeviceNameInDialog)
@@ -164,22 +186,14 @@ class DeviceAwarePermissionGrantTest {
SystemUtil.eventually { click(By.displayId(displayId).res(ALLOW_BUTTON)) }
+ assertAppHasPermissionForDevice(DEVICE_ID_DEFAULT, expectPermissionGrantedOnDefaultDevice)
assertAppHasPermissionForDevice(
- defaultDeviceContext,
- DEVICE_ID_DEFAULT,
- expectPermissionGrantedOnDefaultDevice
- )
-
- assertAppHasPermissionForDevice(
- defaultDeviceContext,
- mFakeVirtualDeviceRule.virtualDevice.deviceId,
+ mVirtualDevice.deviceId,
expectPermissionGrantedOnRemoteDevice
)
}
private fun requestPermissionOnDevice(displayId: Int, targetDeviceId: Int) {
- val options = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle()
-
val intent =
Intent()
.setComponent(
@@ -187,7 +201,7 @@ class DeviceAwarePermissionGrantTest {
)
.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, targetDeviceId)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
- defaultDeviceContext.startActivity(intent, options)
+ mVirtualDeviceRule.sendIntentToDisplay(intent, displayId)
}
private fun assertPermissionMessageContainsDeviceName(displayId: Int, deviceName: String) {
@@ -196,16 +210,12 @@ class DeviceAwarePermissionGrantTest {
Truth.assertThat(text).contains(deviceName)
}
- private fun assertAppHasPermissionForDevice(
- context: Context,
- deviceId: Int,
- expectPermissionGranted: Boolean
- ) {
+ private fun assertAppHasPermissionForDevice(deviceId: Int, expectPermissionGranted: Boolean) {
val checkPermissionResult =
- context
+ defaultDeviceContext
.createDeviceContext(deviceId)
.packageManager
- .checkPermission(Manifest.permission.CAMERA, APP_PACKAGE_NAME)
+ .checkPermission(DEVICE_AWARE_PERMISSION, APP_PACKAGE_NAME)
if (expectPermissionGranted) {
Assert.assertEquals(PackageManager.PERMISSION_GRANTED, checkPermissionResult)
@@ -214,6 +224,12 @@ class DeviceAwarePermissionGrantTest {
}
}
+ private fun getPermissionDialogComponentName(): ComponentName {
+ val intent = Intent(ACTION_REQUEST_PERMISSIONS)
+ intent.setPackage(defaultDeviceContext.packageManager.getPermissionControllerPackageName())
+ return intent.resolveActivity(defaultDeviceContext.packageManager)
+ }
+
companion object {
const val APK_DIRECTORY = "/data/local/tmp/cts-permissionmultidevice"
const val APP_APK_PATH_STREAMING = "${APK_DIRECTORY}/CtsAccessRemoteDeviceCamera.apk"
@@ -223,5 +239,8 @@ class DeviceAwarePermissionGrantTest {
"com.android.permissioncontroller:id/permission_allow_foreground_only_button"
const val DEVICE_ID_DEFAULT = 0
const val PERSISTENT_DEVICE_ID_DEFAULT = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
+ const val DEVICE_AWARE_PERMISSION = Manifest.permission.CAMERA
+ private const val DISPLAY_HEIGHT = 1920
+ private const val DISPLAY_WIDTH = 1080
}
}