diff options
author | Giulio Fiscella <fiscella@google.com> | 2023-01-24 18:08:06 +0000 |
---|---|---|
committer | Giulio Fiscella <fiscella@google.com> | 2023-01-25 14:08:45 +0000 |
commit | a89cb6b277c35e203677475c334f1a514936d4c3 (patch) | |
tree | 64e494efb5abfe8c198db14c116c9594b0d73868 | |
parent | ccb3bf318c4747e35519ce7f9a547bfb0346b7cc (diff) | |
download | Permission-a89cb6b277c35e203677475c334f1a514936d4c3.tar.gz |
Fix toggles when disallowed by admin
Copy the same behaviour used by top level tiles:
- Still display the toggle but with a different style so that the user
knows the current state of the sensor.
- Show a dialog to explain that the toggle is disabled by the device
owner when tapping on the toggle.
Relnote: Fix Safety Center quick setting toggles when disallowed by admin
Bug: 263364047
Test: manual
Change-Id: Ib2f66f8c77cb6898a2c733d26fa6aac5fb5444d1
2 files changed, 86 insertions, 26 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java index 4c48fbb59..e5dc3d59b 100644 --- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java @@ -26,6 +26,7 @@ import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID; import android.content.Context; import android.content.Intent; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Bundle; @@ -64,8 +65,11 @@ import com.android.permissioncontroller.safetycenter.ui.SafetyCenterTouchTarget; import com.android.permissioncontroller.safetycenter.ui.Sensor; import com.android.permissioncontroller.safetycenter.ui.model.LiveSafetyCenterViewModelFactory; import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterQsViewModel; +import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterQsViewModel.SensorState; import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterQsViewModelFactory; import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterViewModel; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.google.android.material.button.MaterialButton; @@ -562,7 +566,7 @@ public class SafetyCenterQsFragment extends Fragment { return layered; } - private void setSensorToggleState(Map<String, Boolean> sensorState, View rootView) { + private void setSensorToggleState(Map<String, SensorState> sensorStates, View rootView) { if (rootView == null) { if (getView() == null) { return; @@ -573,23 +577,36 @@ public class SafetyCenterQsFragment extends Fragment { } } - if (sensorState == null) { - sensorState = new ArrayMap<>(); + if (sensorStates == null) { + sensorStates = new ArrayMap<>(); } for (int i = 0; i < sToggleButtons.size(); i++) { View toggle = rootView.findViewById(sToggleButtons.valueAt(i)); String groupName = sToggleButtons.keyAt(i); + EnforcedAdmin admin = + sensorStates.containsKey(groupName) + ? sensorStates.get(groupName).getAdmin() + : null; + boolean sensorBlockedByAdmin = admin != null; if (!toggle.hasOnClickListeners()) { - toggle.setOnClickListener( - (v) -> { - mViewModel.toggleSensor(groupName); - mSafetyCenterViewModel - .getInteractionLogger() - .recordForSensor( - Action.PRIVACY_CONTROL_TOGGLE_CLICKED, - Sensor.fromPermissionGroupName(groupName)); - }); + if (sensorBlockedByAdmin) { + toggle.setOnClickListener( + (v) -> + startActivity( + RestrictedLockUtils.getShowAdminSupportDetailsIntent( + mContext, admin))); + } else { + toggle.setOnClickListener( + (v) -> { + mViewModel.toggleSensor(groupName); + mSafetyCenterViewModel + .getInteractionLogger() + .recordForSensor( + Action.PRIVACY_CONTROL_TOGGLE_CLICKED, + Sensor.fromPermissionGroupName(groupName)); + }); + } } TextView groupLabel = toggle.findViewById(R.id.toggle_sensor_name); @@ -601,16 +618,21 @@ public class SafetyCenterQsFragment extends Fragment { blockedStatus.setSelected(true); ImageView iconView = toggle.findViewById(R.id.toggle_sensor_icon); boolean sensorEnabled = - !sensorState.containsKey(groupName) || sensorState.get(groupName); + !sensorStates.containsKey(groupName) + || sensorStates.get(groupName).getEnabled(); Drawable icon; - int colorPrimary = getTextColor(true, sensorEnabled); - int colorSecondary = getTextColor(false, sensorEnabled); - if (sensorEnabled) { + boolean useEnabledBackground = sensorEnabled && !sensorBlockedByAdmin; + int colorPrimary = getTextColor(true, useEnabledBackground, sensorBlockedByAdmin); + int colorSecondary = getTextColor(false, useEnabledBackground, sensorBlockedByAdmin); + if (useEnabledBackground) { toggle.setBackgroundResource(R.drawable.safety_center_sensor_toggle_enabled); - icon = KotlinUtils.INSTANCE.getPermGroupIcon(mContext, groupName, colorPrimary); } else { toggle.setBackgroundResource(R.drawable.safety_center_sensor_toggle_disabled); + } + if (sensorEnabled) { + icon = KotlinUtils.INSTANCE.getPermGroupIcon(mContext, groupName, colorPrimary); + } else { icon = mContext.getDrawable(getBlockedIconResId(groupName)); icon.setTint(colorPrimary); } @@ -634,7 +656,7 @@ public class SafetyCenterQsFragment extends Fragment { } @ColorInt - private Integer getTextColor(boolean primary, boolean inverse) { + private int getTextColor(boolean primary, boolean inverse, boolean useLowerOpacity) { int primaryAttribute = inverse ? android.R.attr.textColorPrimaryInverse : android.R.attr.textColorPrimary; int secondaryAttribute = @@ -645,7 +667,20 @@ public class SafetyCenterQsFragment extends Fragment { TypedValue value = new TypedValue(); mContext.getTheme().resolveAttribute(attribute, value, true); int colorRes = value.resourceId != 0 ? value.resourceId : value.data; - return mContext.getColor(colorRes); + int color = mContext.getColor(colorRes); + if (useLowerOpacity) { + color = colorWithAdjustedAlpha(color, 0.5f); + } + return color; + } + + @ColorInt + private int colorWithAdjustedAlpha(@ColorInt int color, float factor) { + return Color.argb( + Math.round(Color.alpha(color) * factor), + Color.red(color), + Color.green(color), + Color.blue(color)); } private CharSequence getPermGroupLabel(String permissionGroup) { diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt index c7d838919..c19af8c8a 100644 --- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterQsViewModel.kt @@ -27,10 +27,12 @@ import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.hardware.SensorPrivacyManager import android.hardware.SensorPrivacyManager.Sensors +import android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE import android.location.LocationManager import android.os.Build import android.os.Process import android.os.UserHandle +import android.os.UserManager import android.permission.PermissionGroupUsage import android.provider.Settings import androidx.annotation.RequiresApi @@ -43,6 +45,8 @@ import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveD import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup import com.android.permissioncontroller.permission.utils.KotlinUtils import com.android.permissioncontroller.permission.utils.LocationUtils +import com.android.settingslib.RestrictedLockUtils +import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin import kotlin.collections.set @RequiresApi(Build.VERSION_CODES.TIRAMISU) @@ -56,6 +60,7 @@ class SafetyCenterQsViewModel( app.getSystemService(SensorPrivacyManager::class.java)!! private val locationManager: LocationManager = app.getSystemService(LocationManager::class.java)!! + private val userManager: UserManager = app.getSystemService(UserManager::class.java)!! val lightAppPermMap = mutableMapOf<LightAppPermissionGroupUsageKey, LightAppPermGroup?>() val revokedUsages = mutableSetOf<PermissionGroupUsage>() @@ -149,21 +154,27 @@ class SafetyCenterQsViewModel( fragment.startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS)) } - val sensorPrivacyLiveData: SmartUpdateMediatorLiveData<Map<String, Boolean>> = + data class SensorState(val enabled: Boolean, val admin: EnforcedAdmin?) + + val sensorPrivacyLiveData: SmartUpdateMediatorLiveData<Map<String, SensorState>> = object : - SmartUpdateMediatorLiveData<Map<String, Boolean>>(), + SmartUpdateMediatorLiveData<Map<String, SensorState>>(), SensorPrivacyManager.OnSensorPrivacyChangedListener, LocationUtils.LocationListener { override fun onUpdate() { - val cameraEnabled = !sensorPrivacyManager.isSensorPrivacyEnabled(Sensors.CAMERA) - val micEnabled = !sensorPrivacyManager.isSensorPrivacyEnabled(Sensors.MICROPHONE) val locationEnabled = locationManager.isLocationEnabledForUser(Process.myUserHandle()) + val locationEnforcedAdmin = + getEnforcedAdmin(UserManager.DISALLOW_SHARE_LOCATION) + ?: getEnforcedAdmin(UserManager.DISALLOW_CONFIG_LOCATION) value = mapOf( - CAMERA to cameraEnabled, - MICROPHONE to micEnabled, - LOCATION to locationEnabled) + CAMERA to + getSensorState(Sensors.CAMERA, UserManager.DISALLOW_CAMERA_TOGGLE), + MICROPHONE to + getSensorState( + Sensors.MICROPHONE, UserManager.DISALLOW_MICROPHONE_TOGGLE), + LOCATION to SensorState(locationEnabled, locationEnforcedAdmin)) } override fun onSensorPrivacyChanged(sensor: Int, enabled: Boolean) { @@ -190,6 +201,20 @@ class SafetyCenterQsViewModel( } } + private fun getSensorState(sensor: Int, restriction: String) = + SensorState( + !sensorPrivacyManager.isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor), + getEnforcedAdmin(restriction)) + + private fun getEnforcedAdmin(restriction: String) = + if (userManager + .getUserRestrictionSources(restriction, Process.myUserHandle()) + .isNotEmpty()) { + RestrictedLockUtils.getProfileOrDeviceOwner(app, Process.myUserHandle()) + } else { + null + } + fun navigateToManageService(fragment: Fragment, navigationIntent: Intent) { fragment.startActivity(navigationIntent) } |