diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl index a392afdacbcbc..9cf329ca3d3de 100644 --- a/core/java/android/hardware/ISensorPrivacyManager.aidl +++ b/core/java/android/hardware/ISensorPrivacyManager.aidl @@ -50,5 +50,7 @@ interface ISensorPrivacyManager { void suppressToggleSensorPrivacyReminders(int userId, int sensor, IBinder token, boolean suppress); + boolean requiresAuthentication(); + void showSensorUseDialog(int sensor); } \ No newline at end of file diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java index 0460e5831e33f..99b58c97dc93d 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -327,6 +327,8 @@ public final class SensorPrivacyManager { @NonNull private boolean mToggleListenerRegistered = false; + private Boolean mRequiresAuthentication = null; + /** * Private constructor to ensure only a single instance is created. */ @@ -760,6 +762,23 @@ public final class SensorPrivacyManager { } } + /** + * @return whether the device is required to be unlocked to change software state. + * + * @hide + */ + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) + public boolean requiresAuthentication() { + if (mRequiresAuthentication == null) { + try { + mRequiresAuthentication = mService.requiresAuthentication(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return mRequiresAuthentication; + } + /** * If sensor privacy for the provided sensor is enabled then this call will show the user the * dialog which is shown when an application attempts to use that sensor. If privacy isn't diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b23d8cab74d4d..dad43f05b7b12 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5444,6 +5444,8 @@ false true + + true diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 21b2351046947..a61b9083eb4ae 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4662,6 +4662,7 @@ + diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java index f4dd415cb6787..d99c1d1daf7eb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java @@ -92,15 +92,15 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl { - mSensorPrivacyController.setSensorBlocked(QS_TILE, getSensorId(), - !mSensorPrivacyController.isSensorBlocked(getSensorId())); - }); + boolean blocked = mSensorPrivacyController.isSensorBlocked(getSensorId()); + if (mSensorPrivacyController.requiresAuthentication() + && mKeyguard.isMethodSecure() + && mKeyguard.isShowing()) { + mActivityStarter.postQSRunnableDismissingKeyguard(() -> + mSensorPrivacyController.setSensorBlocked(QS_TILE, getSensorId(), !blocked)); return; } - mSensorPrivacyController.setSensorBlocked(QS_TILE, getSensorId(), - !mSensorPrivacyController.isSensorBlocked(getSensorId())); + mSensorPrivacyController.setSensorBlocked(QS_TILE, getSensorId(), !blocked); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt index dae375ad7cc7e..2d1d8b75b1bc7 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt @@ -134,7 +134,9 @@ class SensorUseStartedActivity @Inject constructor( override fun onClick(dialog: DialogInterface?, which: Int) { when (which) { BUTTON_POSITIVE -> { - if (keyguardStateController.isMethodSecure && keyguardStateController.isShowing) { + if (sensorPrivacyController.requiresAuthentication() && + keyguardStateController.isMethodSecure && + keyguardStateController.isShowing) { keyguardDismissUtil.executeWhenUnlocked({ bgHandler.postDelayed({ disableSensorPrivacy() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java index 1e73d593c8de1..eb08f37503c60 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java @@ -37,6 +37,11 @@ public interface IndividualSensorPrivacyController extends void suppressSensorPrivacyReminders(int sensor, boolean suppress); + /** + * @return whether lock screen authentication is required to change the toggle state + */ + boolean requiresAuthentication(); + interface Callback { void onSensorBlockedChanged(@Sensor int sensor, boolean blocked); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java index e4c444da5da9f..fffd839fcf11b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java @@ -37,6 +37,7 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr private final @NonNull SensorPrivacyManager mSensorPrivacyManager; private final SparseBooleanArray mSoftwareToggleState = new SparseBooleanArray(); private final SparseBooleanArray mHardwareToggleState = new SparseBooleanArray(); + private Boolean mRequiresAuthentication; private final Set mCallbacks = new ArraySet<>(); public IndividualSensorPrivacyControllerImpl( @@ -95,6 +96,11 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr mSensorPrivacyManager.suppressSensorPrivacyReminders(sensor, suppress); } + @Override + public boolean requiresAuthentication() { + return mSensorPrivacyManager.requiresAuthentication(); + } + @Override public void addCallback(@NonNull Callback listener) { mCallbacks.add(listener); diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java index 08344170b02da..3c779f387673d 100644 --- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java +++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java @@ -727,7 +727,8 @@ public final class SensorPrivacyService extends SystemService { return false; } - if (mKeyguardManager != null && mKeyguardManager.isDeviceLocked(userId)) { + if (requiresAuthentication() && mKeyguardManager != null + && mKeyguardManager.isDeviceLocked(userId)) { Log.i(TAG, "Can't change mic/cam toggle while device is locked"); return false; } @@ -992,6 +993,13 @@ public final class SensorPrivacyService extends SystemService { } } + @Override + public boolean requiresAuthentication() { + enforceObserveSensorPrivacyPermission(); + return mContext.getResources() + .getBoolean(R.bool.config_sensorPrivacyRequiresAuthentication); + } + @Override public void showSensorUseDialog(int sensor) { if (Binder.getCallingUid() != Process.SYSTEM_UID) {