diff --git a/core/api/current.txt b/core/api/current.txt index f9f80f15c72f8..03e29a7b7d6d8 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17705,6 +17705,15 @@ package android.hardware { method public void onDynamicSensorDisconnected(android.hardware.Sensor); } + public final class SensorPrivacyManager { + method public boolean supportsSensorToggle(int); + } + + public static class SensorPrivacyManager.Sensors { + field public static final int CAMERA = 2; // 0x2 + field public static final int MICROPHONE = 1; // 0x1 + } + public final class TriggerEvent { field public android.hardware.Sensor sensor; field public long timestamp; diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 73023d28e129c..d049ee722c1fd 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -2735,10 +2735,8 @@ package android.content.pm { field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES"; field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS"; field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio"; - field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle"; field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub"; field public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery"; - field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle"; field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow"; field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock"; field public static final String FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION = "android.hardware.telephony.ims.singlereg"; @@ -3119,12 +3117,7 @@ package android.hardware { } public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener { - method public void onSensorPrivacyChanged(boolean); - } - - public static class SensorPrivacyManager.Sensors { - field public static final int CAMERA = 2; // 0x2 - field public static final int MICROPHONE = 1; // 0x1 + method public void onSensorPrivacyChanged(int, boolean); } } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 5d51ff6142dc2..d8c138759cf05 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -835,10 +835,8 @@ package android.content.pm { method public void holdLock(android.os.IBinder, int); method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List); field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; - field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle"; field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption"; field public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec"; - field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle"; field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80 field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000 field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services"; @@ -1063,23 +1061,10 @@ package android.graphics.fonts { package android.hardware { public final class SensorPrivacyManager { - method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener); - method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener); - method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int); - method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener); method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(int, boolean); } - public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener { - method public void onSensorPrivacyChanged(boolean); - } - - public static class SensorPrivacyManager.Sensors { - field public static final int CAMERA = 2; // 0x2 - field public static final int MICROPHONE = 1; // 0x1 - } - } package android.hardware.biometrics { diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 67ecb7cb1b1ff..90105d394244a 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3653,32 +3653,6 @@ public abstract class PackageManager { @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_TUNER = "android.hardware.tv.tuner"; - /** - * Feature for {@link #getSystemAvailableFeatures} and - * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for - * microphone. When sensory privacy for the microphone is enabled no microphone data is sent to - * clients, e.g. all audio data is silent. - * - * @hide - */ - @SystemApi - @TestApi - @SdkConstant(SdkConstantType.FEATURE) - public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle"; - - /** - * Feature for {@link #getSystemAvailableFeatures} and - * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for - * camera. When sensory privacy for the camera is enabled no camera data is sent to clients, - * e.g. the view finder in a camera app would appear blank. - * - * @hide - */ - @SystemApi - @TestApi - @SdkConstant(SdkConstantType.FEATURE) - public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle"; - /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has * the necessary changes to support app enumeration. diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl index dbcd79dc5da27..a71bb09a19afa 100644 --- a/core/java/android/hardware/ISensorPrivacyManager.aidl +++ b/core/java/android/hardware/ISensorPrivacyManager.aidl @@ -24,6 +24,8 @@ interface ISensorPrivacyManager { // the ones in // frameworks/native/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl // =============== Beginning of transactions used on native side as well ====================== + boolean supportsSensorToggle(int sensor); + void addSensorPrivacyListener(in ISensorPrivacyListener listener); void addIndividualSensorPrivacyListener(int userId, int sensor, diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java index 85e7d77d93cd6..fc0204a55337e 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -16,6 +16,7 @@ package android.hardware; +import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -30,6 +31,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.service.SensorPrivacyIndividualEnabledSensorProto; import android.util.ArrayMap; +import android.util.Pair; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; @@ -43,23 +46,10 @@ import java.util.concurrent.Executor; * current state of sensor privacy as well as to register / unregister for notification when * the sensor privacy state changes. * - * @hide */ -@SystemApi -@TestApi @SystemService(Context.SENSOR_PRIVACY_SERVICE) public final class SensorPrivacyManager { - /** - * @hide - */ - public static final boolean USE_MICROPHONE_TOGGLE = true; - - /** - * @hide - */ - public static final boolean USE_CAMERA_TOGGLE = true; - /** * Unique Id of this manager to identify to the service * @hide @@ -80,25 +70,23 @@ public final class SensorPrivacyManager { public static final String EXTRA_ALL_SENSORS = SensorPrivacyManager.class.getName() + ".extra.all_sensors"; + private final SparseArray mToggleSupportCache = new SparseArray<>(); + /** * Individual sensors not listed in {@link Sensors} - * @hide */ - @SystemApi - @TestApi public static class Sensors { private Sensors() {} - /** Microphone - * @hide */ - @SystemApi - @TestApi + /** + * Constant for the microphone + */ public static final int MICROPHONE = SensorPrivacyIndividualEnabledSensorProto.MICROPHONE; - /** Camera - * @hide */ - @SystemApi - @TestApi + + /** + * Constant for the camera + */ public static final int CAMERA = SensorPrivacyIndividualEnabledSensorProto.CAMERA; /** @@ -122,14 +110,14 @@ public final class SensorPrivacyManager { * @hide */ @SystemApi - @TestApi public interface OnSensorPrivacyChangedListener { /** * Callback invoked when the sensor privacy state changes. * + * @param sensor the sensor whose state is changing * @param enabled true if sensor privacy is enabled, false otherwise. */ - void onSensorPrivacyChanged(boolean enabled); + void onSensorPrivacyChanged(int sensor, boolean enabled); } private static final Object sInstanceLock = new Object(); @@ -144,7 +132,11 @@ public final class SensorPrivacyManager { private final ISensorPrivacyManager mService; @NonNull - private final ArrayMap mListeners; + private final ArrayMap mListeners; + + @NonNull + private final ArrayMap, ISensorPrivacyListener> + mIndividualListeners; /** * Private constructor to ensure only a single instance is created. @@ -153,6 +145,7 @@ public final class SensorPrivacyManager { mContext = context; mService = service; mListeners = new ArrayMap<>(); + mIndividualListeners = new ArrayMap<>(); } /** @@ -176,52 +169,23 @@ public final class SensorPrivacyManager { } /** - * Sets sensor privacy to the specified state. - * - * @param enable the state to which sensor privacy should be set. - * - * @hide + * Checks if the given toggle is supported on this device + * @param sensor The sensor to check + * @return whether the toggle for the sensor is supported on this device. */ - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) - public void setSensorPrivacy(boolean enable) { + public boolean supportsSensorToggle(@Sensors.Sensor int sensor) { try { - mService.setSensorPrivacy(enable); + Boolean val = mToggleSupportCache.get(sensor); + if (val == null) { + val = mService.supportsSensorToggle(sensor); + mToggleSupportCache.put(sensor, val); + } + return val; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - /** - * Registers a new listener to receive notification when the state of sensor privacy - * changes. - * - * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor - * privacy changes. - * - * @hide - */ - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) - public void addSensorPrivacyListener(@NonNull final OnSensorPrivacyChangedListener listener) { - synchronized (mListeners) { - ISensorPrivacyListener iListener = mListeners.get(listener); - if (iListener == null) { - iListener = new ISensorPrivacyListener.Stub() { - @Override - public void onSensorPrivacyChanged(boolean enabled) { - listener.onSensorPrivacyChanged(enabled); - } - }; - mListeners.put(listener, iListener); - } - - try { - mService.addSensorPrivacyListener(iListener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - } - /** * Registers a new listener to receive notification when the state of sensor privacy * changes. @@ -233,8 +197,7 @@ public final class SensorPrivacyManager { * @hide */ @SystemApi - @TestApi - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, mContext.getUserId(), mContext.getMainExecutor(), @@ -252,7 +215,7 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @UserIdInt int userId, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, userId, mContext.getMainExecutor(), listener); @@ -270,8 +233,7 @@ public final class SensorPrivacyManager { * @hide */ @SystemApi - @TestApi - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener) { addSensorPrivacyListener(sensor, mContext.getUserId(), executor, listener); @@ -289,19 +251,19 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @UserIdInt int userId, @NonNull Executor executor, @NonNull OnSensorPrivacyChangedListener listener) { - synchronized (mListeners) { - ISensorPrivacyListener iListener = mListeners.get(listener); + synchronized (mIndividualListeners) { + ISensorPrivacyListener iListener = mIndividualListeners.get(listener); if (iListener == null) { iListener = new ISensorPrivacyListener.Stub() { @Override public void onSensorPrivacyChanged(boolean enabled) { - executor.execute(() -> listener.onSensorPrivacyChanged(enabled)); + executor.execute(() -> listener.onSensorPrivacyChanged(sensor, enabled)); } }; - mListeners.put(listener, iListener); + mIndividualListeners.put(new Pair<>(listener, sensor), iListener); } try { @@ -314,7 +276,7 @@ public final class SensorPrivacyManager { } /** - * Unregisters the specified listener from receiving notifications when the state of sensor + * Unregisters the specified listener from receiving notifications when the state of any sensor * privacy changes. * * @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when @@ -323,38 +285,23 @@ public final class SensorPrivacyManager { * @hide */ @SystemApi - @TestApi - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) { synchronized (mListeners) { - ISensorPrivacyListener iListener = mListeners.get(listener); - if (iListener != null) { - mListeners.remove(iListener); - try { - mService.removeSensorPrivacyListener(iListener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + for (int i = 0; i < mIndividualListeners.size(); i++) { + Pair pair = mIndividualListeners.keyAt(i); + if (pair.first.equals(listener)) { + try { + mService.removeSensorPrivacyListener(mIndividualListeners.valueAt(i)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + mIndividualListeners.removeAt(i--); } } } } - /** - * Returns whether sensor privacy is currently enabled. - * - * @return true if sensor privacy is currently enabled, false otherwise. - * - * @hide - */ - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) - public boolean isSensorPrivacyEnabled() { - try { - return mService.isSensorPrivacyEnabled(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - /** * Returns whether sensor privacy is currently enabled for a specific sensor. * @@ -363,8 +310,7 @@ public final class SensorPrivacyManager { * @hide */ @SystemApi - @TestApi - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) { return isSensorPrivacyEnabled(sensor, mContext.getUserId()); } @@ -376,7 +322,7 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor, @UserIdInt int userId) { try { return mService.isIndividualSensorPrivacyEnabled(userId, sensor); @@ -394,7 +340,7 @@ public final class SensorPrivacyManager { * @hide */ @TestApi - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable) { setSensorPrivacy(sensor, enable, mContext.getUserId()); } @@ -408,7 +354,7 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId) { try { @@ -428,7 +374,7 @@ public final class SensorPrivacyManager { * @hide */ @TestApi - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor, boolean enable) { setSensorPrivacyForProfileGroup(sensor, enable, mContext.getUserId()); @@ -444,7 +390,7 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor, boolean enable, @UserIdInt int userId) { try { @@ -463,7 +409,7 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void suppressSensorPrivacyReminders(@NonNull String packageName, boolean suppress) { suppressSensorPrivacyReminders(packageName, suppress, mContext.getUserId()); @@ -478,7 +424,7 @@ public final class SensorPrivacyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) public void suppressSensorPrivacyReminders(@NonNull String packageName, boolean suppress, @UserIdInt int userId) { try { @@ -488,4 +434,109 @@ public final class SensorPrivacyManager { throw e.rethrowFromSystemServer(); } } + + /** + * A class implementing this interface can register with the {@link + * android.hardware.SensorPrivacyManager} to receive notification when the all-sensor privacy + * state changes. + * + * @hide + */ + public interface OnAllSensorPrivacyChangedListener { + /** + * Callback invoked when the sensor privacy state changes. + * + * @param enabled true if sensor privacy is enabled, false otherwise. + */ + void onAllSensorPrivacyChanged(boolean enabled); + } + + /** + * Sets all-sensor privacy to the specified state. + * + * @param enable the state to which sensor privacy should be set. + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY) + public void setAllSensorPrivacy(boolean enable) { + try { + mService.setSensorPrivacy(enable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Registers a new listener to receive notification when the state of all-sensor privacy + * changes. + * + * @param listener the OnSensorPrivacyChangedListener to be notified when the state of + * all-sensor privacy changes. + * + * @hide + */ + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) + public void addAllSensorPrivacyListener( + @NonNull final OnAllSensorPrivacyChangedListener listener) { + synchronized (mListeners) { + ISensorPrivacyListener iListener = mListeners.get(listener); + if (iListener == null) { + iListener = new ISensorPrivacyListener.Stub() { + @Override + public void onSensorPrivacyChanged(boolean enabled) { + listener.onAllSensorPrivacyChanged(enabled); + } + }; + mListeners.put(listener, iListener); + } + + try { + mService.addSensorPrivacyListener(iListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Unregisters the specified listener from receiving notifications when the state of all-sensor + * privacy changes. + * + * @param listener the OnAllSensorPrivacyChangedListener to be unregistered from notifications + * when all-sensor privacy changes. + * + * @hide + */ + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) + public void removeAllSensorPrivacyListener( + @NonNull OnAllSensorPrivacyChangedListener listener) { + synchronized (mListeners) { + ISensorPrivacyListener iListener = mListeners.get(listener); + if (iListener != null) { + mListeners.remove(iListener); + try { + mService.removeSensorPrivacyListener(iListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + } + + /** + * Returns whether all-sensor privacy is currently enabled. + * + * @return true if all-sensor privacy is currently enabled, false otherwise. + * + * @hide + */ + @RequiresPermission(Manifest.permission.OBSERVE_SENSOR_PRIVACY) + public boolean isAllSensorPrivacyEnabled() { + try { + return mService.isSensorPrivacyEnabled(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index db536d3aaa4fe..a9b47aab4d182 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -24,7 +24,6 @@ import android.app.ActivityManager; import android.content.ComponentName; import android.content.pm.FeatureInfo; import android.content.pm.PackageManager; -import android.hardware.SensorPrivacyManager; import android.os.Build; import android.os.CarrierAssociatedAppEntry; import android.os.Environment; @@ -1245,14 +1244,6 @@ public class SystemConfig { addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0); } - if (SensorPrivacyManager.USE_MICROPHONE_TOGGLE) { - addFeature(PackageManager.FEATURE_MICROPHONE_TOGGLE, 0); - } - - if (SensorPrivacyManager.USE_CAMERA_TOGGLE) { - addFeature(PackageManager.FEATURE_CAMERA_TOGGLE, 0); - } - for (String featureName : mUnavailableFeatures) { removeFeature(featureName); } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index c2a7e079b1f9f..529aa6641c688 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4868,4 +4868,9 @@ + + + false + + false diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 402ea60cda354..78a794a35bba7 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4357,4 +4357,7 @@ + + + diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java index e05558598e00b..45c71744e0ec2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java @@ -16,7 +16,6 @@ package com.android.systemui.qs.tiles; -import static android.content.pm.PackageManager.FEATURE_CAMERA_TOGGLE; import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; import static com.android.systemui.DejankUtils.whitelistIpcs; @@ -63,7 +62,7 @@ public class CameraToggleTile extends SensorPrivacyToggleTile { @Override public boolean isAvailable() { - return getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE) + return mSensorPrivacyController.supportsSensorToggle(CAMERA) && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "camera_toggle_enabled", true)); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java index 9c01bb9cc1fdf..48a1ad673d763 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java @@ -16,7 +16,6 @@ package com.android.systemui.qs.tiles; -import static android.content.pm.PackageManager.FEATURE_MICROPHONE_TOGGLE; import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; import static com.android.systemui.DejankUtils.whitelistIpcs; @@ -63,8 +62,7 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile { @Override public boolean isAvailable() { - return getHost().getContext().getPackageManager() - .hasSystemFeature(FEATURE_MICROPHONE_TOGGLE) + return mSensorPrivacyController.supportsSensorToggle(MICROPHONE) && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "mic_toggle_enabled", true)); 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 3d9c2721e7a8a..f13576c2d4cc4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java @@ -49,7 +49,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl + if (!isBlocked) { + dismiss() + } } } 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 4e6db40d78edb..d7d1e737661e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java @@ -22,6 +22,8 @@ public interface IndividualSensorPrivacyController extends CallbackController { void init(); + boolean supportsSensorToggle(@Sensor int sensor); + boolean isSensorBlocked(@Sensor int sensor); void setSensorBlocked(@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 beb4b44323a5c..f58a7c030b806 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java @@ -45,12 +45,17 @@ public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPr public void init() { for (int sensor : SENSORS) { mSensorPrivacyManager.addSensorPrivacyListener(sensor, - (enabled) -> onSensorPrivacyChanged(sensor, enabled)); + (s, enabled) -> onSensorPrivacyChanged(sensor, enabled)); mState.put(sensor, mSensorPrivacyManager.isSensorPrivacyEnabled(sensor)); } } + @Override + public boolean supportsSensorToggle(int sensor) { + return mSensorPrivacyManager.supportsSensorToggle(sensor); + } + @Override public boolean isSensorBlocked(@Sensor int sensor) { return mState.get(sensor, false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java index a2334f3a23d6e..6f659c1f2af56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.policy; -import android.content.Context; import android.hardware.SensorPrivacyManager; import androidx.annotation.NonNull; @@ -26,14 +25,12 @@ import com.android.systemui.dagger.SysUISingleton; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - /** * Controls sensor privacy state and notification. */ @SysUISingleton public class SensorPrivacyControllerImpl implements SensorPrivacyController, - SensorPrivacyManager.OnSensorPrivacyChangedListener { + SensorPrivacyManager.OnAllSensorPrivacyChangedListener { private SensorPrivacyManager mSensorPrivacyManager; private final List mListeners = new ArrayList<>(1); private Object mLock = new Object(); @@ -48,8 +45,8 @@ public class SensorPrivacyControllerImpl implements SensorPrivacyController, @Override public void init() { - mSensorPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(); - mSensorPrivacyManager.addSensorPrivacyListener(this); + mSensorPrivacyEnabled = mSensorPrivacyManager.isAllSensorPrivacyEnabled(); + mSensorPrivacyManager.addAllSensorPrivacyListener(this); } /** @@ -83,7 +80,7 @@ public class SensorPrivacyControllerImpl implements SensorPrivacyController, /** * Callback invoked by the SensorPrivacyService when sensor privacy state changes. */ - public void onSensorPrivacyChanged(boolean enabled) { + public void onAllSensorPrivacyChanged(boolean enabled) { synchronized (mLock) { mSensorPrivacyEnabled = enabled; for (OnSensorPrivacyChangedListener listener : mListeners) { diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index e8bc812e5ea88..cd3dca90b39b3 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -743,6 +743,16 @@ public final class SensorPrivacyService extends SystemService { } } + @Override + public boolean supportsSensorToggle(int sensor) { + if (sensor == MICROPHONE) { + return mContext.getResources().getBoolean(R.bool.config_supportsMicToggle); + } else if (sensor == CAMERA) { + return mContext.getResources().getBoolean(R.bool.config_supportsCamToggle); + } + throw new IllegalArgumentException("Unable to find value " + sensor); + } + /** * Registers a listener to be notified when the sensor privacy state changes. */ diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index a55605ed3c15e..098ce7cd137ca 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -846,8 +846,8 @@ public class AudioService extends IAudioService.Stub mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator(); - mSupportsMicPrivacyToggle = mContext.getPackageManager() - .hasSystemFeature(PackageManager.FEATURE_MICROPHONE_TOGGLE); + mSupportsMicPrivacyToggle = context.getSystemService(SensorPrivacyManager.class) + .supportsSensorToggle(SensorPrivacyManager.Sensors.MICROPHONE); // Initialize volume // Priority 1 - Android Property