首页 > 其他分享 >Android显示系统——Transaction

Android显示系统——Transaction

时间:2023-07-08 23:55:25浏览次数:38  
标签:Transaction buffer SurfaceControl 系统 指定 surface Android 图层

Transaction是应用与SurfaceFlinger交流的方式之一,应用通过打开一个Transaction,然后设置各种setXXX操作,最后通过apply把所有的设定操作提交给SurfaceFlinger进行处理。

Transaction最常用的使用方法(套路)一般如下:

Transaction t;
t.setLayer(mSurfaceControl, 0x7fffffff)
    .show(mSurfaceControl)
    .apply();

Java层的Transaction定义位于base\core\java\android\view\SurfaceControl.java文件中。先来看Transaction提供了不同类型的构造函数,做开发者在不同的场景使用。

public Transaction() { // 由系统自动生成一个全新的Transaction
    this(nativeCreateTransaction());
}

private Transaction(long nativeObject) { // 根据nativeObject生成一个Transaction,这里nativeObject指一个已经存在的Trnansaction对象
    mNativeObject = nativeObject;
    mFreeNativeResources = sRegistry.registerNativeAllocation(this, mNativeObject); // 这里主要用于内存Transaction管理,不需要重点关注
}

private Transaction(Parcel in) { // 根据一个已经存在的Parcel对象创建一个Transaction对象
    readFromParcel(in);
}

对应Native侧C++的实现分别为:

// 第一种方式,创建一个全新的Transaction
SurfaceComposerClient::Transaction::Transaction() {
    mId = generateId(); // 自动生成一个Transaction id
}

std::atomic<uint32_t> idCounter = 0; // 查看aosp代码可知,idCounter代表系统已经创建过的Transaction数量
int64_t generateId() {
    return (((int64_t)getpid()) << 32) | ++idCounter;
}

// 第二种方式,根据已经一个已有的Transaction对象生成一个新的Trnasaction对象
SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
      : mId(other.mId),
        mForceSynchronous(other.mForceSynchronous),
        mTransactionNestCount(other.mTransactionNestCount),
        mAnimation(other.mAnimation),
        mEarlyWakeupStart(other.mEarlyWakeupStart),
        mEarlyWakeupEnd(other.mEarlyWakeupEnd),
        mContainsBuffer(other.mContainsBuffer),
        mDesiredPresentTime(other.mDesiredPresentTime),
        mIsAutoTimestamp(other.mIsAutoTimestamp),
        mFrameTimelineInfo(other.mFrameTimelineInfo),
        mApplyToken(other.mApplyToken) {
    mDisplayStates = other.mDisplayStates;
    mComposerStates = other.mComposerStates;
    mInputWindowCommands = other.mInputWindowCommands;
    mListenerCallbacks = other.mListenerCallbacks;
}

// 第三种方式,根据parcel传递过来的信息创建一个新的Transaction对象
std::unique_ptr<SurfaceComposerClient::Transaction>
SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) {
    auto transaction = std::make_unique<Transaction>();
    if (transaction->readFromParcel(parcel) == NO_ERROR) {
        return transaction;
    }
    return nullptr;
}

status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
    const uint32_t forceSynchronous = parcel->readUint32();
    // ......
    sp<IBinder> applyToken;
    parcel->readNullableStrongBinder(&applyToken);
    // ......
    mApplyToken = applyToken;
    return NO_ERROR;
}

下面重点来看Transaction都可以做哪些事情,即setXXX方法都有哪些。

1. Display相关的

操作 入参 说明
setDisplayDecoration 指定surface是否需要使用display decoration optimizations,主要是让SystemUI圆角走硬件RC通道
setDisplayFlags 指定display的一些flags标记,这些flag都是display相关的,不是surface相关的
setDisplayLayerStack 指定display上显示哪个layerStack
setDisplayProjection * orientation:指定屏幕的方向
* layerStackRect:窗口坐标系中的一块区域
* display:指定屏幕上的一块区域,这个区域是旋转orientation后的
指定将layersStackRect区域以orientation方向投影到屏幕的displayRect区域
setDisplaySize 指定屏幕的宽和高
setDisplaySurface 指定屏幕上显示哪个Surface

备注:

  • LayerStack是一个标识,用于唯一标识一组按z轴大小排序的layer的集合,一个layer只能被绑定到一个LayerStack中,但一个LayerStack可以关联到多个Display中,即多个Display显示同一个LayersStack的layers,也就是这些display显示的内容是完全一样的,镜像的。

2. Surface相关的

2.1 setBuffer

setBuffer有4个重载函数

  1. setBuffer(SurfaceControl sc, GraphicBuffer buffer)
  2. setBuffer(@NonNull SurfaceControl sc, @Nullable HardwareBuffer buffer)
  3. setBuffer(@NonNull SurfaceControl sc, @Nullable HardwareBuffer buffer, @Nullable SyncFence fence)
  4. setBuffer(@NonNull SurfaceControl sc, @Nullable HardwareBuffer buffer, @Nullable SyncFence fence, @Nullable Consumer releaseCallback)

4个函数的作用均为更新surface要显示的buffer,但存在如下差异:

  • 第(1)个只能用于类型为FX_SURFACE_BLAST的SurfaceControl。
  • 第(2)个函数中,该buffer只能以HardwareBuffer#USAGE_COMPOSER_OVERLAY类型进行申请,而以HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE申请的buffer会可能会走GPU合成。
  • 第(3)个函数与第(2)函数要求相同,但多了一个fence参数,如果fence参数为空或无效,则与第(2)个函数功能完全相同。该函数在设置要显示的buffer的同时,传入了一个presentation fence参数,主要目的是为了提升性能体验。指定了有效的fence参数后,只有等GPU完成了该Buffer的绘制后,这个transaction才能被SurfaceFlinger处理,否则SurfaceFlinger会一起等待,一起等到GPU绘制完成或者等待超时。例如,假设应用该buffer连同fence(该fence由android.opengl.EGLExt#eglDupNativeFenceFDANDROID(EGLDisplay, EGLSync)创建)一同传递给GPU进行处理,即允许transaction的下发和Buffer内容的绘制可以同时并行进行,合成器则需要等待该fence被signaled后才会将该Buffer进行合成送给Display进行显示。如果在同一个transaction中指定了多个Buffer,则在合成器合成送显之前,这些buffer的fence必须都被signaled后,合成器才能进行这一次的送显操作,主要目的是为了保证同步处理,即保证这些buffer是在一帧中被处理并送显的。
  • 第(4)个函数在第(3)个函数的基础上,又加了一个releaseCallback参数。releaseCallback的主要目的是让producer知道什么可以可以放心重复使用该Buffer,这种用法主要是用于连续使用transaction进行setBuffer的操作场景场景。应用端想重复使用这个buffer,则必须等待该releaseCallback函数被SurfaceFlinger回调后(,此时表明该buffer已经在服务端处理完成并释放掉了)。换句话讲,即应用端可以通过releaseCallback回调函数知道该buffer何时被SurfaceFlinger处理完成了,以此为基础来做一些其他事情。

2.2 setFrameRate

  1. setFrameRate(@NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate, @Surface.FrameRateCompatibility int compatibility)
  2. setFrameRate(@NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate, @Surface.FrameRateCompatibility int compatibility, @Surface.ChangeFrameRateStrategy int changeFrameRateStrategy)
  3. setFrameRateSelectionPriority(@NonNull SurfaceControl sc, int priority)

现今的手机产品,一般都会支持多个不同的刷新率,如60Hz,90Hz,120Hz及144Hz等。一般情况下,系统会根据不同的场景来选择合适的刷新率。改变刷新率,意思着改变了帧间隔时长,这样一般会影响Choreographer的回调节奏,但对于media codec这种则没有任何影响。

这三个函数是应用设置刷新率相关的,简单说明如下:

  • 第(1)个setFrameRate设定该surface预期的刷新速率(或帧率),compatibility表示surface指定的帧率如何与系统当前的帧率兼容,一般有两种方式:FRAME_RATE_COMPATIBILITY_DEFAULT表示不需要继承当前surface的限制,当系统选择了app请求之外的刷新率时,app会以系统选择的刷新率继续运行,该模式一般用于游戏和普通UI场等非Video场景;RAME_RATE_COMPATIBILITY_FIXED_SOURCE模式表示surface的内容应该控制固定frame rate进行显示,如video一般是固定刷新率,当系统选择了app指定之外的刷新率时,app需要pull down或采取一些其他措施来适应系统的刷新节奏,可能会出现长短帧的情况,用户体验不好,该模式主要适用于video场景。还有一种只有系统有权限使用的模式FRAME_RATE_COMPATIBILITY_EXACT,表示当前surface属于高刷新黑名单,需要系统确定采用某个刷新率进行刷新。
  • 第(2)个在第(1)基础上又添加了一个ChangeFrameRateStrategy参数,该参数表示该surface请求的帧率变更是否是无疑平滑切换的(无视觉中断的),用户不可感知的,若frameRate参数为0,则此参数无效。frameRate参数为0时,表示app会接受系统的帧率决策,如果应用未调用此接口,则默认策略即是如此。

2.3 其他函数

操作 入参 说明
setAlpha 指定surface的alhpa值,如果alpha值大于0,系统会根据alpha值将该surface会与其(z轴)下面的surface进行混合处理
setAnimationTransaction 指定此transaction为一个动画transaction,暂未研究SurfaceFlinger如何处理animaton transaction
setBackgroundBlurRadius 设定模糊背景的半径范围
setBlurRegions 指定surface的哪个区域应该做模糊处理
setBufferSize 指定默认buffer大小,如果SurfaceControl关联了一个surface,即buffer的默认大小即为dequeue出来的大小(surface的大小)
setBufferTransform 设置buffer的转换矩阵,与AttachedSurfaceControl#addOnBufferTransformHintChangedListener配合使用,可实现根据display orientation方向对buffer进行预旋转,避免在合成阶段再进行旋转,可减少GPU合成的概率,提升性能体验
setColor float[] color,三个元素的float数组,分别表现R、G、B 使用指定颜色填充Surface,若颜色值无效,则取消颜色填充
setColorSpace 设定SurfaceControl的颜色空间,当前支持的颜色空间为SRGB和Display P3,其他的颜色空间会被当作SRGB处理,此参数只能使用于FX_SURFACE_BLAST类型SurfaceControl
setColorSpaceAgnostic 设定surface的颜色空间不确定,若一个surface的颜色空间不确定,则其颜色在任何颜色空间都可以被解析
setColorTransform matrix为一个3x3的矩阵
translation为3个元素的vector
设定surface的颜色转换矩阵,在SurfaceComposerClient处会将这两个参数组合为一个4x4的矩阵colorTransform
setCornerRadius 设置SurfaceControl的圆角半径,半径的单位为pixcel
setCrop 限制surface及其子图层在指定的Rect区域内。Surface的大小会被忽略掉,只有crop和buffer size会参与surface边界的计算;如果surface即未指定crp也没有buffer,则以其父图层的bounds为边界
setDamageRegion 更新surface的脏区(即内容发生变化的区域),当一帧画面中只有一部分发生变化时,可以通过该函数指定脏区,这样在合成阶段只合成这一区域的内容,减少合成时的负载,典型场景如闪烁的光标或loading indicator。如果没有脏区为null,则相当于没有指定脏区,则会合成整个画面
setDataSpace 设定SurfaceControl的dataspace,这会决定(使用setBuffer(SurfaceControl, HardwareBuffer)设置的)buffer如何被显示出来
setDestationFrame SurfaceControl sc, @NonNull Rect destinationFram
setDestationFrame SurfaceControl sc, int width, int height
setDimmingEnabled 设定layer的亮度是否可以调节,默认值为true,表示layer的亮度可调。禁用此项,则强制layer的亮度不可调,如layer的白色像素与屏幕亮度一致。
setDropInputMode 指定SurfaceControl的input事件的drop mode,有三种模式:NONE,ALL,OBSCURED
setEarlyWakeStart 通知SurfaceFlinger接下下来的合成任务比较繁重,需要改变其offset,提前开始合成工作,尽可能的多留一些时间给合成过程
setEarlyWakeEnd 与setEarlyWakeStart作用相反,参考
setEarlyWakeStart 通知SurfaceFlinger接下下来的合成任务比较繁重,需要改变其offset,提前开始合成工作,尽可能的多留一些时间给合成过程
setFixedTransformHint 当layer及其子layer的方向与屏幕方向不一致时,由graphic producer指定一个固定的旋转hint。在不需要旋转固定方向时,调用者需要负责清理掉这个hint。当layer旋转时,这个transform hint用于防止分配一个不同大小的buffer。消费者可以选择指定这个hint以分配相同大小的buffer
setFocusedWindow 指定窗口为当前的焦点窗口,当窗口状态为不可focusable时,系统会将这个请求缓存起来直到窗口变得可focusable或者被其他请求覆盖掉
setFrameTimelineVsync 设定从choreographer处接收到的的frame timeline的vsync id
setGeometry 指定与surface关联的buffer如何被映射到父图层的坐标系中,在根据orientation指定的方向进行旋转后,系统会对source frame进行缩放操作以适配destination frame
setInputWindowInfo 设定输入窗口相关的info
setLayer 指定surfaceControl相对于其同级图层的z-order,若两个同级图层的z order相同且未定义,则z order为负数的surface会显示在其父surface下面
setLayerStack 指定surfacecontrol上的LayerStack
setMarix 设置SurfaceControl的Matrix,一般为dsdx,dtdx,dtdy,dsdy
setMetadata 设定surface的Metadata
setOpaque 指定surface是否为不透明的,即使pixel format被设置为translucent。该参数用于决定是否从 alpha通道采样不透明数据。调用setAlpha()函数设置的Plane-alpha仍然会影响合成时的混合效果,而不会考虑opaque设置。如果底层buffer无alpha channel,则相当于自动调用了setOpaque(true)。
setPosition 指定SurfaceControl相对于其父节点的位置
setRelativelayer 指定SurfaceControl相对参考目标
setScale 指定SurfaceControl基于(0,0)点进行大小缩放的倍数
setSecure 指定该surface是否为安全图层,安全图层截图和屏幕均不可见
setShadowRadius 指定surface周边绘制阴影的长度(阴影半径),若为0,则不绘制阴影。如果surface的圆角半径小于在screen bounds内,以阴影大小以圆角半径为准。阴影效果只能合适用有buffer的图层和color图层。如果在一个container图层上设置了radius参数,则会向下传递下一级的buffer或color图层,而不是传递给其子图层。
setSkipScreenshot
setStretchEffect
setTransparentRegionHint
setTrustedOverlay
setVisibility
setWindowCrop
unsetColor
unsetFixedTransformHint

备注:

  • 针对OPAQUE和alpha对合成的影响:
    • OPAQUE + alpha(1.0) == opaque composition
    • OPAQUE + alpha(0.x) == blended composition
    • OPAQUE + alpha(0.0) == no composition
    • !OPAQUE + alpha(1.0) == blended composition
    • !OPAQUE + alpha(0.x) == blended composition
    • OPAQUE + alpha(0.0) == no composition

标签:Transaction,buffer,SurfaceControl,系统,指定,surface,Android,图层
From: https://www.cnblogs.com/tsts/p/17537595.html

相关文章

  • android架构组件Lifecycle
    Lifecycle组件指的是android.arch.lifecycle包下提供的各种类与接口,可以让开发者构建能感知其他组件(主要指Activity、Fragment)生命周期(lifecycle-aware)的类。 在android开发的过程中,我们常常需要让一些操作能够感知Activity/Fragment的生命周期,从而实现在活动状态下允许操......
  • Android架构组件LiveData
    LiveDataLiveData是基于观察者模式创建的,其中,LiveData是被观察者,观察者通过注册方法,监听被观察者的数据变化。LiveData在数据发生变化的时候,会通知观察者。LiveData是一个容器,存放数据的容器,它的数据变化可以被监听,也就是LiveData是一个被观察者,如下,创建了一个存放String的数据......
  • 通用权限系统-Spring-Boot-Starter
    Spring-Boot-Starter自定义Starter案例一:读取application.yml中的参数1、创建1、创建maven工程hello-spring-boot-starter2、pom中添加依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:......
  • 第1章信息化发展|软考高项信息系统项目管理师-教程伴读脑图
    第1章信息化发展,一共36页的内容,篇幅中等,难度也是中等(三颗星),读起来虽然有一些枯燥,但是理解起来不难,毕竟技术的含量不是很高,更多是一些高大上的内容。按照我的经验,你可能需要2个小时左右完成本章的通读。第1章信息化发展,一共包含5小节的知识块,分别是“信息与信息化”、“现代化基础设......
  • 数据库系统概论—恢复与并发
    数据库概论系统—系统篇一、关系查询处理和查询优化1.1关系数据库的查询处理查询处理可分为四个阶段:查询分析、检查检查、查询优选和查询执行(其中查询优化可分为代数和物理优化)1.2关系数据库系统的查询优化查询优化的优点不仅在于用户不必考虑如何最好地表达查询以获得较高......
  • 如何在 Mac OS X 下制作可以在 PC 上启动的PE系统?
    如何在MacOSX下制作可以在PC上启动的PE系统?(zhihu.com)(84条消息)如何在MacOSX下制作可以在PC上启动的PE系统?-知乎(zhihu.com)如何在macOS下制作winpe启动U盘-老吴黑苹果工作室(hpglw.com)......
  • 嵌入式linux根文件系统镜像制作
    原文:https://zhuanlan.zhihu.com/p/568784791在嵌入式linux平台中,大部分工作则是填充根文件系统,在开发中,根文件系统一般都是以目录的方式放在开发宿主机上。当根文件系统填充完成后,我们需要将其打包成xxx.img或者其他的镜像格式。本文以xxx.img镜像格式为例,描述如何将根文件......
  • Android开发腾讯云智面经分享
    分享一位读者面试腾讯云智(腾讯集团旗下的全资子公司)投稿的面经,主要记录了自己在面试过程中遇到的问题。下面是正文。本人在湖北的一所民办二本,学校非常一般。由于寒气逼人,快到七月才拿到offer,感谢腾讯云智!!!腾讯云智(武汉)一面(40min)1、GC原理,有哪几种GC方式。2、HashMap原理。3、H......
  • 从零开始构建根文件系统
    原文:https://blog.csdn.net/oqqHuTu12345678/article/details/125342676以下内容源于网络资源的学习与整理,如有侵权请告知删除。 在前面的理论分析的基础上,我们开始从零开始构建一个根文件系统。构建根文件系统的步骤:首先,在形式上创建一些空目录。然后,利用busybox软件来生成......
  • 谷歌浏览器扩展通知到win系统
    记得要开启chrome通知权限,右下角,对话图标,打开通知栏,点右上角管理通知,找到chrome,开启文档:https://developer.chrome.com/docs/extensions/reference/notifications/manifest.json"permissions":["notifications"],service-worker.js//提醒functionnotify(tex......