当前位置: 首页 > article >正文

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 content
                maxLuminance = 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 matrix
        const 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.kler.cn/a/388188.html

相关文章:

  • 【数据结构与算法】第11课—数据结构之选择排序和交换排序
  • 使用 Flask 和 ONLYOFFICE 实现文档在线编辑功能
  • 机器学习基础02_特征工程
  • 监控录音如何消除杂音?降低录音噪音的五个技巧
  • SQL50题
  • 【Xrdp联机Ubuntu20.04实用知识点补充】
  • Pycharm远程调试deepspeed!可用!
  • 前端三件套配合豆包MarsCode 实现钉钉官网动画
  • USB学习(上)
  • 「Mac玩转仓颉内测版1」入门篇1 - Cangjie环境的搭建
  • NLP之ASR之moonshine:moonshine的简介、安装和使用方法、案例应用之详细攻略
  • 如何设置定时关闭或启动整个docker而不是某个容器
  • GPIO 唤醒深度睡眠的esp32-c3
  • 如何找到养生生活视频素材?推荐几个优秀网站
  • 每日一题之成绩排序(进阶版)
  • springboot静态资源映射不生效问题
  • Node.js——fs模块-相对路径的bug与解决
  • 机器学习—多类
  • C++使用开源ConcurrentQueue库处理自定义业务数据类
  • MySQL的其他函数
  • Oracle简介、环境搭建和基础DML语句
  • 网络安全从入门到精通(特别篇IIl):应急响应之病毒蠕虫处置流程
  • 深度学习-张量相关
  • 解决 IntelliJ IDEA Maven 项目 JDK 版本自动变为 1.5 的问题
  • 硬件设备网络安全问题与潜在漏洞分析及渗透测试应用
  • 开源竞争-利用kimi编程助手搭建小程序(11)