聊一聊豆包AI手机助手高度敏感权限CAPTURE_SECURE_VIDEO_OUTPUT

背景:

近来手机界最火爆的话题莫过于豆包手机助手
https://o.doubao.com/在这里插入图片描述

很多博主拿到豆包手机后也开始对豆包手机助手进行一系列的实现原理调研和猜想,比如调研时候就涉及几个我们系统fw和应用开发中常用的一些权限,CAPTURE_SECURE_VIDEO_OUTPUT(录取屏幕数据),INJECT_EVENTS(注入相关输入事件)。
其实这两个权限在我们投屏专题和input专题课程都有介绍过,不过课程讲解抓取屏幕权限那时候是CAPTURE_VIDEO_OUTPUT权限,而豆包用的是CAPTURE_SECURE_VIDEO_OUTPUT多了一个SECURE,那么这里的权限CAPTURE_SECURE_VIDEO_OUTPUT到底能用来干什么呢?

下面来详细剖析一下这个CAPTURE_SECURE_VIDEO_OUTPUT权限。

CAPTURE_SECURE_VIDEO_OUTPUT权限介绍

CAPTURE_SECURE_VIDEO_OUTPUT权限添加:

    <uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />

对应权限的定义:
frameworks/base/core/res/AndroidManifest.xml



      <!-- Allows an application to capture video output.
         <p>Not for use by third-party applications.</p>
          @hide
          @removed -->
    <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
        android:protectionLevel="signature" />

    <!-- Allows an application to capture secure video output.
         <p>Not for use by third-party applications.</p>
          @hide
          @removed -->
    <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
        android:protectionLevel="signature" />

官方注释解释:
允许一个app可以抓取安全级别的视频内容,这个权限不是给第三方app用的,是需要系统签名的权限,保护级别也是android:protectionLevel=“signature”。
其实只看这个权限了解的话,大家还是会感觉比较空,只能理解到字面意思就是可以抓取安全级别的视频内容,所以要全面了解只看这一点注释还远远不够。
首先疑问就是什么是安全级别内容?有现实的案例来说明么,开发过程中哪些画面界面就是要设置这个安全级别内容。

安全Activity画面如何设置

当一个窗口被标记为 FLAG_SECURE 后,系统会认为它包含敏感内容,从而阻止或限制以下行为:

禁止常规截屏(包括adb shell screencap命令和大多数手机自带的截屏功能)。

禁止录屏(包括系统录屏工具和大多数录屏App)。

防止内容出现在不安全的显示输出上,例如通过MediaProjection API投屏、录屏,或显示在非受信的外部显示器上。
比如涉及到场景为:密码输入,手势输入,银行App登录、账户总览、交易密码输入、支付确认、付款二维码/条形码(包含金额)

实际案例
这里就以手机的手势设置画面来进行代码剖析。
按如下路径进行操作:
设置app —》 安全与隐私 —》设置锁屏 —》 手势密码设置
在这里插入图片描述

那么看看这个手势密码设置画面的详细情况,Activity画面在onCreate时候就把Activity设置成了FLAG_SECURE
在这里插入图片描述下面看看这个FLAG_SECURE
frameworks/base/core/java/android/view/WindowManager.java

    /** Window flag: treat the content of the window as secure, preventing
         * it from appearing in screenshots or from being viewed on non-secure
         * displays.
         *
         * <p>See {@link android.view.Display#FLAG_SECURE} for more details about
         * secure surfaces and secure displays.
         */
        public static final int FLAG_SECURE             = 0x00002000;

注释也比较详细,可以看出主要是把window的内容变成安全的,防止window内容展示在截图,或者不安全的display中(比如常见投屏录屏的虚拟屏)。

dumpsys SurfaceFlinger后查看相关输出如下:
在这里插入图片描述可以看到这里的ChooseLockPattern的Activity对应Layer实际上isSecure为true

在这里插入图片描述
如果没有额外特别设置,则一般 isSecure=false。

* Layer 0x735dc3562330 (2ed9211 com.android.settings/com.android.settings.SubSettings#355)
      isSecure=false geomUsesSourceCrop=false geomBufferUsesDisplayInverseTransform=false geomLayerTransform (ROT_0) (IDENTITY)

那么上面也一直强调说不安全的display的,那么display的是否安全又是靠啥标识和控制呢?
这里接下来就需要看Display创建时候的对应flag了。

VIRTUAL_DISPLAY_FLAG_SECURE的Flag介绍:

创建虚拟屏幕这块已经在投屏课程有深入讲解,也有对这些flag进行剖析,这里主要看看VIRTUAL_DISPLAY_FLAG_SECURE这个flag的讲解。

frameworks/base/core/java/android/hardware/display/DisplayManager.java

    /**
     * Virtual display flag: Create a secure display.
     *
     * <h3>Secure virtual displays</h3>
     * <p>
     * When this flag is set, the virtual display is considered secure as defined
     * by the {@link Display#FLAG_SECURE} display flag.  The caller promises to take
     * reasonable measures, such as over-the-air encryption, to prevent the contents
     * of the display from being intercepted or recorded on a persistent medium.
     * </p><p>
     * Creating a secure virtual display requires the CAPTURE_SECURE_VIDEO_OUTPUT permission.
     * This permission is reserved for use by system components and is not available to
     * third-party applications.
     * </p>
     *
     * <h3>Non-secure virtual displays</h3>
     * <p>
     * When this flag is not set, the virtual display is considered unsecure.
     * The content of secure windows will be blanked if shown on this display.
     * </p>
     *
     * @see Display#FLAG_SECURE
     * @see #createVirtualDisplay
     */
    public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2;

frameworks/base/core/java/android/view/Display.java

    /**
     * Display flag: Indicates that the display has a secure video output and
     * supports compositing secure surfaces.
     * <p>
     * If this flag is set then the display device has a secure video output
     * and is capable of showing secure surfaces.  It may also be capable of
     * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}.
     * </p><p>
     * If this flag is not set then the display device may not have a secure video
     * output; the user may see a blank region on the screen instead of
     * the contents of secure surfaces or protected buffers.
     * </p><p>
     * Secure surfaces are used to prevent content rendered into those surfaces
     * by applications from appearing in screenshots or from being viewed
     * on non-secure displays.  Protected buffers are used by secure video decoders
     * for a similar purpose.
     * </p><p>
     * An application creates a window with a secure surface by specifying the
     * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag.
     * Likewise, an application creates a {@link SurfaceView} with a secure surface
     * by calling {@link SurfaceView#setSecure} before attaching the secure view to
     * its containing window.
     * </p><p>
     * An application can use the absence of this flag as a hint that it should not create
     * secure surfaces or protected buffers on this display because the content may
     * not be visible.  For example, if the flag is not set then the application may
     * choose not to show content on this display, show an informative error message,
     * select an alternate content stream or adopt a different strategy for decoding
     * content that does not rely on secure surfaces or protected buffers.
     * </p>
     *
     * @see #getFlags
     */
    public static final int FLAG_SECURE = 1 << 1;

VIRTUAL_DISPLAY_FLAG_SECURE这个flag就是用来创建一个安全的虚拟屏幕,在创建虚拟屏时候设置了这个标志位后,对应的Display对象的flag就会带上FLAG_SECURE,带有安全的标志的屏幕就可以展示上面isSecure=true的Layer,但是创建这样一个secure的Display是需要有CAPTURE_SECURE_VIDEO_OUTPUT权限的,这个权限对第三方app不可以用。

如果没有VIRTUAL_DISPLAY_FLAG_SECURE创建非安全的Display是无法展示那些安全的要求Layer,所以一般我们看到现象就是一篇黑。这也就是可以解释支付一些界面无法截图,或者截图后是一片黑的现象。

Activity设置FLAG_SECURE后普通scrcpy展示情况:

下面看看scrcpy默认情况下(关于scrcpy相关原理内容去看马哥投屏专题),展示手势密码设置界面情况如下:

默认scrcpy的虚拟屏未设置FLAG_SECURE

在这里插入图片描述dumpsys display看看相关display情况结果如下:
在这里插入图片描述
可以看出完全scrcpy的虚拟屏幕没有FLAG_SECURE的安全flag,所以自然无法展示出有secure为true的Layer。

设置FLAG_SECURE
具体设置的方法大概就是,调用DisplayManager的createVirtualDisplay时候传递flag要或上FLAG_SECURE这个掩码,具体在投屏课程也有demo。
在这里插入图片描述

成功后效果如下:

在这里插入图片描述
对应的dumpsys display看看scrcpy虚拟屏幕情况:
在这里插入图片描述

总结

上面有讲到权限,虚拟屏幕创建Display,app创建对于secure的Layer,下面总结一下他们关系:

1、应用通过Secure的flag创建Secure Layer,应用将帧数据绘制到Secure Layer。

2、SurfaceFlinger进行合成,它看到该Secure Layer的目标Display具有FLAG_SECURE。

3、创建目标Display具有FLAG_SECURE需要这个app具备CAPTURE_SECURE_VIDEO_OUTPUT权限。

在这里插入图片描述

<think>嗯,用户遇到了STATUS_DLL_NOT_FOUND错误,需要我提供解决方法。这个错误通常发生在Windows系统中程序无法找到必要的动态链接库文件时。 从用户提供的引用来看,有几个关键信息值得注意。引用[1]提到DLLEscort软件可以修复缺失的DLL运行库文件,引用[2]展示了在cargo test命令中遇到这个错误的情况,引用[3]则描述了VirtualBox驱动文件缺失的解决方案。这些引用说明该错误可能由多种原因引起,包括系统文件缺失、驱动问题或运行库不完整等。 用户明确表示想查找解决这个错误的方法,因此我需要整理套系统化的解决方案。首先应该从最基础的解决方案开始,比如重新安装相关程序,因为这是最简单直接的解决方法。如果无效再进行系统文件检查,使用系统自带的SFC和DISM工具修复。 考虑到用户可能遇到的是第三方依赖问题,比如引用[2]中的cargo test错误,需要建议检查程序依赖库是否完整。对于开发环境相关的问题,可能需要重新安装运行时组件如Visual C++ Redistributable。 驱动问题也是常见原因,如引用[3]中VirtualBox驱动缺失的情况,所以驱动检查和重新安装也应包含在解决方案中。最后考虑系统级的修复工具,如引用[1]提到的DLLEscort,但这类工具需要谨慎推荐,避免用户下载到恶意软件。 在安全方面,需要强调从官方渠道获取软件的重要性,同时提醒用户创建系统还原点以防万。对于开发环境特有的问题,如Rust的cargo test报错,可能需要额外建议检查环境变量和路径设置。 准备在回答中给出从简单到复杂的逐步解决方案,确保用户能按步骤排查问题。同时生成的相关问题要覆盖不同场景,帮助用户延伸思考可能的故障点和预防措施。最后要标注引用来源,保持信息可追溯。 </think>以下是针对 **STATUS_DLL_NOT_FOUND** 错误的系统性解决方法,根据错误场景分类整理: --- ### **、通用修复流程** 1. **重启系统** 临时性加载错误可能通过重启解决。 2. **重新安装报错程序** 程序安装包可能损坏或未正确注册 DLL 文件。 **步骤**: - 卸载当前程序 → 重启系统 → 从**官方渠道**下载最新版本重新安装。 3. **运行系统文件检查** 修复系统核心文件损坏问题。 **命令**(管理员权限运行 CMD): ```cmd sfc /scannow DISM /Online /Cleanup-Image /RestoreHealth ``` --- ### **二、针对性场景解决方案** #### **场景1:缺少运行库**(常见于游戏/开发工具) - **安装运行库合集**: 修复引用[1]中提到的 `NetworkStatus.dll` 类错误,需安装: - **Microsoft Visual C++ Redistributable**([官方下载](https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0)) - **DirectX End-User Runtime**([官方下载](https://www.microsoft.com/en-us/download/details.aspx?id=35)) > 建议使用 `DLLEscort` 等工具**批量修复运行库**,避免多次手动下载文件[^1]。 #### **场景2:驱动服务异常**(常见于虚拟机/硬件相关) - 如引用[3]中的 `VirtualBox` 驱动错误: 1. 进入 VirtualBox 安装目 `\drivers\vboxdrv\` 2. 右键安装 `VBoxDrv.inf` → 重启系统[^3]。 > 其他驱动问题:通过**设备管理器**更新驱动或重新安装硬件厂商官方驱动。 #### **场景3:开发环境报错**(如引用[2]的 `cargo test`) - **检查依赖完整性**: ```cmd cargo clean # 清除缓存 cargo update # 更新依赖 cargo test # 重新测试 ``` - **设置环境变量**: 将 Rust 工具链路径(如 `C:\.cargo\bin`)添加到系统 `PATH`。 --- ### **三、高级修复方案** 1. **手动注册 DLL 文件** ```cmd regsvr32 /s 文件名.dll # 管理员CMD运行 ``` > 需确保 DLL 文件来源可靠(建议从程序安装目提取)。 2. **使用系统还原点** 若更新后出现错误,回退到更新前状态(`设置 → 系统 → 恢复`)。 3. **扫描恶意软件** 使用 **Windows Defender** 或 **Malwarebytes** 扫描,排除病毒篡改文件。 --- ### **安全提示** - ❌ **避免从非官方下载 DLL 文件**:可能包含恶意代码或版本不匹配。 - ✅ **优先选择方案**: `重装程序` > `修复运行库` > `更新驱动` > `系统级修复`。 --- ### 相关问题 1. 如何区分 `STATUS_DLL_NOT_FOUND` 是系统问题还是程序自身缺陷? 2. 使用 `DLLEscort` 修复运行库是否存在安全风险? 3. 虚拟机环境频繁出现驱动加载失败(如 `VBoxDrv`)应如何彻底解决? 4. Rust 开发中如何预防 `STATUS_DLL_NOT_FOUND` 类环境配置错误? > 参考资料: > [^1]: DLL 运行库修复工具说明 > [^2]: Cargo 测试环境 DLL 加载失败案例 > [^3]: VirtualBox 驱动修复方案
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值