diff --git a/res/values/strings.xml b/res/values/strings.xml
index b569f27e80a..d2128f6d118 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8832,10 +8832,6 @@
Permission manager
-
- Apps using %1$s
-
- Apps using %1$s, and more
Tap to wake
diff --git a/src/com/android/settings/applications/AppPermissionsPreferenceController.java b/src/com/android/settings/applications/AppPermissionsPreferenceController.java
deleted file mode 100644
index 4458ea4105c..00000000000
--- a/src/com/android/settings/applications/AppPermissionsPreferenceController.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-package com.android.settings.applications;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.icu.text.ListFormatter;
-import android.util.ArraySet;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.applications.PermissionsSummaryHelper;
-
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public class AppPermissionsPreferenceController extends BasePreferenceController {
-
- private static final String TAG = "AppPermissionPrefCtrl";
- private static final int NUM_PACKAGE_TO_CHECK = 4;
-
- @VisibleForTesting
- static int NUM_PERMISSIONS_TO_SHOW = 3;
-
- private final PackageManager mPackageManager;
- private final Set mPermissionGroups;
-
- private final PermissionsSummaryHelper.PermissionsResultCallback mPermissionsCallback =
- new PermissionsSummaryHelper.PermissionsResultCallback() {
- @Override
- public void onPermissionSummaryResult(int standardGrantedPermissionCount,
- int requestedPermissionCount, int additionalGrantedPermissionCount,
- List grantedGroupLabels) {
- updateSummary(grantedGroupLabels);
- }
- };
-
- @VisibleForTesting
- int mNumPackageChecked;
-
- private Preference mPreference;
-
- public AppPermissionsPreferenceController(Context context, String preferenceKey) {
- super(context, preferenceKey);
- mPackageManager = context.getPackageManager();
- mPermissionGroups = new ArraySet<>();
- }
-
- @Override
- public int getAvailabilityStatus() {
- return AVAILABLE;
- }
-
- @Override
- public void updateState(Preference preference) {
- mPreference = preference;
- mNumPackageChecked = 0;
- queryPermissionSummary();
- }
-
- @VisibleForTesting
- void queryPermissionSummary() {
- final List installedPackages =
- mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
- // Here we only get the first four apps and check their permissions.
- final List packagesWithPermission = installedPackages.stream()
- .filter(pInfo -> pInfo.permissions != null)
- .limit(NUM_PACKAGE_TO_CHECK)
- .collect(Collectors.toList());
-
- for (PackageInfo installedPackage : packagesWithPermission) {
- PermissionsSummaryHelper.getPermissionSummary(mContext,
- installedPackage.packageName, mPermissionsCallback);
- }
- }
-
- @VisibleForTesting
- void updateSummary(List grantedGroupLabels) {
- mPermissionGroups.addAll(grantedGroupLabels);
- mNumPackageChecked++;
-
- if (mNumPackageChecked < NUM_PACKAGE_TO_CHECK) {
- return;
- }
-
- final List permissionsToShow = mPermissionGroups.stream()
- .limit(NUM_PERMISSIONS_TO_SHOW)
- .collect(Collectors.toList());
- final boolean isMoreShowed = mPermissionGroups.size() > NUM_PERMISSIONS_TO_SHOW;
- CharSequence summary;
-
- if (!permissionsToShow.isEmpty()) {
- if (isMoreShowed) {
- summary = mContext.getString(R.string.app_permissions_summary_more,
- ListFormatter.getInstance().format(permissionsToShow).toLowerCase());
- } else {
- summary = mContext.getString(R.string.app_permissions_summary,
- ListFormatter.getInstance().format(permissionsToShow).toLowerCase());
- }
- } else {
- summary = mContext.getString(
- R.string.runtime_permissions_summary_no_permissions_granted);
- }
- mPreference.setSummary(summary);
- }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/spa/app/appsettings/AppButtonRepository.kt b/src/com/android/settings/spa/app/appsettings/AppButtonRepository.kt
index c5e84ae886d..37801989b1e 100644
--- a/src/com/android/settings/spa/app/appsettings/AppButtonRepository.kt
+++ b/src/com/android/settings/spa/app/appsettings/AppButtonRepository.kt
@@ -22,9 +22,12 @@ import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
+import com.android.settingslib.RestrictedLockUtils
+import com.android.settingslib.RestrictedLockUtilsInternal
import com.android.settingslib.Utils
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.model.app.isDisallowControl
+import com.android.settingslib.spaprivileged.model.app.userId
class AppButtonRepository(private val context: Context) {
private val packageManager = context.packageManager
@@ -43,6 +46,16 @@ class AppButtonRepository(private val context: Context) {
else -> app.isDisallowControl(context)
}
+ /**
+ * Checks whether uninstall is blocked by admin.
+ */
+ fun isUninstallBlockedByAdmin(app: ApplicationInfo): Boolean =
+ RestrictedLockUtilsInternal.checkIfUninstallBlocked(context, app.packageName, app.userId)
+ ?.let { admin ->
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, admin)
+ true
+ } ?: false
+
fun getHomePackageInfo(): HomePackages {
val homePackages = mutableSetOf()
val homeActivities = ArrayList()
diff --git a/src/com/android/settings/spa/app/appsettings/AppDisableButton.kt b/src/com/android/settings/spa/app/appsettings/AppDisableButton.kt
index cc5a76e2f99..0d48728bfd1 100644
--- a/src/com/android/settings/spa/app/appsettings/AppDisableButton.kt
+++ b/src/com/android/settings/spa/app/appsettings/AppDisableButton.kt
@@ -16,6 +16,7 @@
package com.android.settings.spa.app.appsettings
+import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ArrowCircleDown
@@ -34,7 +35,6 @@ import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spa.widget.button.ActionButton
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.framework.common.userManager
-import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
import com.android.settingslib.spaprivileged.model.app.isDisabledUntilUsed
import com.android.settingslib.Utils as SettingsLibUtils
@@ -58,7 +58,7 @@ class AppDisableButton(
return when {
app.enabled && !app.isDisabledUntilUsed -> {
- disableButton(enabled = isDisableButtonEnabled(packageInfo))
+ disableButton(app = app, enabled = isDisableButtonEnabled(packageInfo))
}
else -> enableButton()
@@ -82,9 +82,6 @@ class AppDisableButton(
// signed with the system certificate.
SettingsLibUtils.isSystemPackage(resources, packageManager, packageInfo) -> false
- // If this is a device admin, it can't be disabled.
- app.isActiveAdmin(context) -> false
-
// We don't allow disabling DO/PO on *any* users if it's a system app, because
// "disabling" is actually "downgrade to the system version + disable", and "downgrade"
// will clear data on all users.
@@ -99,11 +96,16 @@ class AppDisableButton(
}
}
- private fun disableButton(enabled: Boolean) = ActionButton(
+ private fun disableButton(app: ApplicationInfo, enabled: Boolean) = ActionButton(
text = context.getString(R.string.disable_text),
imageVector = Icons.Outlined.HideSource,
enabled = enabled,
- ) { openConfirmDialog = true }
+ ) {
+ // Currently we apply the same device policy for both the uninstallation and disable button.
+ if (!appButtonRepository.isUninstallBlockedByAdmin(app)) {
+ openConfirmDialog = true
+ }
+ }
private fun enableButton() = ActionButton(
text = context.getString(R.string.enable_text),
diff --git a/src/com/android/settings/spa/app/appsettings/AppSettingsMoreOptions.kt b/src/com/android/settings/spa/app/appsettings/AppSettingsMoreOptions.kt
index d17ff33bf39..20415c3b028 100644
--- a/src/com/android/settings/spa/app/appsettings/AppSettingsMoreOptions.kt
+++ b/src/com/android/settings/spa/app/appsettings/AppSettingsMoreOptions.kt
@@ -30,7 +30,6 @@ import com.android.settingslib.spa.widget.scaffold.MoreOptionsAction
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.model.app.PackageManagers
-import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
import com.android.settingslib.spaprivileged.model.app.isDisallowControl
import com.android.settingslib.spaprivileged.model.app.userId
@@ -76,7 +75,7 @@ private fun isShowUninstallUpdates(context: Context, app: ApplicationInfo): Bool
!context.resources.getBoolean(R.bool.config_disable_uninstall_update)
private fun isShowUninstallForAllUsers(context: Context, app: ApplicationInfo): Boolean =
- app.userId == 0 && !app.isSystemApp && !app.isInstantApp && !app.isActiveAdmin(context) &&
+ app.userId == 0 && !app.isSystemApp && !app.isInstantApp &&
isOtherUserHasInstallPackage(context, app)
private fun isOtherUserHasInstallPackage(context: Context, app: ApplicationInfo): Boolean =
diff --git a/src/com/android/settings/spa/app/appsettings/AppUninstallButton.kt b/src/com/android/settings/spa/app/appsettings/AppUninstallButton.kt
index cdb2cd01e8f..e85adc8cad5 100644
--- a/src/com/android/settings/spa/app/appsettings/AppUninstallButton.kt
+++ b/src/com/android/settings/spa/app/appsettings/AppUninstallButton.kt
@@ -16,32 +16,21 @@
package com.android.settings.spa.app.appsettings
-import android.app.settings.SettingsEnums
-import android.content.ComponentName
-import android.content.Intent
import android.content.om.OverlayManager
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
-import android.net.Uri
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Delete
import com.android.settings.R
-import com.android.settings.Utils
-import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd
-import com.android.settingslib.RestrictedLockUtils
-import com.android.settingslib.RestrictedLockUtilsInternal
import com.android.settingslib.spa.widget.button.ActionButton
-import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.model.app.hasFlag
import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
import com.android.settingslib.spaprivileged.model.app.userHandle
-import com.android.settingslib.spaprivileged.model.app.userId
class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter) {
private val context = packageInfoPresenter.context
private val appButtonRepository = AppButtonRepository(context)
private val overlayManager = context.getSystemService(OverlayManager::class.java)!!
- private val devicePolicyManager = context.devicePolicyManager
fun getActionButton(packageInfo: PackageInfo): ActionButton? {
val app = packageInfo.applicationInfo
@@ -54,7 +43,7 @@ class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter)
!app.hasFlag(ApplicationInfo.FLAG_INSTALLED) -> false
// Not allow to uninstall DO/PO.
- Utils.isProfileOrDeviceOwner(devicePolicyManager, app.packageName, app.userId) -> false
+ app.isActiveAdmin(context) -> false
appButtonRepository.isDisallowControl(app) -> false
@@ -99,20 +88,7 @@ class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter)
) { onUninstallClicked(app) }
private fun onUninstallClicked(app: ApplicationInfo) {
- if (app.isActiveAdmin(context)) {
- packageInfoPresenter.logAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN)
- val intent = Intent(context, DeviceAdminAdd::class.java).apply {
- putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME, app.packageName)
- }
- context.startActivityAsUser(intent, app.userHandle)
- return
- }
- RestrictedLockUtilsInternal.checkIfUninstallBlocked(
- context, app.packageName, app.userId
- )?.let { admin ->
- RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, admin)
- return
- }
+ if (appButtonRepository.isUninstallBlockedByAdmin(app)) return
packageInfoPresenter.startUninstallActivity()
}
}
diff --git a/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java
deleted file mode 100644
index dfa938313b3..00000000000
--- a/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.settings.applications;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class AppPermissionsPreferenceControllerTest {
-
- private Context mContext;
- private AppPermissionsPreferenceController mController;
- private Preference mPreference;
-
- @Before
- public void setUp() throws NameNotFoundException {
- mContext = RuntimeEnvironment.application;
- mPreference = spy(new Preference(mContext));
- mController = spy(new AppPermissionsPreferenceController(mContext, "pref_key"));
- }
-
- @Test
- public void isAvailable_shouldAlwaysReturnTrue() {
- assertThat(mController.isAvailable()).isTrue();
- }
-
- @Test
- public void updateState_shouldResetNumPackageChecked() {
- doNothing().when(mController).queryPermissionSummary();
- mController.mNumPackageChecked = 3;
-
- mController.updateState(mPreference);
-
- assertThat(mController.mNumPackageChecked).isEqualTo(0);
- }
-
- @Test
- public void updateSummary_noGrantedPermission_shouldSetNoPermissionGrantedSummary() {
- doNothing().when(mController).queryPermissionSummary();
- mController.updateState(mPreference);
- mController.mNumPackageChecked = 3;
-
- mController.updateSummary(new ArrayList<>());
-
- assertThat(mPreference.getSummary()).isEqualTo(
- mContext.getString(R.string.runtime_permissions_summary_no_permissions_granted));
- }
-
- @Test
- public void updateSummary_hasOnePermission_shouldSetPermissionAsSummary() {
- doNothing().when(mController).queryPermissionSummary();
- mController.updateState(mPreference);
- final String permission = "location";
- final ArrayList labels = new ArrayList<>();
- labels.add(permission);
- final String summary = "Apps using " + permission;
- mController.mNumPackageChecked = 3;
-
- mController.updateSummary(labels);
-
- assertThat(mPreference.getSummary()).isEqualTo(summary);
- }
-
- @Test
- public void updateSummary_hasThreePermissions_shouldShowThreePermissionAsSummary() {
- doNothing().when(mController).queryPermissionSummary();
- mController.updateState(mPreference);
- mController.mNumPackageChecked = 3;
- final List labels = new ArrayList<>();
- labels.add("Phone");
- labels.add("SMS");
- labels.add("Microphone");
-
- mController.updateSummary(labels);
-
- final String summary = "Apps using microphone, sms, and phone";
- assertThat(mPreference.getSummary()).isEqualTo(summary);
- }
-
- @Test
- public void updateSummary_hasFivePermissions_shouldShowThreePermissionsAndMoreAsSummary() {
- doNothing().when(mController).queryPermissionSummary();
- mController.updateState(mPreference);
- mController.mNumPackageChecked = 3;
- final List labels = new ArrayList<>();
- labels.add("Phone");
- labels.add("SMS");
- labels.add("Microphone");
- labels.add("Contacts");
- labels.add("Camera");
- labels.add("Location");
-
- mController.updateSummary(labels);
-
- final String summary = "Apps using microphone, contacts, and sms, and more";
- assertThat(mPreference.getSummary()).isEqualTo(summary);
- }
-
- @Test
- public void updateSummary_notReachCallbackCount_shouldNotSetSummary() {
- doNothing().when(mController).queryPermissionSummary();
- mController.updateState(mPreference);
- final String permission = "location";
- final ArrayList labels = new ArrayList<>();
- labels.add(permission);
-
- mController.updateSummary(labels);
-
- verify(mPreference, never()).setSummary(anyString());
- }
-}