HWC 接口分析
# HWC 接口分析
# 1. HWC3 AIDL 接口分析
HWC HAL 作为一个 HAL 模块,通过 Binder 服务向 SurfaceFlinger 提供了使用接口。这些接口通过 AIDL 文件定义:
- IComposer.aidl:HWC 直接提供的 Binder 服务
- IComposerClient.aidl:HWC 通过匿名 Binder 提供的 Binder 服务
SurfaceFlinger 向 HWC 注册了一个 Binder 回调,用于接收 HWC 事件通知,该回调协议通过 AIDL 文件定义:
- IComposerCallback.aidl:HWC 事件通知回调接口
# 1.1 IComposer.aidl 接口分析
// /hardware/interfaces/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposer.aidl
package android.hardware.graphics.composer3;
@VintfStability
interface IComposer {
android.hardware.graphics.composer3.IComposerClient createClient();
android.hardware.graphics.composer3.Capability[] getCapabilities();
const int EX_NO_RESOURCES = 6;
}
2
3
4
5
6
7
8
getCapabilities 用于获取 HWC 支持的能力, 返回的 Capability 是一个枚举类型,枚举值定义在 Capability.aidl 中。
// /hardware/interfaces/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
enum Capability {
// 作为默认值或错误状态的标识
INVALID = 0,
// 支持侧带流(Sideband Stream)处理能力,允许硬件直接处理视频流,无需通过 SurfaceFlinger
SIDEBAND_STREAM = 1,
// 跳过客户端颜色变换处理,HWC 可以直接在硬件层面处理颜色空间转换
SKIP_CLIENT_COLOR_TRANSFORM = 2,
// 当硬件无法提供可靠的同步信号时设置此标志
PRESENT_FENCE_IS_NOT_RELIABLE = 3,
// - 原本用于跳过 HWC 的验证阶段以提升性能,现在默认启用,不再需要显式设置
/**
* @deprecated - enabled by default.
*/
SKIP_VALIDATE = 4,
//支持启动时显示配置
BOOT_DISPLAY_CONFIG = 5,
// HDR 输出转换配置支持
HDR_OUTPUT_CONVERSION_CONFIG = 6,
// 刷新率变化回调调试支持
REFRESH_RATE_CHANGED_CALLBACK_DEBUG = 7,
// 图层生命周期批处理命令支持
LAYER_LIFECYCLE_BATCH_COMMAND = 8,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
createClient 用于获取 HWC 的匿名 Binder 服务 IComposerClient,该服务是一个匿名 Binder 服务,其能力定义在 IComposerClient.aidl 文件中。
# 1.2 IComposerClient.aidl 接口分析
IComposerClient.aidl 定义了 HWC 进程中匿名 Binder 服务 IComposerClient 向 SurfaceFlinger 提供的主要的功能,其定义如下:
// /hardware/interfaces/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
package android.hardware.graphics.composer3;
@VintfStability
interface IComposerClient {
long createLayer(long display, int bufferSlotCount);
android.hardware.graphics.composer3.VirtualDisplay createVirtualDisplay(int width, int height, android.hardware.graphics.common.PixelFormat formatHint, int outputBufferSlotCount);
void destroyLayer(long display, long layer);
void destroyVirtualDisplay(long display);
android.hardware.graphics.composer3.CommandResultPayload[] execut eCommands(in android.hardware.graphics.composer3.DisplayCommand[] commands);
int getActiveConfig(long display);
android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
/**
* @deprecated use getDisplayConfigurations instead. Returns a display attribute value for a particular display configuration. For legacy support getDisplayAttribute should return valid values for any requested DisplayAttribute, and for all of the configs obtained either through getDisplayConfigs or getDisplayConfigurations.
*/
int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
android.hardware.graphics.composer3.DisplayCapability[] getDisplayCapabilities(long display);
/**
* @deprecated use getDisplayConfigurations instead. For legacy support getDisplayConfigs should return at least one valid config. All the configs returned from the getDisplayConfigs should also be returned from getDisplayConfigurations.
*/
int[] getDisplayConfigs(long display);
android.hardware.graphics.composer3.DisplayConnectionType getDisplayConnectionType(long display);
android.hardware.graphics.composer3.DisplayIdentification getDisplayIdentificationData(long display);
String getDisplayName(long display);
int getDisplayVsyncPeriod(long display);
android.hardware.graphics.composer3.DisplayContentSample getDisplayedContentSample(long display, long maxFrames, long timestamp);
android.hardware.graphics.composer3.DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
android.hardware.graphics.common.Transform getDisplayPhysicalOrientation(long display);
android.hardware.graphics.composer3.HdrCapabilities getHdrCapabilities(long display);
int getMaxVirtualDisplayCount();
android.hardware.graphics.composer3.PerFrameMetadataKey[] getPerFrameMetadataKeys(long display);
android.hardware.graphics.composer3.ReadbackBufferAttributes getReadbackBufferAttributes(long display);
@nullable ParcelFileDescriptor getReadbackBufferFence(long display);
android.hardware.graphics.composer3.RenderIntent[] getRenderIntents(long display, android.hardware.graphics.composer3.ColorMode mode);
android.hardware.graphics.composer3.ContentType[] getSupportedContentTypes(long display);
@nullable android.hardware.graphics.common.DisplayDecorationSupport getDisplayDecorationSupport(long display);
void registerCallback(in android.hardware.graphics.composer3.IComposerCallback callback);
void setActiveConfig(long display, int config);
android.hardware.graphics.composer3.VsyncPeriodChangeTimeline setActiveConfigWithConstraints(long display, int config, in android.hardware.graphics.composer3.VsyncPeriodChangeConstraints vsyncPeriodChangeConstraints);
void setBootDisplayConfig(long display, int config);
void clearBootDisplayConfig(long display);
int getPreferredBootDisplayConfig(long display);
void setAutoLowLatencyMode(long display, boolean on);
void setClientTargetSlotCount(long display, int clientTargetSlotCount);
void setColorMode(long display, android.hardware.graphics.composer3.ColorMode mode, android.hardware.graphics.composer3.RenderIntent intent);
void setContentType(long display, android.hardware.graphics.composer3.ContentType type);
void setDisplayedContentSamplingEnabled(long display, boolean enable, android.hardware.graphics.composer3.FormatColorComponent componentMask, long maxFrames);
void setPowerMode(long display, android.hardware.graphics.composer3.PowerMode mode);
void setReadbackBuffer(long display, in android.hardware.common.NativeHandle buffer, in @nullable ParcelFileDescriptor releaseFence);
void setVsyncEnabled(long display, boolean enabled);
void setIdleTimerEnabled(long display, int timeoutMs);
android.hardware.graphics.composer3.OverlayProperties getOverlaySupport();
android.hardware.graphics.common.HdrConversionCapability[] getHdrConversionCapabilities();
android.hardware.graphics.common.Hdr setHdrConversionStrategy(in android.hardware.graphics.common.HdrConversionStrategy conversionStrategy);
void setRefreshRateChangedCallbackDebugEnabled(long display, boolean enabled);
android.hardware.graphics.composer3.DisplayConfiguration[] getDisplayConfigurations(long display, int maxFrameIntervalNs);
oneway void notifyExpectedPresent(long display, in android.hardware.graphics.composer3.ClockMonotonicTimestamp expectedPresentTime, int frameIntervalNs);
int getMaxLayerPictureProfiles(long display);
oneway void startHdcpNegotiation(long display, in android.hardware.drm.HdcpLevels levels);
android.hardware.graphics.composer3.Luts[] getLuts(long display, in android.hardware.graphics.composer3.Buffer[] buffers);
const int EX_BAD_CONFIG = 1;
const int EX_BAD_DISPLAY = 2;
const int EX_BAD_LAYER = 3;
const int EX_BAD_PARAMETER = 4;
const int EX_RESERVED = 5;
const int EX_NO_RESOURCES = 6;
const int EX_NOT_VALIDATED = 7;
const int EX_UNSUPPORTED = 8;
const int EX_SEAMLESS_NOT_ALLOWED = 9;
const int EX_SEAMLESS_NOT_POSSIBLE = 10;
const int EX_CONFIG_FAILED = 11;
const int EX_PICTURE_PROFILE_MAX_EXCEEDED = 12;
const int INVALID_CONFIGURATION = 0x7fffffff;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
内部定义的接口可分为以下几类:
- 命令执行,绝大部分显示相关操作都是通过
android.hardware.graphics.composer3.CommandResultPayload[] executeCommands(in android.hardware.graphics.composer3.DisplayCommand[] commands);函数执行 - 图层管理函数
long createLayer(long display, int bufferSlotCount)void destroyLayer(long display, long layer);
- 虚拟显示管理
- createVirtualDisplay
- destroyVirtualDisplay
- 显示配置管理
- getActiveConfig / setActiveConfigWithConstraints
- getDisplayConfigurations
- setActiveConfigWithConstraints
- 颜色和显示质量管理
- getColorModes / setColorMode
- getHdrCapabilities
- getDataspaceSaturationMatrix
- 电源管理
- setPowerMode
- 同步和时序控制
- setVsyncEnabled
- getDisplayVsyncPeriod
- notifyExpectedPresent
- 回调注册
- registerCallback
- 高级功能
- getOverlaySupport
- setAutoLowLatencyMode
- getHdrConversionCapabilities() / setHdrConversionStrategy
- 调试和诊断
* setRefreshRateChangedCallbackDebugEnabled
* getDisplayedContentSample
口还定义了一系列错误码常量:
- EX_BAD_CONFIG - 配置错误
- EX_BAD_DISPLAY - 显示设备错误
- EX_BAD_LAYER - 图层错误
- EX_NO_RESOURCES - 资源不足
- EX_UNSUPPORTED - 不支持的操作
IComposerClient 接口是 Android 图形系统的核心组件,它提供了完整的显示设备管理、图层合成、颜色管理、电源控制等功能。通过这个接口,Android系统能够高效地管理各种显示设备,支持多显示器、HDR、高刷新率等现代显示技术,同时保证良好的性能和用户体验。
# 1.3 IComposerCallback.aidl 接口分析
ComposerCallback.aidl 定义了 HWC HAL 层向 SurfaceFlinger 回调的接口。该接口包含 8 个回调方法,用于通知显示设备状态变化、垂直同步事件和其他重要的图形系统事件。
// /hardware/interfaces/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerCallback.aidl
package android.hardware.graphics.composer3;
@VintfStability
interface IComposerCallback {
/**
* 已弃用,建议使用 onHotplugEvent 替代
*/
void onHotplug(long display, boolean connected);
/**
参数说明:
- display : 显示设备 ID
- connected : 布尔值,表示设备是连接 (true) 还是断开 (false)
触发场景: 当外部显示设备(如 HDMI 显示器、USB-C 显示器)物理连接或断开时触发
作用:HAL 层检测到硬件连接状态变化时主动调用此回调,通知 SurfaceFlinger 显示设备的热插拔状态变化
*/
oneway void onRefresh(long display);
/**
参数说明:
- display : 显示设备 ID
触发场景: 当显示设备支持无缝模式切换(如刷新率变化、分辨率变化)时触发
作用: 当 HWC 检测到某个显示设备(由 display参数标识)能够支持无缝切换到一种新的显示模式(例如分辨率、刷新率的改变)时,通过此回调函数主动通知上层的 SurfaceFlinger,无需黑屏或闪烁
*/
oneway void onSeamlessPossible(long display);
/**
参数说明:
- display : 产生垂直同步信号的显示设备 ID
- timestamp : 垂直同步信号的时间戳(纳秒)
- vsyncPeriodNanos : 垂直同步周期(纳秒)
触发场景: 每当显示设备产生垂直同步信号时触发,通常以固定频率(如 60Hz、90Hz、120Hz)
作用: 为 SurfaceFlinger 提供精确的显示时序信息,用于同步渲染和合成操作,确保流畅的动画和视频播放
*/
oneway void onVsync(long display, long timestamp, int vsyncPeriodNanos);
/**
参数说明:
- display : 显示设备 ID
- updatedTimeline : `VsyncPeriodChangeTimeline.aidl` 结构,包含:
- newVsyncAppliedTimeNanos : 新垂直同步周期生效的时间
- refreshRequired : 是否需要刷新
- refreshTimeNanos : 刷新时间
触发场景: 当显示设备的垂直同步周期发生变化时触发,如动态刷新率切换
*/
oneway void onVsyncPeriodTimingChanged(long display, in android.hardware.graphics.composer3.VsyncPeriodChangeTimeline updatedTimeline);
/**
参数说明:
- display : 进入空闲状态的显示设备 ID
触发场景: 当显示设备进入空闲状态,不再需要频繁的垂直同步信号时触发,HAL 层检测到显示内容静止或系统进入省电模式时调用
*/
oneway void onVsyncIdle(long display);
/**
参数说明:
- data : `RefreshRateChangedDebugData.aidl` 结构,包含:
- display : 显示设备 ID
- vsyncPeriodNanos : 垂直同步周期(纳秒)
- refreshPeriodNanos : 刷新周期(纳秒)
触发场景: 当刷新率发生变化时触发,主要用于调试和性能分析
*/
oneway void onRefreshRateChangedDebug(in android.hardware.graphics.composer3.RefreshRateChangedDebugData data);
/*
参数说明:
- display : 显示设备 ID
- event : `DisplayHotplugEvent.aidl` 枚举,包含:
- CONNECTED : 设备连接
- DISCONNECTED : 设备断开
- ERROR_UNKNOWN : 未知错误
- ERROR_INCOMPATIBLE_CABLE : 不兼容的线缆
- ERROR_TOO_MANY_DISPLAYS : 显示设备过多
- ERROR_LINK_UNSTABLE : 连接不稳定
触发场景:当显示设备热插拔事件发生时触发,替代已弃用的 onHotplug 方法
*/
void onHotplugEvent(long display, android.hardware.graphics.common.DisplayHotplugEvent event);
/*
参数说明:
- display : 显示设备 ID
- levels : HDCP(高带宽数字内容保护)级别信息
触发场景: 当显示设备的 HDCP 保护级别发生变化时触发,用于数字版权管理和内容保护
*/
oneway void onHdcpLevelsChanged(long display, in android.hardware.drm.HdcpLevels levels);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 2. HWC3 AIDL 接口的封装
上述的 aidl 中定义的接口,通常不直接使用代理端对象操作,一般会通过一个管理类来封装这些接口。AidlComposer 类就是这样一个管理类,它封装了 IComposer 接口的所有方法,提供了更方便的调用接口。
# 2.1 AidlComposer 类结构分析
// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
class AidlComposer final : public Hwc2::Composer
2
AidlComposer 继承自 Hwc2::Composer,Hwc2::Composer 内部基本都是虚函数,定义了 HWC3 AIDL 接口代理端管理类应该具有的能力。
# 2.1.1 成员变量
AIDL 接口相关成员:
// AIDL 接口实例
std::shared_ptr<AidlIComposer> mAidlComposer; // AIDL Composer 客户端接口
std::shared_ptr<AidlIComposerClient> mAidlComposerClient; // AIDL Composer 客户端接口
std::shared_ptr<AidlIComposerCallbackWrapper> mAidlComposerCallback; // 回调接口包装器
2
3
4
命令缓冲区管理成员:
// 每个显示设备的命令写入器和读取器
ui::PhysicalDisplayMap<Display, ComposerClientWriter> mWriters GUARDED_BY(mMutex);
ui::PhysicalDisplayMap<Display, ComposerClientReader> mReaders GUARDED_BY(mMutex);
2
3
配置和状态管理成员:
// 接口版本和功能标志
int32_t mComposerInterfaceVersion = 1; // Composer 接口版本
bool mEnableLayerCommandBatchingFlag = false; // 图层命令批处理标志
std::atomic<int64_t> mLayerID = 1; // 原子性图层ID计数器
// 多线程支持配置
bool mSingleReader = true; // 单读取器模式标志
static constexpr int64_t kSingleReaderKey = 0; // 单读取器模式的键值
2
3
4
5
6
7
8
缓冲区管理成员:
sp<GraphicBuffer> mClearSlotBuffer; // 提供一个专用缓冲区用于清理图层的缓冲区槽位
# 2.1.2 成员方法
生命周期管理:
static bool isDeclared(const std::string& serviceName); // 检查服务是否声明
explicit AidlComposer(const std::string& serviceName); // 构造函数
~AidlComposer() override; // 析构函数
2
3
能力查询接口:
bool isSupported(OptionalFeature) const; // 检查可选功能支持
bool isVrrSupported() const; // 检查可变刷新率支持
std::vector<Capability> getCapabilities() override; // 获取硬件能力
2
3
显示设备管理:
Error createVirtualDisplay(...); // 创建虚拟显示设备
Error destroyVirtualDisplay(...); // 销毁虚拟显示设备
Error getDisplayConfigs(...); // 获取显示配置
Error setActiveConfig(...); // 显示配置
Error setActiveConfigWithConstraints(...) // 显示配置
2
3
4
5
图层操作接口:
Error createLayer(...); // 创建图层
Error destroyLayer(...); // 销毁图层
Error setLayerBuffer(...); // 设置图层缓冲区
Error setLayerCompositionType(...); // 设置图层合成类型
Error setClientTarget(...)
// ......
2
3
4
5
6
# 2.1.3 mReaders 与 mWriters 作用分析
ui::PhysicalDisplayMap<Display, ComposerClientWriter> mWriters GUARDED_BY(mMutex);
ui::PhysicalDisplayMap<Display, ComposerClientReader> mReaders GUARDED_BY(mMutex);
2
mWriters 的主要功能是为每个物理显示设备维护一个独立的命令写入器 ComposerClientWriter,用于:
1.命令缓冲管理:为每个显示设备缓存待发送给硬件合成器(HWC)的命令 2.显示设备隔离:确保不同显示设备的命令操作相互独立 3.批量命令处理:支持将多个图层操作命令批量发送,提高性能
mReaders 负责解析和处理来自 Composer 服务的命令执行结果。
ComposerClientWriter 添加过程与移除过程:
void AidlComposer::addDisplay(Display display) {
const auto displayId = translate<int64_t>(display);
mMutex.lock();
auto [it, added] = mWriters.try_emplace(display, displayId);
// ...
}
void AidlComposer::removeDisplay(Display display) {
mMutex.lock();
bool wasErased = mWriters.erase(display);
// ...
}
2
3
4
5
6
7
8
9
10
11
12
ComposerClientReader 的添加与移除过程:
void AidlComposer::addReader(Display display) {
const auto displayId = translate<int64_t>(display);
std::optional<int64_t> displayOpt;
if (displayId != kSingleReaderKey) {
displayOpt.emplace(displayId);
}
auto [it, added] = mReaders.try_emplace(display, std::move(displayOpt));
ALOGW_IF(!added, "Attempting to add writer for display %" PRId64 " which is already connected",
displayId);
}
void AidlComposer::removeReader(Display display) {
bool wasErased = mReaders.erase(display);
ALOGW_IF(!wasErased,
"Attempting to remove reader for display %" PRId64 " which is not connected",
translate<int64_t>(display));
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ComposerClientWriter 的核心成员如下:
std::optional<DisplayCommand> mDisplayCommand;
std::optional<LayerCommand> mLayerCommand;
std::vector<DisplayCommand> mCommands;
const int64_t mDisplay;
2
3
4
AidlComposer 中定义了很多显示设备与图层配置的函数,当执行这些函数时,显示相关的参数插入 mDisplayCommand 中,Layer相关的参数插入 mLayerCommand 中。当配置完成,需要完成一帧的显示时,会调用 composerClientWriter 的 takePendingCommands 函数获取配置好的 Command 集合:
// /hardware/interfaces/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
std::vector<DisplayCommand> takePendingCommands() {
flushLayerCommand();
flushDisplayCommand();
std::vector<DisplayCommand> moved = std::move(mCommands);
mCommands.clear();
return moved;
}
2
3
4
5
6
7
8
flushLayerCommand 和 flushDisplayCommand 函数会将 mDisplayCommand 和 mLayerCommand 中保存的指令汇总到 mCommands 成员中,接着将 mCommands 中的成员通过 Binder 远程调用传递给 HWC 执行。
接着我们以 layer 的 buffer 配置为例分析整个过程:
AidlComposer::setLayerBuffer配置 layer 的buffer 过程:
// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
Error AidlComposer::setLayerBuffer(Display display, Layer layer, uint32_t slot,
const sp<GraphicBuffer>& buffer, int acquireFence) {
Error error = Error::NONE;
mMutex.lock_shared();
if (auto writer = getWriter(display)) {
writer->get().setLayerBuffer(translate<int64_t>(display), translate<int64_t>(layer),
slot, handle, acquireFence);
} else {
error = Error::BAD_DISPLAY;
}
mMutex.unlock_shared();
return error;
}
// /hardware/interfaces/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
void setLayerBuffer(int64_t display, int64_t layer, uint32_t slot,
const native_handle_t* buffer, int acquireFence) {
// 图层相关配置保存到 mLayerCommand 中
getLayerCommand(display, layer).buffer = getBufferCommand(slot, buffer, acquireFence);
}
LayerCommand& getLayerCommand(int64_t display, int64_t layer) {
getDisplayCommand(display);
if (!mLayerCommand.has_value() || mLayerCommand->layer != layer) {
flushLayerCommand();
mLayerCommand.emplace();
mLayerCommand->layer = layer;
}
return *mLayerCommand;
}
DisplayCommand& getDisplayCommand(int64_t display) {
if (!mDisplayCommand.has_value() || mDisplayCommand->display != display) {
LOG_ALWAYS_FATAL_IF(display != mDisplay);
flushLayerCommand();
flushDisplayCommand();
mDisplayCommand.emplace();
mDisplayCommand->display = display;
}
return *mDisplayCommand;
}
Buffer getBufferCommand(uint32_t slot, const native_handle_t* bufferHandle, int fence) {
Buffer bufferCommand;
bufferCommand.slot = static_cast<int32_t>(slot);
if (bufferHandle) bufferCommand.handle.emplace(::android::dupToAidl(bufferHandle));
if (fence > 0) bufferCommand.fence = ::ndk::ScopedFileDescriptor(fence);
return bufferCommand;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
- 当 setLayerBuffer 配置命令执行完成后,调用 executeCommands 方法将缓存的命令批量发送给 HWC 执行。
// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
Error AidlComposer::executeCommands(Display display) {
mMutex.lock_shared();
auto error = execute(display);
mMutex.unlock_shared();
return error;
}
Error AidlComposer::execute(Display display) {
auto writer = getWriter(display);
auto reader = getReader(display);
if (!writer || !reader) {
return Error::BAD_DISPLAY;
}
// takePendingCommands 函数将 mDisplayCommand 和 mLayerCommand 中保存的指令汇总到 mCommands 成员中并返回
auto commands = writer->get().takePendingCommands();
if (commands.empty()) {
return Error::NONE;
}
{ // scope for results
std::vector<CommandResultPayload> results;
// 远程调用到 HWC,批量执行命令
auto status = mAidlComposerClient->executeCommands(commands, &results);
if (!status.isOk()) {
ALOGE("executeCommands failed %s", status.getDescription().c_str());
return static_cast<Error>(status.getServiceSpecificError());
}
// 解析 HWC 的返回值
reader->get().parse(std::move(results));
}
// 异常处理
const auto commandErrors = reader->get().takeErrors();
Error error = Error::NONE;
for (const auto& cmdErr : commandErrors) {
const auto index = static_cast<size_t>(cmdErr.commandIndex);
if (index < 0 || index >= commands.size()) {
ALOGE("invalid command index %zu", index);
return Error::BAD_PARAMETER;
}
const auto& command = commands[index];
if (command.validateDisplay || command.presentDisplay || command.presentOrValidateDisplay) {
error = translate<Error>(cmdErr.errorCode);
} else {
ALOGW("command '%s' generated error %" PRId32, command.toString().c_str(),
cmdErr.errorCode);
}
}
return error;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
最后来看 ComposerClientReader 如何解析 HWC 返回的数据。ComposerClientReader 解析出的数据保存在 mReturnData 成员中:
std::unordered_map<int64_t, ReturnData> mReturnData
mReturnData 是一个 map 数据,key 是显示器ID,value 是解析出的数据。
struct ReturnData {
DisplayRequest displayRequests; // 显示请求
std::vector<ChangedCompositionLayer> changedLayers; // 合成类型变更的图层
ndk::ScopedFileDescriptor presentFence; // 呈现栅栏
std::vector<PresentFence::LayerPresentFence> layerPresentFences; // 图层呈现栅栏
std::vector<ReleaseFences::Layer> releasedLayers; // 释放栅栏的图层
PresentOrValidate::Result presentOrValidateState; // 呈现或验证状态
ClientTargetPropertyWithBrightness clientTargetProperty; // 客户端目标属性
std::vector<DisplayLuts::LayerLut> layerLuts; // 图层查找表
};
2
3
4
5
6
7
8
9
10
parse 传入的数据类型是 CommandResultPayload:
union CommandResultPayload {
/**
* Indicates an error generated by a command.
*
* If there is an error from a command, the composer should only respond
* with the CommandError, and not with other results
* (e.g. ChangedCompositionTypes).
*/
CommandError error;
/**
* Sets the layers for which the device requires a different composition
* type than had been set prior to the last call to VALIDATE_DISPLAY. The
* client must either update its state with these types and call
* ACCEPT_DISPLAY_CHANGES, or must set new types and attempt to validate
* the display again.
*/
ChangedCompositionTypes changedCompositionTypes;
/**
* Sets the display requests and the layer requests required for the last
* validated configuration.
*
* Display requests provide information about how the client must handle
* the client target. Layer requests provide information about how the
* client must handle an individual layer.
*/
DisplayRequest displayRequest;
/**
* Sets the present fence as a result of PRESENT_DISPLAY. For physical
* displays, this fence must be signaled at the vsync when the result
* of composition of this frame starts to appear (for video-mode panels)
* or starts to transfer to panel memory (for command-mode panels). For
* virtual displays, this fence must be signaled when writes to the output
* buffer have completed and it is safe to read from it.
*/
PresentFence presentFence;
/**
* Sets the release fences for device layers on this display which will
* receive new buffer contents this frame.
*
* A release fence is a file descriptor referring to a sync fence object
* which must be signaled after the device has finished reading from the
* buffer presented in the prior frame. This indicates that it is safe to
* start writing to the buffer again. If a given layer's fence is not
* returned from this function, it must be assumed that the buffer
* presented on the previous frame is ready to be written.
*
* The fences returned by this function must be unique for each layer
* (even if they point to the same underlying sync object).
*
*/
ReleaseFences releaseFences;
/**
* Sets the state of PRESENT_OR_VALIDATE_DISPLAY command.
*/
PresentOrValidate presentOrValidateResult;
/**
* The brightness parameter describes the intended brightness space of the client target buffer.
* The brightness is in the range [0, 1], where 1 is the current brightness of the display.
* When client composition blends both HDR and SDR content, the client must composite to the
* brightness space as specified by the hardware composer. This is so that adjusting the real
* display brightness may be applied atomically with compensating the client target output. For
* instance, client-compositing a list of SDR layers requires dimming the brightness space of
* the SDR buffers when an HDR layer is simultaneously device-composited.
*/
ClientTargetPropertyWithBrightness clientTargetProperty;
/**
* Sets the Lut(s) for the layers.
*
* HWC should only request Lut(s) if SurfaceFlinger does not send the Lut(s) to the HWC.
* The main use-case is like HDR10+ or Dolby Vision where there is no Lut to send from
* SurfaceFlinger.
*/
DisplayLuts displayLuts;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
解析过程如下:
// /hardware/interfaces/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
void parse(std::vector<CommandResultPayload>&& results) {
resetData();
for (auto& result : results) {
switch (result.getTag()) { // 根据 tag 区分不同的类型,具体解析函数就不看了
case CommandResultPayload::Tag::error:
parseSetError(std::move(result.get<CommandResultPayload::Tag::error>()));
break;
case CommandResultPayload::Tag::changedCompositionTypes:
parseSetChangedCompositionTypes(std::move(
result.get<CommandResultPayload::Tag::changedCompositionTypes>()));
break;
case CommandResultPayload::Tag::displayRequest:
parseSetDisplayRequests(
std::move(result.get<CommandResultPayload::Tag::displayRequest>()));
break;
case CommandResultPayload::Tag::presentFence:
parseSetPresentFence(
std::move(result.get<CommandResultPayload::Tag::presentFence>()));
break;
case CommandResultPayload::Tag::releaseFences:
parseSetReleaseFences(
std::move(result.get<CommandResultPayload::Tag::releaseFences>()));
break;
case CommandResultPayload::Tag::presentOrValidateResult:
parseSetPresentOrValidateDisplayResult(std::move(
result.get<CommandResultPayload::Tag::presentOrValidateResult>()));
break;
case CommandResultPayload::Tag::clientTargetProperty:
parseSetClientTargetProperty(std::move(
result.get<CommandResultPayload::Tag::clientTargetProperty>()));
break;
case CommandResultPayload::Tag::displayLuts:
parseSetDisplayLuts(
std::move(result.get<CommandResultPayload::Tag::displayLuts>()));
break;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40