传感器已关闭

在飞行模式下,设备仍可以访问某些传感器以启用特定功能,比如屏幕旋转和拍照。Android 10 提供了一个开发者选项设置,用于关闭设备中的所有传感器。此功能可帮助开发者在这些传感器不可用的情况下测试其应用的功能,也为用户提供了控制其设备中的传感器的方法。

当开发者或用户在开发者选项(设置 > 系统 > 开发者选项 > 快捷设置开发者图块)中启用传感器已关闭时,快捷设置面板中便会出现一个新的图块。他们可以使用该图块来阻止应用访问摄像头、麦克风和由 SensorManager 类管理的所有传感器。

实现

Android 10 中包含一个用于处理摄像头、麦克风和 SensorManager 传感器的参考实现。管理传感器已关闭状态并向客户端传达状态变更的系统服务位于 frameworks/base/services/core/java/com/android/server/SensorPrivacyService.java。便于在应用上下文中访问 SensorPrivacyService 的管理器位于 frameworks/base/core/java/android/hardware/SensorPrivacyManager.java

如果您的设备使用 SensorServiceCameraServiceAudioPolicyService 的默认实现,则无需对参考设计进行额外的自定义。如果您有其他传感器,请参阅自定义,详细了解如何支持此功能。

常见问题

在实现此功能时,当系统首次尝试获取摄像头和当摄像头不再可用时,相机应用有时无法正确响应 onError 回调。如果启用此图块,这通常会导致应用崩溃,但它可以作为一个信号,表明该功能的行为符合预期。

此行为表明应用没有正确处理 onError 回调(CameraDevice.StateCallback 中)。启用传感器已关闭后,系统会调用 onError 回调,并将 CameraDevice.StateCallback.ERROR_CAMERA_DISABLED 设置为错误值。请更新所有第一方应用以使用此值处理 onError 回调,具体方法为:在对 openCamera 成功进行后续调用之前,不对 CameraDevice 进行任何后续调用。

传感器行为

启用传感器已关闭后,传感器将停止向系统或应用报告任何数据。启用传感器已关闭后,应用仍可以请求传感器和注册监听器,但结果要么是对麦克风返回静音,要么是永远不对传感器调用 onSensorChanged 回调。一旦停用该图块,这些监听器便会开始从麦克风接收实际输出或者对 onSensorChanged 发出预期的回调,而无需您执行任何其他操作。静默传感器的默认行为如下所述。

摄像头

如果应用在已启用传感器已关闭的情况下使用摄像头,则系统会向 onError 回调方法发送一条错误消息,并关闭 CameraDevice

如果应用在已启用传感器已关闭的情况下尝试访问摄像头,则系统会向 onError 回调方法发送一条错误消息。

麦克风

启用传感器已关闭后,应用仍可以访问麦克风,但仅会返回静音。如果应用在已启用传感器已关闭的情况下使用麦克风,则不会生成任何错误,但录音会处于静音状态,并且仅会返回一个全零数组。如果在应用仍使用麦克风的情况下停用传感器已关闭,则会返回预期的音频数据。

如果应用在已启用传感器已关闭的情况下尝试访问麦克风,则麦克风将返回静音。

传感器

如果应用在已启用传感器已关闭的情况下尝试访问其他传感器,传感器类型会影响默认行为:

  • 连续传感器:处于此报告模式下的传感器会停止调度事件。如果应用在已启用传感器已关闭的情况下与连续传感器互动,则在停用该功能之前,传感器不会向应用发送任何其他数据。
  • 刷新事件:启用图块后可以请求传感器刷新,系统会调用 onFlushComplete 回调以表明请求的刷新已成功完成,但不会生成带有传感器数据的任何新事件并返回到 onSensorChanged 回调。
  • 变化时事件:启用传感器已关闭后,将不会报告新的变更事件。
  • 触发事件:启用传感器已关闭后,将会停止生成触发事件。任何现有的事件都将完成。

自定义

如果您的设备使用 SensorServiceCameraServiceAudioPolicyService 的默认实现,则无需对参考设计进行额外的自定义。但是,您可以支持在 SensorManager 外部管理的传感器,从设备中移除传感器已关闭,或者更改开发者快速设置图块的系统界面或传感器已关闭图块的图标。

支持更多的传感器

如果您的设备包含在 SensorManager 外部管理的传感器,则您应使用 SensorPrivacyServiceSensorPrivacyManager 为其添加支持。

切换过传感器已关闭图块后,SensorPrivacyService 会为所有已注册的监听器调用单程回调。收到此回调后,已注册的监听器可以根据图块状态采取必要的步骤。如果已启用“传感器已关闭”,则系统会终止所有现有的连接并返回空数据,此外还会设置一个标记来阻止新连接。如果停用“传感器已关闭”,则可以重置该标记以允许新连接。以摄像头服务 (platform/frameworks/av/services/camera/libcameraservice/) 为例,可遵循以下步骤来添加对新传感器的支持。

  1. 实现 BnSensorPrivacyListener 接口。如需了解详情,请参阅 CameraService.h 中的 SensorPrivacyPolicy
  2. 注册 SensorPrivacyManager 并在启动时获取图块的状态。如需了解详情,请参阅 CameraService.cpp 中的 SensorPrivacyPolicy::registerSelf
  3. 处理回调中传感器已关闭的状态变更。如需了解详情,请参阅 CameraService.cpp 中的 SensorPrivacyPolicy::onSensorPrivacyChangedCameraService::blockAllClients
  4. 启用该图块后,禁止访问传感器数据。如需了解详情,请参阅 CameraService.cppCameraService::validateClientPermissionsLocked 中的传感器隐私权政策检查项。

移除“传感器已关闭”

作为用于测试的开发者工具,传感器已关闭处于隐藏状态,因为用户必须首先启用开发者模式,然后才能选择使该图块在“设置”中可用。

如果您不希望设备支持传感器已关闭,则可以从 packages/apps/Settings/AndroidManifest.xml 移除该服务标签。移除后,传感器已关闭图块将无法在开发者快捷设置图块页面中启用。

更改“传感器已关闭”界面

可以为传感器已关闭界面自定义两个元素:针对开发者快捷设置图块显示的图标,以及该图块启用后在状态栏中显示的图标。要自定义这些图标的外观,请替换以下文件:

  • 快捷设置图块图标:packages/apps/Settings/res/drawable/tile_icon_sensors_off.xml
  • 状态栏图标:frameworks/base/packages/SystemUI/res/drawable/stat_sys_sensors_off.xml

验证

此功能作为可选的开发者工具,因此不存在有针对性的 CTS 测试。

您可以手动测试,只需通过 Google Play 安装一个可以读取并显示设备所有传感器的应用即可。在启用传感器已关闭图块后,请确保传感器的任何值都不会产生变化,麦克风音频处于静音状态,且无法访问摄像头。