summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/res/values/strings.xml3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java20
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt33
-rw-r--r--flags/flags.aconfig9
-rw-r--r--tests/cts/permissionui/Android.bp1
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt15
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationBackportTest.kt146
8 files changed, 228 insertions, 0 deletions
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 698a9bbb4..57268f670 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1992,6 +1992,9 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- A string representing a message (sms, email, etc.) telling the user about a one time password. Used for testing [CHAR LIMIT=NONE] -->
<string name="test_otp_msg">Your one time password is 132435</string>
+ <!-- [CHAR LIMIT=50] Manage applications, unlock restricted setting from app permissions options menu -->
+ <string name="allow_restricted_settings">Allow restricted settings</string>
+
<!-- START ENHANCED CONFIRMATION DIALOG -->
<!--Title for dialog displayed to tell user that settings are blocked by setting restrictions [CHAR LIMIT=50] -->
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
index eff5738fc..e8d0fb22b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
@@ -252,6 +252,12 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
mPackageName, mUser));
return true;
}
+
+ case MENU_ALLOW_RESTRICTED_SETTINGS: {
+ mViewModel.clearRestriction();
+ getActivity().invalidateOptionsMenu();
+ return true;
+ }
}
return super.onOptionsItemSelected(item);
}
@@ -266,6 +272,20 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
getClass().getName());
}
}
+
+ if (SdkLevel.isAtLeastT() && !SdkLevel.isAtLeastV()
+ && Flags.enhancedConfirmationBackportEnabled()) {
+ menu.add(Menu.NONE, MENU_ALLOW_RESTRICTED_SETTINGS, Menu.NONE,
+ R.string.allow_restricted_settings);
+ }
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(@NonNull Menu menu) {
+ final MenuItem allowRestrictedSettingsMenu = menu.findItem(MENU_ALLOW_RESTRICTED_SETTINGS);
+ if (allowRestrictedSettingsMenu != null) {
+ allowRestrictedSettingsMenu.setVisible(mViewModel.isClearRestrictedAllowed());
+ }
}
private static void bindUi(SettingsWithLargeHeader fragment, String packageName,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java
index 17e72b413..a44c761a1 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java
@@ -42,6 +42,7 @@ public abstract class PermissionsFrameFragment extends PreferenceFragmentCompat
static final int MENU_ALL_PERMS = Menu.FIRST + 1;
public static final int MENU_SHOW_SYSTEM = Menu.FIRST + 2;
public static final int MENU_HIDE_SYSTEM = Menu.FIRST + 3;
+ static final int MENU_ALLOW_RESTRICTED_SETTINGS = Menu.FIRST + 4;
private ViewGroup mPreferencesContainer;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
index ee0c5d2f2..f92cc08d7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
@@ -17,6 +17,7 @@
package com.android.permissioncontroller.permission.ui.model
import android.Manifest
+import android.annotation.SuppressLint
import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_ALLOWED
import android.app.AppOpsManager.MODE_IGNORED
@@ -31,6 +32,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.android.modules.utils.build.SdkLevel
+import com.android.permission.flags.Flags
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.PermissionControllerStatsLog
import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION
@@ -128,6 +130,37 @@ class AppPermissionGroupsViewModel(
private val fullStoragePermsLiveData = FullStoragePermissionAppsLiveData
private val packagePermsExternalDeviceLiveData =
PackagePermissionsExternalDeviceLiveData[packageName, user]
+ private val appOpsManager = app.getSystemService(AppOpsManager::class.java)!!
+ private val packageManager = app.packageManager
+
+ /** Check if the application is in restricted settings mode. */
+ @SuppressLint("NewApi")
+ fun isClearRestrictedAllowed(): Boolean {
+ if (Flags.enhancedConfirmationBackportEnabled()) {
+ // TODO(b/347876543): Replace this when EnhancedConfirmtionServiceImpl is
+ // available.
+ val isRestricted =
+ appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS,
+ packageManager.getApplicationInfoAsUser(packageName, 0, user).uid,
+ packageName, null, null) == MODE_IGNORED
+ return isRestricted
+ }
+ return false
+ }
+
+ /** Allow restricted settings on the applications. */
+ @SuppressLint("NewApi")
+ fun clearRestriction() {
+ if (Flags.enhancedConfirmationBackportEnabled()) {
+ // TODO(b/347876543): Replace this when EnhancedConfirmationServiceImpl is
+ // available.
+ appOpsManager.setMode(
+ AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS,
+ packageManager.getApplicationInfoAsUser(packageName, 0, user).uid,
+ packageName, MODE_ALLOWED
+ )
+ }
+ }
/**
* LiveData whose data is a map of grant category (either allowed or denied) to a list of
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
index 2dd34e5ff..4f0f08938 100644
--- a/flags/flags.aconfig
+++ b/flags/flags.aconfig
@@ -47,6 +47,15 @@ flag {
}
flag {
+ name: "enhanced_confirmation_backport_enabled"
+ is_exported: true
+ namespace: "permissions"
+ description: "Flag to backport enhanced confirmation in permission mainline to T and U."
+ bug: "347876543"
+ is_fixed_read_only: true
+}
+
+flag {
name: "enable_coarse_fine_location_prompt_for_aaos"
is_exported: true
namespace: "permissions"
diff --git a/tests/cts/permissionui/Android.bp b/tests/cts/permissionui/Android.bp
index c1ec017ff..72624f5e2 100644
--- a/tests/cts/permissionui/Android.bp
+++ b/tests/cts/permissionui/Android.bp
@@ -44,6 +44,7 @@ android_test {
"platform-test-annotations",
"android.content.pm.flags-aconfig-java-export",
"android.permission.flags-aconfig-java-export",
+ "com.android.permission.flags-aconfig-java-export",
"Harrier",
],
data: [
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
index fdc13b3af..7e3f7f8dc 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
@@ -1102,6 +1102,21 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
}
}
+ @Suppress("DEPRECATION")
+ protected fun startManageAppPermissionsActivity() {
+ doAndWaitForWindowTransition {
+ runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ }
+ )
+ }
+ }
+ }
+
/** Starts activity with intent [ACTION_REVIEW_APP_DATA_SHARING_UPDATES]. */
fun startAppDataSharingUpdatesActivity() {
doAndWaitForWindowTransition {
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationBackportTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationBackportTest.kt
new file mode 100644
index 000000000..f38f678e9
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationBackportTest.kt
@@ -0,0 +1,146 @@
+/*
+ * 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 android.permissionui.cts
+
+import android.Manifest.permission_group.SMS
+import android.os.Build
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.modules.utils.build.SdkLevel
+import com.android.permission.flags.Flags
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+/** Enhanced Confirmation Backport UI tests. */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class EnhancedConfirmationBackportTest : BaseUsePermissionTest() {
+
+ @JvmField
+ @Rule
+ val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
+ @Before
+ fun setup() {
+ assumeFalse(isAutomotive)
+ assumeFalse(isTv)
+ assumeFalse(isWatch)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_BACKPORT_ENABLED)
+ @Test
+ fun installDownloadedFile_clickAppPermissions_clickAllowRestrictedSettings_clickSMSPermGroup_clickAllowed() {
+ installPackageWithInstallSourceAndNoMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
+
+ startManageAppPermissionsActivity()
+ waitFindObject(By.descContains(MORE_OPTIONS)).clickAndWait(
+ Until.newWindow(),
+ BasePermissionTest.TIMEOUT_MILLIS
+ )
+
+ if (!SdkLevel.isAtLeastV()) {
+ waitFindObject(By.text(ALLOW_RESTRICTED_SETTINGS)).click()
+
+ pressBack()
+
+ navigateToIndividualPermissionSetting(SMS)
+
+ assertAllowButtonIsEnabledAndClickAndChecked()
+
+ pressBack()
+ } else {
+ findView(By.text(ALLOW_RESTRICTED_SETTINGS), false)
+ }
+
+ pressBack()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_BACKPORT_ENABLED)
+ @Test
+ fun installFromLocalFile_clickAppPermissions_clickAllowRestrictedSettings_clickSMSPermGroup_clickAllowed() {
+ installPackageWithInstallSourceAndNoMetadataFromLocalFile(APP_APK_NAME_LATEST)
+
+ startManageAppPermissionsActivity()
+ waitFindObject(By.descContains(MORE_OPTIONS)).click()
+
+ if (!SdkLevel.isAtLeastV()) {
+ waitFindObject(By.text(ALLOW_RESTRICTED_SETTINGS)).click()
+
+ pressBack()
+
+ navigateToIndividualPermissionSetting(SMS)
+
+ assertAllowButtonIsEnabledAndClickAndChecked()
+
+ pressBack()
+ } else {
+ findView(By.text(ALLOW_RESTRICTED_SETTINGS), false)
+ }
+
+ pressBack()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @RequiresFlagsDisabled(Flags.FLAG_ENHANCED_CONFIRMATION_BACKPORT_ENABLED)
+ @Test
+ fun installDownloadedFile_clickAppPermissions_noAllowRestrictedSettings() {
+ installPackageWithInstallSourceAndNoMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
+
+ startManageAppPermissionsActivity()
+ waitFindObject(By.descContains(MORE_OPTIONS)).clickAndWait(
+ Until.newWindow(),
+ BasePermissionTest.TIMEOUT_MILLIS
+ )
+
+ findView(By.text(ALLOW_RESTRICTED_SETTINGS), false)
+
+ pressBack()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @RequiresFlagsDisabled(Flags.FLAG_ENHANCED_CONFIRMATION_BACKPORT_ENABLED)
+ @Test
+ fun installFromLocalFile_clickAppPermissions_noAllowRestrictedSettings() {
+ installPackageWithInstallSourceAndNoMetadataFromLocalFile(APP_APK_NAME_LATEST)
+
+ startManageAppPermissionsActivity()
+ waitFindObject(By.descContains(MORE_OPTIONS)).click()
+
+ findView(By.text(ALLOW_RESTRICTED_SETTINGS), false)
+
+ pressBack()
+ }
+
+ private fun assertAllowButtonIsEnabledAndClickAndChecked() {
+ waitFindObject(By.res(ALLOW_RADIO_BUTTON).enabled(true).checked(false))
+ .click()
+ waitFindObject(By.res(ALLOW_RADIO_BUTTON).checked(true))
+ }
+
+ companion object {
+ private const val MORE_OPTIONS = "More options"
+ private const val ALLOW_RESTRICTED_SETTINGS = "Allow restricted settings"
+ }
+}