在飞行模式下,设备仍然可以访问某些传感器以启用特定功能,例如屏幕旋转和拍照。Android 10 提供了一个开发者选项设置来关闭设备中的所有传感器。此功能可帮助开发者在传感器不可用的情况下测试其应用的功能,并为用户提供了一种控制设备中传感器的方法。
当开发者或用户在开发者选项中启用传感器关闭时(设置 > 系统 > 开发者选项 > 快速设置开发者图块),快速设置托盘中会出现一个新的图块。他们可以使用该图块来阻止应用访问相机、麦克风以及由 SensorManager
类管理的所有传感器。
警告:此选项仅影响通过 `SensorService`、`CameraService` 和 `AudioPolicyService` 访问传感器的应用。电话功能不使用 `AudioPolicyService`,并且在通话期间仍然可以访问麦克风。
实现
Android 10 包含一个参考实现,用于处理相机、麦克风和 SensorManager
传感器。管理传感器关闭状态并通知客户端状态更改的系统服务位于 frameworks/base/services/core/java/com/android/server/SensorPrivacyService.java
中。促进在应用的上下文中访问 SensorPrivacyService
的管理器位于 frameworks/base/core/java/android/hardware/SensorPrivacyManager.java
中。
如果您的设备使用 SensorService
、CameraService
和 AudioPolicyService
的默认实现,则无需对参考设计进行额外的自定义。如果您有其他传感器,请参阅自定义,详细了解如何支持此功能。
常见问题
在实现此功能时,有时相机应用无法正确响应 onError
回调,无论是在首次尝试获取相机时还是在相机不再可用时。这通常会导致在启用此图块时应用崩溃,但这可以用作指示该功能按预期运行的信号。
此行为表明应用未正确处理 CameraDevice.StateCallback
中的 onError
回调。当传感器关闭启用时,将使用设置为错误值的 CameraDevice.StateCallback.ERROR_CAMERA_DISABLED
调用 onError
回调。更新任何第一方应用以处理带有此值的 onError
回调,方法是在后续 openCamera
调用成功之前,不对 CameraDevice
进行任何后续调用。
传感器行为
当传感器关闭启用时,传感器停止向系统或应用报告任何数据。应用仍然可以请求传感器并在传感器关闭启用时注册监听器,但麦克风会返回静音,或者永远不会为传感器调用 onSensorChanged
回调。一旦禁用该图块,这些相同的监听器将开始接收来自麦克风的实际输出或对 onSensorChanged
的预期回调,而无需执行任何额外的工作。静音传感器的默认行为如下所示。
相机
如果应用在传感器关闭启用时正在使用相机,则会向 onError
回调方法发送错误,并且 CameraDevice
会关闭。
如果应用在传感器关闭启用时尝试访问相机,则会向 onError
回调方法发送错误。
麦克风
当 传感器关闭 启用后,仍然可以访问麦克风,但只会返回静音。如果当 传感器关闭 启用时应用正在使用麦克风,则不会生成错误,但录音将被静音,并且仅返回一个零数组。如果在应用仍在使用麦克风时禁用 传感器关闭,则会返回预期的音频数据。
如果应用尝试在 传感器关闭 启用时访问麦克风,麦克风将返回静音。
传感器
当应用尝试在 传感器关闭 启用时访问其他传感器时,传感器类型会影响默认行为
- 持续传感器: 处于此报告模式的传感器会停止分发事件。如果当 传感器关闭 启用时应用正在与持续传感器交互,则该传感器不会向应用发送任何额外数据,直到该功能被禁用。
- 刷新事件: 当磁贴启用时,可以请求传感器刷新,并且会调用
onFlushComplete
回调来指示请求的刷新已成功完成,但是不会生成新的带有传感器数据的事件并返回到onSensorChanged
回调。 - 变化事件: 当 传感器关闭 启用时,不会报告新的变化事件。
- 触发事件: 当 传感器关闭 启用时,触发事件停止生成。任何现有事件都会完成。
自定义
如果您的设备使用 SensorService
、CameraService
和 AudioPolicyService
的默认实现,则参考设计不需要额外的自定义。但是,您可以支持在 SensorManager
之外管理的传感器,从您的设备中移除 传感器关闭,或者更改开发者快速设置磁贴的系统 UI 或 传感器关闭 磁贴的图标。
支持更多传感器
如果您的设备包含在 SensorManager
之外管理的传感器,则应使用 SensorPrivacyService
和 SensorPrivacyManager
为它们添加支持。
当 传感器关闭 磁贴被切换时,SensorPrivacyService
会为所有注册的监听器调用单向回调。当收到此回调时,注册的监听器可以根据磁贴的状态采取必要的步骤。如果启用,则可以终止所有现有连接并返回空数据,并设置标志以阻止新连接。如果禁用,则可以重置标志以允许新连接。以相机服务(platform/frameworks/av/services/camera/libcameraservice/
)为例,请按照以下步骤添加对新传感器的支持。
- 实现
BnSensorPrivacyListener
接口。有关更多详细信息,请参阅CameraService.h
中的SensorPrivacyPolicy
,地址为CameraService.h
。 - 向
SensorPrivacyManager
注册并在启动时获取磁贴的状态。有关更多详细信息,请参阅CameraService.cpp
中的SensorPrivacyPolicy::registerSelf
,地址为CameraService.cpp
。 - 在回调中处理 传感器关闭 状态更改。有关更多详细信息,请参阅
CameraService.cpp
中的SensorPrivacyPolicy::onSensorPrivacyChanged
和CameraService::blockAllClients
,地址为CameraService.cpp
。 - 当磁贴启用时,阻止访问传感器数据。有关更多详细信息,请参阅
CameraService.cpp
中的CameraService::validateClientPermissionsLocked
中的传感器隐私策略检查,地址为CameraService.cpp
。
移除传感器关闭
作为用于测试的开发者工具,传感器关闭 是隐藏的,因为用户必须首先启用开发者模式,然后选择在设置中启用该磁贴。
如果您不想在设备上支持 传感器关闭,请从 packages/apps/Settings/AndroidManifest.xml
中移除 service 标签。如果您移除 service 标签,则无法从开发者快速设置磁贴页面启用 传感器关闭 磁贴。
更改传感器关闭 UI
传感器关闭 UI 有两个可以自定义的元素:开发者快速设置磁贴显示的图标和磁贴启用时状态栏中显示的图标。要自定义这些图标的外观,请替换以下文件
- 快速设置磁贴图标:
packages/apps/Settings/res/drawable/tile_icon_sensors_off.xml
- 状态栏图标:
frameworks/base/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml
验证
作为一个可选的开发者工具,此功能没有 CTS 测试。
您可以通过从 Google Play 安装一个读取和显示设备所有传感器的应用来手动测试。当您启用 传感器关闭 磁贴时,请确保传感器的所有值均未更改,麦克风音频为静音,并且相机不可访问。