传感器已关闭

在飞行模式下,设备仍可以访问某些传感器以启用特定功能,如屏幕旋转和拍照。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

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

常见问题

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

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

传感器行为

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

相机

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

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

麦克风

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

如果应用在已启用传感器已关闭的情况下尝试访问麦克风,麦克风就会以静默状态返回。

Sensor

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

  • 连续传感器:处于此报告模式下的传感器会停止调度事件。如果应用在已启用传感器已关闭的情况下与连续传感器互动,在停用该功能之前,传感器不会向应用发送任何其他数据。
  • 刷新事件:启用该图块后可以请求传感器刷新,系统会调用 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 安装一个可以读取并显示设备所有传感器的应用即可。在启用传感器已关闭图块后,请确保传感器的任何值都不会产生变化,麦克风音频处于静音状态,且摄像头无法访问。