Android智能座驾,carlink场景截屏黑屏问题

  • 背景
    项目开发过程中,遇到如下问题:
    【操作步骤】
    1、建立导航+音乐分屏
    2、连接Carlink,车机端打开任意Carlink应用,点击音乐图标回到分屏
    【结果】
    页面会出现1s黑屏再显示分屏的情况

  • 详细分析
    比较怀疑是截屏的方法拿到的图片就是黑色导致。截屏采用的SurfaceControl.captureDisplay

通过dumpsys SurfaceFlinger和dumpsys window可以发现:不能截图的页面,带有secure属性。
在这里插入图片描述

在这里插入图片描述

  • status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs&
    args,const sp& captureListener)
  • ftl::SharedFuture
    SurfaceFlinger::captureScreenCommon(
    RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers,
    const std::shared_ptrrenderengine::ExternalTexture& buffer, bool regionSampling,
    bool grayscale, const sp& captureListener)
  • ftl::SharedFuture SurfaceFlinger::renderScreenImpl(
    const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
    const std::shared_ptrrenderengine::ExternalTexture& buffer,
    bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
    ScreenCaptureResults& captureResults)
  • std::optionalcompositionengine::LayerFE::LayerSettings
    BufferLayer::prepareClientComposition(
    compositionengine::LayerFE::ClientCompositionTargetSettings&
    targetSettings)
std::optional<compositionengine::LayerFE::LayerSettings> BufferLayer::prepareClientComposition(compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) {ATRACE_CALL();ALOGE("captureDisplay, prepareClientComposition");std::optional<compositionengine::LayerFE::LayerSettings> result =Layer::prepareClientComposition(targetSettings);if (!result) {return result;}if (CC_UNLIKELY(mBufferInfo.mBuffer == 0) && mSidebandStream != nullptr) {// For surfaceview of tv sideband, there is no activeBuffer// in bufferqueue, we need return LayerSettings.return result;}const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||((isSecure() || isProtected()) && !targetSettings.isSecure);const bool bufferCanBeUsedAsHwTexture =mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;compositionengine::LayerFE::LayerSettings& layer = *result;if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {ALOGE("captureDisplay, prepareClientComposition-2, blackOutLayer = %d, bufferCanBeUsedAsHwTexture=%d, \isProtected()=%d, !targetSettings.supportsProtectedContent = %d, isSecure()=%d, !targetSettings.isSecure=%d",blackOutLayer, bufferCanBeUsedAsHwTexture, isProtected(), (!targetSettings.supportsProtectedContent), isSecure(), (!targetSettings.isSecure));ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",mName.c_str());prepareClearClientComposition(layer, true /* blackout */);return layer;}ALOGE("captureDisplay, prepareClientComposition-3");const State& s(getDrawingState());layer.source.buffer.buffer = mBufferInfo.mBuffer;layer.source.buffer.isOpaque = isOpaque(s);layer.source.buffer.fence = mBufferInfo.mFence;layer.source.buffer.textureName = mTextureName;layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();layer.source.buffer.isY410BT2020 = isHdrY410();bool hasSmpte2086 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086;bool hasCta861_3 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::CTA861_3;float maxLuminance = 0.f;if (hasSmpte2086 && hasCta861_3) {maxLuminance = std::min(mBufferInfo.mHdrMetadata.smpte2086.maxLuminance,mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel);} else if (hasSmpte2086) {maxLuminance = mBufferInfo.mHdrMetadata.smpte2086.maxLuminance;} else if (hasCta861_3) {maxLuminance = mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel;} else {switch (layer.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {case HAL_DATASPACE_TRANSFER_ST2084:case HAL_DATASPACE_TRANSFER_HLG:// Behavior-match previous releases for HDR contentmaxLuminance = defaultMaxLuminance;break;}}layer.source.buffer.maxLuminanceNits = maxLuminance;layer.frameNumber = mCurrentFrameNumber;layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;const bool useFiltering =targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();// Query the texture matrix given our current filtering mode.float textureMatrix[16];getDrawingTransformMatrix(useFiltering, textureMatrix);if (getTransformToDisplayInverse()) {/** the code below applies the primary display's inverse transform to* the texture transform*/uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags();mat4 tr = inverseOrientation(transform);/*** TODO(b/36727915): This is basically a hack.** Ensure that regardless of the parent transformation,* this buffer is always transformed from native display* orientation to display orientation. For example, in the case* of a camera where the buffer remains in native orientation,* we want the pixels to always be upright.*/sp<Layer> p = mDrawingParent.promote();if (p != nullptr) {const auto parentTransform = p->getTransform();tr = tr * inverseOrientation(parentTransform.getOrientation());}// and finally apply it to the original texture matrixconst mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));}const Rect win{getBounds()};float bufferWidth = getBufferSize(s).getWidth();float bufferHeight = getBufferSize(s).getHeight();// BufferStateLayers can have a "buffer size" of [0, 0, -1, -1] when no display frame has// been set and there is no parent layer bounds. In that case, the scale is meaningless so// ignore them.if (!getBufferSize(s).isValid()) {bufferWidth = float(win.right) - float(win.left);bufferHeight = float(win.bottom) - float(win.top);}const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;const float translateY = float(win.top) / bufferHeight;const float translateX = float(win.left) / bufferWidth;// Flip y-coordinates because GLConsumer expects OpenGL convention.mat4 tr = mat4::translate(vec4(.5, .5, 0, 1)) * mat4::scale(vec4(1, -1, 1, 1)) *mat4::translate(vec4(-.5, -.5, 0, 1)) *mat4::translate(vec4(translateX, translateY, 0, 1)) *mat4::scale(vec4(scaleWidth, scaleHeight, 1.0, 1.0));layer.source.buffer.useTextureFiltering = useFiltering;layer.source.buffer.textureTransform = mat4(static_cast<const float*>(textureMatrix)) * tr;return layer;
}

通过加log debug发现是如下红框部分进入了,出现了黑色图层。
在这里插入图片描述
通过log可以知道:blackOutLayer = 1, bufferCanBeUsedAsHwTexture=1
那么问题就出在blackOutLayer ,继续分析:isProtected()=0, !targetSettings.supportsProtectedContent = 1, isSecure()=1, !targetSettings.isSecure=1

接下来排查isSecure() 和 targetSettings.isSecure的来龙去脉。

isSecure()如下:
在这里插入图片描述

targetSettings.isSecure如下:
在这里插入图片描述

从dump信息来看,display和layer 都是secure的,所以需要将mAllowSecureLayers设置问题true,才能截取secure layer图片。

  • 解决方案
    截屏的时候,将mCaptureSecureLayers设置为true,问题解决。
    在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/7576.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Go语言的常用内置函数

文章目录 一、Strings包字符串处理包定义Strings包的基本用法Strconv包中常用函数 二、Time包三、Math包math包概述使用math包 四、随机数包&#xff08;rand&#xff09; 一、Strings包 字符串处理包定义 Strings包简介&#xff1a; 一般编程语言包含的字符串处理库功能区别…

Vue实战学习(2)(Vue快速入门(快速构建一个局部Vue项目))

目录 一、Vue快速入门。 &#xff08;1&#xff09;快速入门的案例需求。 &#xff08;2&#xff09;原生js解决。 &#xff08;3&#xff09;使用Vue解决。 1、准备一个html页面。且该页面需要引入Vue模块。 2、创建Vue程序的应用实例。 3、准备html元素&#xff08;如div&…

canal1.1.7使用canal-adapter进行mysql同步数据

重要的事情说前面&#xff0c;canal1.1.8需要jdk11以上&#xff0c;大家自行选择&#xff0c;我这由于项目原因只能使用1.1.7兼容版的 文章参考地址&#xff1a; canal 使用详解_canal使用-CSDN博客 使用canal.deployer-1.1.7和canal.adapter-1.1.7实现mysql数据同步_mysql更…

羽星股份引领连锁业数智化转型,厦门羽星科技公司逆势增长剑指纳斯达克

羽星股份引领连锁业数智化转型&#xff0c;厦门羽星科技公司逆势增长剑指纳斯达克 在消费降级的大环境下&#xff0c;许多企业面临严峻挑战。在消费降级背景下&#xff0c;消费者购买力下降&#xff0c;对价格敏感度提升&#xff0c;更加注重产品的性价比和实用性。这一趋势促使…

RabbitMQ应用

1. 7种工作模式介绍 1.1 Simple(简单模式) P: ⽣产者,也就是要发送消息的程序C: 消费者,消息的接收者Queue: 消息队列(图中⻩⾊背景部分)类似⼀个邮箱,可以缓存消息;⽣产者向其中投递消息,消费者从 其中取出消息 特点: ⼀个⽣产者P&#xff0c;⼀个消费者C, 消息只能被消费…

从Java中使用new 关键字创建对象开始,深度剖析对象结构与存储

文章目录 1.对象结构2.扩展补充3.小结 1.对象结构 在介绍之前.先来看一个java高频面试题&#xff0c;new String(hello") 创建了几个对象&#xff1f; 1.这里分情况讨论&#xff0c;如果hello已经在常量池中存在&#xff0c;那么就是在堆中创建1个对象&#xff0c;并返回…

ThreadLocal 的原理和使用场景

1.ThreadLocal是什么 ThreadLocal 是 Java 提供的一个用于线程存储本地变量的类。它为每个线程提供独立的变量副本&#xff0c;确保变量在多线程环境下的线程安全。每个线程访问 ThreadLocal 时&#xff0c;都会有自己专属的变量副本&#xff0c;互不干扰&#xff0c;避免了并…

qt QColorDialog详解

1、概述 QColorDialog是Qt框架中的一个对话框类&#xff0c;专门用于让用户选择颜色。它提供了一个标准的颜色选择界面&#xff0c;其中包括基本的颜色选择器&#xff08;如调色板和颜色轮&#xff09;、自定义颜色输入区域以及预定义颜色列表。QColorDialog支持RGB、HSV和十六…

关于Redis

Redis 基础 什么是 Redis&#xff1f; Redis &#xff08;REmote DIctionary Server&#xff09;是一个基于 C 语言开发的开源 NoSQL 数据库&#xff08;BSD 许可&#xff09;。与传统数据库不同的是&#xff0c;Redis 的数据是保存在内存中的&#xff08;内存数据库&#xf…

linux nvidia/cuda安装

1.查看显卡型号 lspci |grep -i vga2.nvidia安装 2.1在线安装 终端输入&#xff08;当显卡插上之后&#xff0c;系统会有推荐的安装版本&#xff09; ubuntu-drivers devices可得到如下内容 vendor : NVIDIA Corporation model : TU104GL [Tesla T4] driver : nvid…

uniapp 实现瀑布流

效果演示 组件下载 瀑布流布局-waterfall - DCloud 插件市场

了解聚簇索引和非聚簇索引

在关系型数据库中,索引是提高查询效率的重要手段。索引类似于书籍中的目录,能够帮助数据库快速定位到所需的数据。而在数据库中,最常用的两种索引类型是聚簇索引(Clustered Index)和非聚簇索引(Non-clustered Index)。本文将详细介绍这两种索引类型,帮助读者更好地理解…

CODESYS可视化桌面屏保-动态气泡制作详细案例

#一个用于可视化(HMI)界面的动态屏保的详细制作案例程序# 前言: 在工控自动化设备上,为了防止由于人为误触发或操作引起的故障,通常在触摸屏(HMI)增加屏幕保护界面,然而随着PLC偏IT化的发展,在控制界面上的美观程度也逐渐向上位机或网页前端方面发展,本篇模仿Windows…

【数据结构 队列】超详细理解例题

数据结构 队列 前言队列的定义队列的概念队列的基本操作 队列用C语言实现Queue.hQueue.ctext.c 队列 VS 栈队列的应用 你好&#xff0c;这里是新人 Sunfor 这篇是我最近对于数据结构 队列的学习心得和错题整理 有任何错误欢迎指正&#xff0c;欢迎交流&#xff01; 会持续更新…

VSCode + linux 远程免密登录

目录 一. VS Code端1. 安装插件Remote - SSH2. 配置config文件3. 公钥生成 二、远程服务器端1. 将生成的公钥发送到远程服务器 三、连接1. 准备就绪后&#xff0c;VSCode连接 一. VS Code端 1. 安装插件Remote - SSH 2. 配置config文件 Host H5WebHostName xx.xx.xx.xxUser ro…

简单分享一下淘宝商品数据自动化抓取的技术实现与挑战

在电子商务领域&#xff0c;数据是驱动决策的关键。淘宝作为国内最大的电商平台之一&#xff0c;其商品数据对电商从业者来说具有极高的价值。然而&#xff0c;从淘宝平台自动化抓取商品数据并非易事&#xff0c;涉及多重技术和法律挑战。本文将从技术层面分析实现淘宝商品数据…

初识网络编程

目录 前言相关名词解释应用层协议——HTTP传输层协议socketTCP帧头格式三次握手、四次挥手 UDPTCP的socket实现 参考博文 前言 刚碰到网络编程&#xff0c;会出现一堆协议、概念、这层次那技术的&#xff0c;头都大了&#xff0c;还是得总结总结…… 相关名词解释 ✨✨网络…

JRTPLIB中的RTPSession与OnSSRCCollision:深入解析SSRC冲突处理机制

JRTPLIB中的RTPSession与OnSSRCCollision:深入解析SSRC冲突处理机制 一、RTP与SSRC基础1.1 RTP简介1.2 SSRC的作用二、JRTPLIB与RTPSession2.1 JRTPLIB概述2.2 RTPSession类三、SSRC冲突与OnSSRCCollision3.1 SSRC冲突的原因3.2 OnSSRCCollision回调函数3.3 OnSSRCCollision的…

【数据集】【YOLO】【目标检测】口罩佩戴识别数据集 1971 张,YOLO佩戴口罩检测算法实战训练教程!

数据集介绍 【数据集】口罩佩戴检测数据集 1971 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。 数据集中包含1种分类&#xff1a;{0: face_mask}&#xff0c;佩戴口罩。 数据集来自国内外图片网站和视频截图。 检测场景为城市街道、医院、商场、机场、车站、办…

实测讯飞智作,一张照片定制属于自己的数字人

Datawhale亲测 AI应用&#xff1a;讯飞智作 只用一张照片&#xff0c;就可以定制属于自己的数字人。 这是大模型给数字人领域带来的最新震撼。 就在两周前的 AI 开发者 Talk 合肥站活动上&#xff0c;我们 Datawhale 的一名小伙伴玉鑫化身成数字人亮相大屏幕&#xff0c;为参加…