Snap for 9156029 from 107109c4ac to udc-release

Change-Id: I34139bd2439a17fbf9e8d8085f80a1d9d3bfeeac
This commit is contained in:
Android Build Coastguard Worker
2022-10-09 23:36:37 +00:00
7 changed files with 25 additions and 307 deletions

View File

@@ -8832,10 +8832,6 @@
<!-- Label for list that shows all permissions -->
<string name="app_permissions">Permission manager</string>
<!-- Summary of permissions currently granted to apps [CHAR LIMIT=60] -->
<string name="app_permissions_summary">Apps using <xliff:g id="apps" example="location">%1$s</xliff:g></string>
<!-- Summary of permissions currently granted to apps [CHAR LIMIT=60] -->
<string name="app_permissions_summary_more">Apps using <xliff:g id="apps" example="location">%1$s</xliff:g>, and more</string>
<!-- Label for tap to wake setting [CHAR LIMIT=30] -->
<string name="tap_to_wake">Tap to wake</string>

View File

@@ -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<CharSequence> mPermissionGroups;
private final PermissionsSummaryHelper.PermissionsResultCallback mPermissionsCallback =
new PermissionsSummaryHelper.PermissionsResultCallback() {
@Override
public void onPermissionSummaryResult(int standardGrantedPermissionCount,
int requestedPermissionCount, int additionalGrantedPermissionCount,
List<CharSequence> 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<PackageInfo> installedPackages =
mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
// Here we only get the first four apps and check their permissions.
final List<PackageInfo> 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<CharSequence> grantedGroupLabels) {
mPermissionGroups.addAll(grantedGroupLabels);
mNumPackageChecked++;
if (mNumPackageChecked < NUM_PACKAGE_TO_CHECK) {
return;
}
final List<CharSequence> 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);
}
}

View File

@@ -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<String>()
val homeActivities = ArrayList<ResolveInfo>()

View File

@@ -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),

View File

@@ -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 =

View File

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

View File

@@ -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<CharSequence> 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<CharSequence> 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<CharSequence> 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<CharSequence> labels = new ArrayList<>();
labels.add(permission);
mController.updateSummary(labels);
verify(mPreference, never()).setSummary(anyString());
}
}