Loading packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java +10 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.settingslib; import android.app.admin.EnforcingAdmin; import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; Loading Loading @@ -159,6 +160,15 @@ public class PrimarySwitchPreference extends RestrictedPreference { setSwitchEnabled(admin == null); } /** * If admin is not null, disables the switch. * Otherwise, keep it enabled. */ public void setDisabledByAdmin(EnforcingAdmin admin) { super.setDisabledByAdmin(admin); setSwitchEnabled(admin == null); } public CompoundButton getSwitch() { return mSwitch; } Loading packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +82 −0 Original line number Diff line number Diff line Loading @@ -26,9 +26,11 @@ import static com.android.settingslib.Utils.getColorAttrDefaultColor; import android.annotation.UserIdInt; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.admin.DevicePolicyIdentifiers; import android.app.admin.DevicePolicyManager; import android.app.admin.EnforcingAdmin; import android.app.admin.PackagePolicy; import android.app.admin.PolicyEnforcementInfo; import android.app.admin.SystemAuthority; import android.app.ecm.EnhancedConfirmationManager; import android.app.role.RoleManager; Loading Loading @@ -272,6 +274,53 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { return checkForLockSetting(context, userId, check); } /** * Checks whether keyguard features are disabled by policy and returns the admin information. * * @param context {@link Context} for the calling user. * @param keyguardFeatures Any one of keyguard features that can be disabled by {@link * android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}. * @param userId User to check keyguard features for. * @return PolicyEnforcementInfo Object containing the enforcing admin information. null if * keyguard features are not disabled. * @throws IllegalStateException if * {@link android.app.admin.flags.Flags#setKeyguardDisabledFeaturesCoexistence} is not enabled. * When the flag is disabled, please use {@link #checkIfKeyguardFeaturesDisabled} instead. */ @RequiresApi(Build.VERSION_CODES.BAKLAVA) public static PolicyEnforcementInfo getEnforcingAdminsForKeyguardFeatures(Context context, int keyguardFeatures, @UserIdInt int userId) { // TODO(b/359186276): Remove this check once the flag is ready for clean-up. if (!android.app.admin.flags.Flags.setKeyguardDisabledFeaturesCoexistence()) { throw new IllegalStateException( "setKeyguardDisabledFeaturesCoexistence is not enabled. Use " + "checkIfKeyguardFeaturesDisabled instead."); } DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); if (dpm == null) { Log.w(LOG_TAG, "DevicePolicyManager is null"); return null; } if (!isKeyguardFeaturesDisabled(dpm, keyguardFeatures, userId)) { return null; } // We don't need to check separately for managed profile or parent profile policies as // the policy application is handled by DPM in {@link android.app.admin // .DevicePolicyManager#setKeyguardDisabledFeatures} already. return dpm.getEnforcingAdminsForPolicy( DevicePolicyIdentifiers.KEYGUARD_DISABLED_FEATURES_POLICY, userId); } private static boolean isKeyguardFeaturesDisabled(DevicePolicyManager dpm, int keyguardFeatures, int userId) { // Set admin as null to check for all admins who has set policy. int disabledFeatures = dpm.getKeyguardDisabledFeatures(/*admin=*/null, userId); return (disabledFeatures & keyguardFeatures) != KEYGUARD_DISABLE_FEATURES_NONE; } /** * @return the UserHandle for a userId. Return null for USER_NULL */ Loading Loading @@ -779,6 +828,39 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { item.setTitle(sb); } /** * Set the menu item as disabled by admin by adding a restricted padlock at the end of the * text and set the click listener which will send an intent to show the admin support details * dialog. If the admin is null, remove the padlock and disabled color span. When the admin is * null, we also set the OnMenuItemClickListener to null, so if you want to set a custom * OnMenuItemClickListener, set it after calling this method. */ public static void setMenuItemAsDisabledByAdmin(final Context context, final MenuItem item, final EnforcingAdmin admin, final String restriction) { SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle()); removeExistingRestrictedSpans(sb); if (admin != null) { final int disabledColor = getColorAttrDefaultColor(context, android.R.attr.textColorHint); sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ImageSpan image = new RestrictedLockImageSpan(context); sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { sendShowAdminSupportDetailsIntent(context, admin, restriction); return true; } }); } else { item.setOnMenuItemClickListener(null); } item.setTitle(sb); } private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) { final int length = sb.length(); RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length, Loading packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java +11 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package com.android.settingslib; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.admin.EnforcingAdmin; import android.content.Context; import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.res.TypedArrayUtils; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceViewHolder; Loading Loading @@ -149,6 +151,15 @@ public class RestrictedPreference extends TwoTargetPreference implements } } /** * Sets the admin that disabled this preference. */ public void setDisabledByAdmin(@Nullable EnforcingAdmin admin) { if (mHelper.setDisabledByEnforcingAdmin(admin)) { notifyChanged(); } } public boolean isDisabledByAdmin() { return mHelper.isDisabledByAdmin(); } Loading packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java +2 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.annotation.UserIdInt; import android.app.AlertDialog; import android.app.admin.EnforcingAdmin; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; Loading Loading @@ -217,7 +218,7 @@ public class InputMethodPreference extends PrimarySwitchPreference // This preference should also be disabled in case the admin does not allow this input // method. if (isAlwaysChecked) { setDisabledByAdmin(null); setDisabledByAdmin((EnforcingAdmin) null); setSwitchEnabled(false); } else if (!mIsAllowedByOrganization) { EnforcedAdmin admin = Loading packages/SettingsLib/src/com/android/settingslib/supervision/SupervisionRestrictionsHelper.kt +37 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.settingslib.supervision import android.app.admin.DeviceAdminReceiver import android.app.admin.EnforcingAdmin import android.app.admin.RoleAuthority import android.app.role.RoleManager import android.app.supervision.SupervisionAppService import android.app.supervision.SupervisionManager import android.content.ComponentName Loading @@ -40,6 +43,37 @@ object SupervisionRestrictionsHelper { restriction: String, user: UserHandle, ): EnforcedAdmin? { if (!supervisionEnabled(context, user.identifier)) { return null } return EnforcedAdmin(getSupervisionComponent(context, user.identifier), restriction, user) } /** * Creates an instance of [EnforcingAdmin] that uses the correct supervision component or * returns null if supervision is not enabled. */ @JvmStatic fun createEnforcingAdmin(context: Context, user: UserHandle): EnforcingAdmin? { if (!supervisionEnabled(context, user.identifier)) { return null } val componentName = getSupervisionComponent(context, user.identifier) val packageName = componentName?.packageName ?: "" return EnforcingAdmin( packageName, RoleAuthority(setOf(RoleManager.ROLE_SYSTEM_SUPERVISION)), user, componentName, ) } private fun supervisionEnabled(context: Context, userId: Int): Boolean { val supervisionManager = context.getSystemService(SupervisionManager::class.java) return supervisionManager?.isSupervisionEnabledForUser(userId) == true } private fun getSupervisionComponent(context: Context, userId: Int): ComponentName? { val supervisionManager = context.getSystemService(SupervisionManager::class.java) val supervisionAppPackage = supervisionManager?.activeSupervisionAppPackage ?: return null var supervisionComponent: ComponentName? = null Loading @@ -49,7 +83,7 @@ object SupervisionRestrictionsHelper { context.packageManager.queryIntentServicesAsUser( Intent(SupervisionAppService.ACTION_SUPERVISION_APP_SERVICE), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, user.identifier, userId, ) resolveSupervisionApps .mapNotNull { it.serviceInfo?.componentName } Loading @@ -63,7 +97,7 @@ object SupervisionRestrictionsHelper { context.packageManager.queryBroadcastReceiversAsUser( Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, user.identifier, userId, ) resolveDeviceAdmins .mapNotNull { it.activityInfo?.componentName } Loading @@ -74,6 +108,6 @@ object SupervisionRestrictionsHelper { if (supervisionComponent == null) { Log.d(SupervisionLog.TAG, "Could not find the supervision component.") } return EnforcedAdmin(supervisionComponent, restriction, user) return supervisionComponent } } Loading
packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java +10 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.settingslib; import android.app.admin.EnforcingAdmin; import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; Loading Loading @@ -159,6 +160,15 @@ public class PrimarySwitchPreference extends RestrictedPreference { setSwitchEnabled(admin == null); } /** * If admin is not null, disables the switch. * Otherwise, keep it enabled. */ public void setDisabledByAdmin(EnforcingAdmin admin) { super.setDisabledByAdmin(admin); setSwitchEnabled(admin == null); } public CompoundButton getSwitch() { return mSwitch; } Loading
packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +82 −0 Original line number Diff line number Diff line Loading @@ -26,9 +26,11 @@ import static com.android.settingslib.Utils.getColorAttrDefaultColor; import android.annotation.UserIdInt; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.admin.DevicePolicyIdentifiers; import android.app.admin.DevicePolicyManager; import android.app.admin.EnforcingAdmin; import android.app.admin.PackagePolicy; import android.app.admin.PolicyEnforcementInfo; import android.app.admin.SystemAuthority; import android.app.ecm.EnhancedConfirmationManager; import android.app.role.RoleManager; Loading Loading @@ -272,6 +274,53 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { return checkForLockSetting(context, userId, check); } /** * Checks whether keyguard features are disabled by policy and returns the admin information. * * @param context {@link Context} for the calling user. * @param keyguardFeatures Any one of keyguard features that can be disabled by {@link * android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}. * @param userId User to check keyguard features for. * @return PolicyEnforcementInfo Object containing the enforcing admin information. null if * keyguard features are not disabled. * @throws IllegalStateException if * {@link android.app.admin.flags.Flags#setKeyguardDisabledFeaturesCoexistence} is not enabled. * When the flag is disabled, please use {@link #checkIfKeyguardFeaturesDisabled} instead. */ @RequiresApi(Build.VERSION_CODES.BAKLAVA) public static PolicyEnforcementInfo getEnforcingAdminsForKeyguardFeatures(Context context, int keyguardFeatures, @UserIdInt int userId) { // TODO(b/359186276): Remove this check once the flag is ready for clean-up. if (!android.app.admin.flags.Flags.setKeyguardDisabledFeaturesCoexistence()) { throw new IllegalStateException( "setKeyguardDisabledFeaturesCoexistence is not enabled. Use " + "checkIfKeyguardFeaturesDisabled instead."); } DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); if (dpm == null) { Log.w(LOG_TAG, "DevicePolicyManager is null"); return null; } if (!isKeyguardFeaturesDisabled(dpm, keyguardFeatures, userId)) { return null; } // We don't need to check separately for managed profile or parent profile policies as // the policy application is handled by DPM in {@link android.app.admin // .DevicePolicyManager#setKeyguardDisabledFeatures} already. return dpm.getEnforcingAdminsForPolicy( DevicePolicyIdentifiers.KEYGUARD_DISABLED_FEATURES_POLICY, userId); } private static boolean isKeyguardFeaturesDisabled(DevicePolicyManager dpm, int keyguardFeatures, int userId) { // Set admin as null to check for all admins who has set policy. int disabledFeatures = dpm.getKeyguardDisabledFeatures(/*admin=*/null, userId); return (disabledFeatures & keyguardFeatures) != KEYGUARD_DISABLE_FEATURES_NONE; } /** * @return the UserHandle for a userId. Return null for USER_NULL */ Loading Loading @@ -779,6 +828,39 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { item.setTitle(sb); } /** * Set the menu item as disabled by admin by adding a restricted padlock at the end of the * text and set the click listener which will send an intent to show the admin support details * dialog. If the admin is null, remove the padlock and disabled color span. When the admin is * null, we also set the OnMenuItemClickListener to null, so if you want to set a custom * OnMenuItemClickListener, set it after calling this method. */ public static void setMenuItemAsDisabledByAdmin(final Context context, final MenuItem item, final EnforcingAdmin admin, final String restriction) { SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle()); removeExistingRestrictedSpans(sb); if (admin != null) { final int disabledColor = getColorAttrDefaultColor(context, android.R.attr.textColorHint); sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ImageSpan image = new RestrictedLockImageSpan(context); sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { sendShowAdminSupportDetailsIntent(context, admin, restriction); return true; } }); } else { item.setOnMenuItemClickListener(null); } item.setTitle(sb); } private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) { final int length = sb.length(); RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length, Loading
packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java +11 −0 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package com.android.settingslib; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.admin.EnforcingAdmin; import android.content.Context; import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.res.TypedArrayUtils; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceViewHolder; Loading Loading @@ -149,6 +151,15 @@ public class RestrictedPreference extends TwoTargetPreference implements } } /** * Sets the admin that disabled this preference. */ public void setDisabledByAdmin(@Nullable EnforcingAdmin admin) { if (mHelper.setDisabledByEnforcingAdmin(admin)) { notifyChanged(); } } public boolean isDisabledByAdmin() { return mHelper.isDisabledByAdmin(); } Loading
packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java +2 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.annotation.UserIdInt; import android.app.AlertDialog; import android.app.admin.EnforcingAdmin; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; Loading Loading @@ -217,7 +218,7 @@ public class InputMethodPreference extends PrimarySwitchPreference // This preference should also be disabled in case the admin does not allow this input // method. if (isAlwaysChecked) { setDisabledByAdmin(null); setDisabledByAdmin((EnforcingAdmin) null); setSwitchEnabled(false); } else if (!mIsAllowedByOrganization) { EnforcedAdmin admin = Loading
packages/SettingsLib/src/com/android/settingslib/supervision/SupervisionRestrictionsHelper.kt +37 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.settingslib.supervision import android.app.admin.DeviceAdminReceiver import android.app.admin.EnforcingAdmin import android.app.admin.RoleAuthority import android.app.role.RoleManager import android.app.supervision.SupervisionAppService import android.app.supervision.SupervisionManager import android.content.ComponentName Loading @@ -40,6 +43,37 @@ object SupervisionRestrictionsHelper { restriction: String, user: UserHandle, ): EnforcedAdmin? { if (!supervisionEnabled(context, user.identifier)) { return null } return EnforcedAdmin(getSupervisionComponent(context, user.identifier), restriction, user) } /** * Creates an instance of [EnforcingAdmin] that uses the correct supervision component or * returns null if supervision is not enabled. */ @JvmStatic fun createEnforcingAdmin(context: Context, user: UserHandle): EnforcingAdmin? { if (!supervisionEnabled(context, user.identifier)) { return null } val componentName = getSupervisionComponent(context, user.identifier) val packageName = componentName?.packageName ?: "" return EnforcingAdmin( packageName, RoleAuthority(setOf(RoleManager.ROLE_SYSTEM_SUPERVISION)), user, componentName, ) } private fun supervisionEnabled(context: Context, userId: Int): Boolean { val supervisionManager = context.getSystemService(SupervisionManager::class.java) return supervisionManager?.isSupervisionEnabledForUser(userId) == true } private fun getSupervisionComponent(context: Context, userId: Int): ComponentName? { val supervisionManager = context.getSystemService(SupervisionManager::class.java) val supervisionAppPackage = supervisionManager?.activeSupervisionAppPackage ?: return null var supervisionComponent: ComponentName? = null Loading @@ -49,7 +83,7 @@ object SupervisionRestrictionsHelper { context.packageManager.queryIntentServicesAsUser( Intent(SupervisionAppService.ACTION_SUPERVISION_APP_SERVICE), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, user.identifier, userId, ) resolveSupervisionApps .mapNotNull { it.serviceInfo?.componentName } Loading @@ -63,7 +97,7 @@ object SupervisionRestrictionsHelper { context.packageManager.queryBroadcastReceiversAsUser( Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, user.identifier, userId, ) resolveDeviceAdmins .mapNotNull { it.activityInfo?.componentName } Loading @@ -74,6 +108,6 @@ object SupervisionRestrictionsHelper { if (supervisionComponent == null) { Log.d(SupervisionLog.TAG, "Could not find the supervision component.") } return EnforcedAdmin(supervisionComponent, restriction, user) return supervisionComponent } }