协议
分配器
在 fuchsia.sysmem/allocator.fidl 中定义
分配系统内存缓冲区。
AllocateNonSharedCollection
代表单个客户端(也称为发起方)分配 BufferCollection,该客户端也是唯一的参与者(从 sysmem 的角度来看)。
此调用主要用于临时/测试目的。此调用会跳过 BufferCollectionToken 阶段,因此无法允许其他参与者指定其限制条件。
建议实际客户端改用 AllocateSharedCollection(),并让相关参与者直接向 sysmem 传达自己的限制。
collection_request 是 BufferCollection FIDL 通道的服务器端。客户端可以在此通道的客户端调用 SetConstraints(),然后调用 WaitForBuffersAllocated(),以指定限制条件,然后确定成功/失败并获取 BufferCollection 的 BufferCollectionInfo_2。客户端在使用 BufferCollection 时还应保持此通道的客户端端处于打开状态,并应在此通道关闭时注意到这一点,并尽快停止使用 BufferCollection。
请求
| 名称 | 类型 |
|---|---|
collection_request |
server_end:BufferCollection
|
AllocateSharedCollection
创建一个逻辑 BufferCollectionToken,该令牌可在参与者之间共享(使用 BufferCollectionToken.Duplicate()),然后使用 BindSharedCollection() 转换为 BufferCollection。
是否成功使用缓冲区填充 BufferCollection 是通过 BufferCollection 接口确定的。
请求
| 名称 | 类型 |
|---|---|
token_request |
server_end:BufferCollectionToken
|
BindSharedCollection
将 BufferCollectionToken 转换为与逻辑 BufferCollection 的连接。BufferCollection 尚未填充缓冲区 - 参与者还必须先通过 buffer_collection 的客户端发送 SetConstraints()。
必须先通过 BindSharedCollection() 提交从通过 AllocateSharedCollection() 创建的逻辑 BufferCollectionToken 复制的所有 BufferCollectionToken,然后逻辑 BufferCollection 才会填充缓冲区。
token:通道的客户端端点,其服务器端已使用 AllocateSharedCollection 发送到 sysmem,或其服务器端已使用 BufferCollectionToken.Duplicate() 发送到 sysmem。令牌正在“交换”为指向逻辑 BufferCollection 的通道。
buffer_collection_request BufferCollection 通道的服务器端。发送方照常保留客户端。BufferCollection 通道是单个参与者与逻辑 BufferCollection 的连接。通常会有其他参与者,他们拥有自己的 BufferCollection 通道,可连接到逻辑 BufferCollection。
请求
| 名称 | 类型 |
|---|---|
token |
client_end:BufferCollectionToken
|
buffer_collection_request |
server_end:BufferCollection
|
ConnectToSysmem2Allocator
这样,您就可以在给定 sysmem(1) Allocator 的情况下创建 sysmem2 Allocator。
这主要适用于以下情况:库代码被分配了 sysmem(1) 分配器,但库代码已更新为使用 sysmem2。通常,库会提供一种方法来传入 sysmem2 Allocator,但客户端代码并不总是在同一个代码库中,因此此消息允许库暂时仍接受 sysmem(1) 分配器。
通过 SetDebugClientInfo 设置的信息(如果有)会复制到 sysmem2 Allocator。
请求
| 名称 | 类型 |
|---|---|
allocator_request |
server_end:fuchsia.sysmem2/Allocator
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可使用这些信息来帮助调试泄漏的内存和等待约束时挂起的问题。|name| 可以是任意字符串,但当前进程名称(请参阅 fsl::GetCurrentProcessName())是一个不错的默认值。|id| 可以是任意 ID,但当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())是一个不错的默认值。
此信息会传播到使用此分配器中的 BindSharedCollection() 或 AllocateNonSharedCollection() 创建的所有 BufferCollection。它不会影响 BufferCollectionToken,因为这些令牌通常会跨进程传递,并且其名称应手动管理。
请求
| 名称 | 类型 |
|---|---|
name |
string:64
|
id |
uint64
|
ValidateBufferCollectionToken
验证 sysmem 服务器是否知道 BufferCollectionToken。
如果客户端代码希望提前知道传入令牌是否有效(到目前为止),则可以在 BufferCollectionToken.Duplicate() + BufferCollectionToken.Sync() 之后才调用 BindSharedCollection() 的情况下使用此方法。
对 sysmem 未知的令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永远挂起。
鉴于传入令牌可能随时失效(如果任何参与者丢弃其 BufferCollectionToken 或 BufferCollection),建议客户端代码的作者考虑不调用 ValidateBufferCollectionToken(),而是在所有 BufferCollectionToken.Duplicate() 和 BindSharedCollection() 之后(在将任何重复令牌发送到其他进程之前)处理 BufferCollection.Sync() 的异步失败。
无论此调用的结果如何,此调用都不会对具有引用 koid 的令牌产生任何影响。
此调用返回 true 结果并不能保证令牌在之后的任何时间内都保持有效。
客户端代码将在客户端的令牌句柄上执行 zx_object_get_info(),传递 ZX_INFO_HANDLE_BASIC 并返回 related_koid,然后将其传递给 ValidateBufferCollectionToken()。
如果 ValidateBufferCollectionToken() 返回 true,则表示在 sysmem 服务器处理调用时,令牌是已知的,但在客户端代码收到响应时,令牌可能不再有效/已知。
如果 ValidateBufferCollectionToken() 返回 false,则表示在 sysmem 服务器处理调用时,令牌未知,但当客户端代码收到响应时,令牌可能已变为已知。不过,客户端代码无需降低令牌可能较晚才被知晓的可能性,因为令牌的来源应在将令牌发送到客户端代码之前,将令牌同步到 sysmem。
如果调用 ValidateBufferCollectionToken() 失败,FIDL 层会返回 zx_status_t。
token_server_koid:通道(可能是 BufferCollectionToken 通道)服务器端的 koid。这可以通过 zx_object_get_info() ZX_INFO_HANDLE_BASIC related_koid 获取。
请求
| 名称 | 类型 |
|---|---|
token_server_koid |
zx/Koid
|
响应
| 名称 | 类型 |
|---|---|
is_known |
bool
|
BufferCollection
在 fuchsia.sysmem/collection.fidl 中定义
BufferCollection 是从参与者到 sysmem 的直接连接,即逻辑 BufferCollection;通常,逻辑 BufferCollection 会与其他参与者共享。换句话说,BufferCollection 接口的实例是“逻辑缓冲区集合”的视图。
此连接的存在是为了便于异步指示何时已使用缓冲区填充逻辑 BufferCollection。
此外,服务器关闭通道向客户端表明,客户端应尽快关闭从 BufferCollection 获取的所有 VMO 句柄。
此外,此接口将来可能允许以其他方式指定限制条件,并且可能允许在一定程度上来回协商限制条件。
此接口未来可能允许每个 BufferCollection 具有 64 个以上的 VMO 句柄,但目前限制为 64 个。
此接口将来可能允许分配/取消分配单个缓冲区。
某些发起方可能会等待一小段时间,直到所有旧的逻辑 BufferCollection VMO 句柄都已关闭(或直到该小段时间超时),然后再分配新的 BufferCollection,以帮助控制物理内存碎片并避免新旧集合的缓冲区分配生命周期重叠。集合可能很大,因此值得避免分配重叠(在时间上)。
AttachLifetimeTracking
AttachLifetimeTracking:
AttachLifetimeTracking() 旨在让客户端在尝试分配新的逻辑缓冲区集合之前,等待旧的逻辑缓冲区集合完全或大部分解除分配。
将 eventpair 端点附加到逻辑缓冲区集合,以便在分配的缓冲区数量降至“buffers_remaining”时关闭 server_end。在逻辑分配完成之前,server_end 不会关闭。
如果逻辑分配失败(例如,对于附加的子树 [使用 AttachToken()]),则无论在整个逻辑缓冲区集合中可能分配了多少个缓冲区,server_end 都会在该失败期间关闭。
此事件指示的生命周期包括已分配缓冲区的异步清理,并且只有在缓冲区的所有 VMO 句柄持有者都关闭这些 VMO 句柄后,才能进行此异步清理。 因此,客户端应注意避免永远等待 ZX_EVENTPAIR_PEER_CLOSED 信号,尤其是在使用逻辑缓冲区集合的任何参与者不太可信或不太可靠的情况下。
buffers_remaining 参数允许等待除 buffers_remaining 缓冲区之外的所有缓冲区完全解除分配。在已知数量的缓冲区有意不关闭以便数据可以继续使用的情况下,这可能很有用,例如,即使视频流使用的是受保护的输出缓冲区,也可以在界面中显示最后一个可用的视频画面。确定在不关闭的情况下可以保留多少个缓冲区超出了 BufferCollection 接口的范围(至少目前是这样),但通常在 0-2 范围内。
此机制旨在与其他提供类似 AttachLifetimeTracking() 机制的协议兼容,因为同一事件的副本可以发送到多个 AttachLifetimeTracking(),并且当所有生命周期结束条件都满足时(副本的所有持有者都已关闭其句柄),系统会发出 ZX_EVENTPAIR_PEER_CLOSED 信号。
无法取消附加。关闭事件对的客户端端不会减少待处理附加的数量。
关闭客户端不会导致服务器执行任何操作。 如果服务器确实会监听来自客户端的事件,则仅用于调试日志记录。
服务器有意不“信任”客户端发出的任何位信号。此机制有意仅使用 ZX_EVENTPAIR_PEER_CLOSED,该事件无法提前触发,只有在 server_end 的所有句柄都关闭时才会触发。任何其他信号位都没有关联的含义,客户端应在功能上忽略事件对或其对等端任一端的任何其他信号位。
server_end 可能缺少 ZX_RIGHT_SIGNAL 或 ZX_RIGHT_SIGNAL_PEER,但必须具有 ZX_RIGHT_DUPLICATE(并且必须具有 ZX_RIGHT_TRANSFER 才能进行传输,而不会导致 CodecFactory 通道故障)。
请求
| 名称 | 类型 |
|---|---|
server_end |
handle<eventpair>
|
buffers_remaining |
uint32
|
AttachToken
如果现有集合的缓冲区计数、限制和参与者允许,则创建一个新令牌,以尝试向现有集合添加新参与者。
这对于替换失败的参与者和/或在分配缓冲区后添加/重新添加参与者非常有用。
附加令牌 / 集合的失败不会传播到附加令牌的父级。失败确实会从可有可无的令牌的普通子级传播到可有可无的令牌。如果子节点已附加,或者子节点可有可无且故障发生在逻辑分配之后,则子节点的故障不会影响其父节点。
在某些情况下,发起方可能会选择最初为参与者的给定实例使用可有可无的令牌,然后,如果该参与者的第一个实例失败,则该参与者的新第二个实例可能会获得使用 AttachToken() 创建的令牌。
从 BufferCollectionToken 通道的客户端角度来看,该令牌与其他任何令牌一样。客户端可以根据需要 Duplicate() 令牌,并可以将令牌发送到其他进程。应通过调用 BindSharedCollection() 将令牌正常转换为 BufferCollection 通道。应在该 BufferCollection 通道上调用 SetConstraints()。
WaitForBuffersAllocated() 返回成功结果意味着,使用已存在的缓冲区集合、已建立的 BufferCollectionInfo(包括图片格式限制条件)以及已存在的其他参与者及其缓冲区计数,可以满足新参与者的限制条件。失败结果意味着,使用现有缓冲区集合及其已在逻辑上分配的参与者无法满足新参与者的限制条件。如果改用 SetDispensable() 代替 AttachToken(),或者使用普通令牌,则创建新集合可能会满足所有参与者的限制条件。
使用 AttachToken() 创建的令牌会与当前对缓冲区集合生效的所有限制、正在考虑的附加令牌以及附加令牌下的子令牌(这些子令牌本身不是附加令牌,也不在附加令牌下)一起执行限制聚合。
buffer_count 到 min_buffer_count_for_camping 等的分配遵循先到先得原则,但从逻辑上讲,在所有父级发送 SetConstraints() 之前,子级无法进行分配。
另请参阅 SetDispensable(),与 AttachToken() 相比,它会让创建的令牌 + 子令牌与其父令牌一起参与限制条件汇总。
新创建的令牌需要先 Sync() 到 sysmem,然后才能传递给 BindSharedCollection()。新令牌的 Sync() 可以通过对此 BufferCollection 执行 BufferCollection.Sync() 来完成。或者,也可以对新令牌使用 BufferCollectionToken.Sync()。在通过新创建的令牌发送任何 BufferCollectionToken.Duplicate() 消息后,可以启动 BufferCollectionToken.Sync(),以便通过一次往返将这些额外的令牌同步到 sysmem。
这些 rights_attenuation_mask 值不会导致衰减(请注意,0 不在此列表中;0 会向系统日志输出 ERROR,以帮助诊断客户端代码中的 bug):
- ZX_RIGHT_SAME_RIGHTS(首选)
- 0xFFFFFFFF(在计算衰减掩码时,此值是合理的)
请求
| 名称 | 类型 |
|---|---|
rights_attenuation_mask |
uint32
|
token_request |
server_end:BufferCollectionToken
|
CheckBuffersAllocated
如果缓冲区集合已分配或失败,则返回与 WaitForBuffersAllocated 相同的结果代码;如果 WaitForBuffersAllocated 会阻塞,则返回 ZX_ERR_UNAVAILABLE。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
status |
zx/Result
|
关闭
在 BufferCollectionToken 频道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地 Close() 令牌(然后立即或稍后关闭通道,以响应服务器关闭其端),从而避免导致逻辑缓冲区集合失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,如果 BufferCollection 发生意外故障,服务器会使整个逻辑缓冲区集合发生故障。部分原因是为了在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者希望完全关闭 BufferCollection 视图而不导致逻辑缓冲区集合失败,则可以在关闭 BufferCollection 通道的客户端之前发送 Close()。如果这是最后一个 BufferCollection 视图,则逻辑缓冲区集合仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前发生,则缓冲区集合不需要此节点的限制条件即可进行分配。如果在 SetConstraints() 之后,即使没有通道连接,约束条件也会保留并与任何后续逻辑分配一起汇总。
在 BufferCollectionTokenGroup 渠道上:
默认情况下,BufferCollectionTokenGroup 的意外故障会触发逻辑 BufferCollectionTokenGroup 的故障,并将故障传播到其父级。如需关闭 BufferCollectionTokenGroup 逻辑分组通道,而不导致逻辑分组失败或传播失败,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,则尽管有 Close(),逻辑缓冲区集合仍会失败(因为 sysmem 无法确定是否已创建所有相关子项,因此不确定是否会向 sysmem 提供所有相关限制条件)。如果 Close() 发生在 AllChildrenPresent() 之后,则子级及其所有限制条件将保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
GetNodeRef
这会获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端不会获得发出此事件信号的权利,因为此句柄只能用作客户端从该节点获取此句柄的证明。
由于这是 get 而不是 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能在不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
IsAlternateFor
此方法会检查调用节点是否位于以公共父级 BufferCollectionTokenGroup 的不同子令牌为根的子树中(相对于传入的 node_ref)。
此调用用于协助准入控制去重和调试。
node_ref 必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时都调用 GetNodeRef()。
如果调用令牌可能根本不是有效令牌(因为令牌提供程序可能具有敌意/不受信任),请先调用 ValidateBufferCollectionToken(),而不是在 IsAlternateFor() 永远不响应时无限期地卡住(因为调用令牌不是真实令牌,即未真正与 sysmem 通信)。另一种方法是先使用此令牌调用 BindSharedCollection,这也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示在与调用节点相同的逻辑缓冲区集合中找不到 node_ref。在逻辑分配之前,且在同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 都会至少持续存在到逻辑分配(包括已执行 Close() 并关闭其通道的节点),并且要返回 ZX_ERR_NOT_FOUND,此节点的通道仍需在服务器端连接,如果整个逻辑分配失败,则不会出现这种情况。在逻辑分配之后或在不同的逻辑分配子树中,此错误还有其他潜在原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此节点的逻辑分配分开)可能会导致其子树删除这些节点,或者可能存在 BufferCollectionTokenGroup,并且可能会选择与 node_ref 所在子树不同的子树,从而导致删除 node_ref 节点。只有在以下情况下,sysmem 才会在节点没有对应通道后保留该节点:使用了 Close() 且节点的子树尚未失败。 导致此错误的另一个原因是,node_ref 是具有足够权限的 eventpair 句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是 eventpair 句柄,或者不具有实际 node_ref 上所需的权限。
此调用不会返回任何其他失败状态代码。不过,sysmem 可能会在未来添加其他代码,因此客户端应针对任何失败状态代码提供合理的默认处理。
如果成功,is_alternate 的含义如下:
- true - 调用节点和 node_ref 节点之间的第一个共同父节点是 BufferCollectionTokenGroup。这意味着, 调用节点和 node_ref 节点不会同时应用其 约束条件,而是 sysmem 会选择其中一个 约束条件,而不会同时选择这两个约束条件。这是因为在逻辑分配期间,系统只会选择 BufferCollectionTokenGroup 的一个子级,并且只有该子级的子树会参与约束条件聚合。
- false - 调用节点与 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同父节点是 BufferCollectionToken 或 BufferCollection(无论是否已 Close())。这意味着,如果所涉及的任何父级 BufferCollectionTokenGroup 都选择了这两个节点,则调用节点和 node_ref 节点可能会在逻辑分配的约束条件汇总期间应用其约束条件。在这种情况下,没有任何 BufferCollectionTokenGroup 会直接阻止两个节点同时被选中且其约束条件同时被汇总,但即使为 false,如果一个或两个节点具有直接或间接父级 BufferCollectionTokenGroup,且该父级 BufferCollectionTokenGroup 选择的子级子树不是包含调用节点或 node_ref 节点的子树,则一个或两个节点仍可能被排除在考虑范围之外。
请求
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
响应
| 名称 | 类型 |
|---|---|
payload |
Node_IsAlternateFor_Result
|
SetConstraints
向逻辑 BufferCollection 提供 BufferCollectionConstraints。
参与者只能调用 SetConstraints() 一次。
有时,发起方只是一个参与者,只想关注成功/失败以填充缓冲区,并在失败时关注 zx.Status。在这种情况下,has_constraints 可以为 false,并且 constraints 将被忽略。
系统不会向发送 null 约束条件的客户端提供 VMO 句柄 - 对于不需要 VMO 句柄的发起方,这可能是故意的。没有 VMO 句柄并不会阻止发起方调整缓冲区的哪个部分被视为有效等,但发起方无法保持 VMO 句柄处于打开状态,以防止逻辑 BufferCollection 在需要消失时(无论发起方的参与程度如何,也无论出于何种原因)进行清理。
如需尝试填充缓冲区,BufferCollection 客户端通道的所有持有者都需要先调用 SetConstraints(),然后 sysmem 才会尝试分配缓冲区。
has_constraints 如果为 false,则约束条件实际上为 null,并且 constraints 会被忽略。null 约束条件的发送方不会在 BufferCollectionInfo 中获得任何 VMO 句柄,但仍可以了解分配了多少个缓冲区,并且仍可以通过 buffer_index 引用缓冲区。
constraints 是对缓冲区集合的限制。
请求
| 名称 | 类型 |
|---|---|
has_constraints |
bool
|
constraints |
BufferCollectionConstraints
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可使用这些信息来帮助调试泄漏的内存和等待约束时挂起的问题。|name| 可以是任意字符串,但当前进程名称(请参阅 fsl::GetCurrentProcessName())是一个不错的默认值。|id| 可以是任意 ID,但当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())是一个不错的默认值。
在启用详细日志记录时(请参阅 SetVerboseLogging()),此名称还用于指明哪个客户端首先关闭其通道,从而导致子树失败(如果子树的目的已达到,这可能是正常的,但如果发生的时间早于预期,则从 sysmem 的角度来看,客户端通道专用名称有助于诊断故障首先来自何处)。
默认情况下(除非被此消息覆盖或使用 Allocator.SetDebugClientInfo()),节点会在创建子节点时从其父节点复制信息。虽然这比什么都不做要好,但每个参与者最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 来使信息与当前客户端直接相关。此外,如果怀疑某个节点包含从其父节点复制的信息,则可以使用 SetVerboseLogging() 来帮助消除歧义。
请求
| 名称 | 类型 |
|---|---|
name |
string:64
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制,Sysmem 会记录一条警告。客户端可以调用此方法来更改日志的输出时间。如果多个客户端设置了截止期限,则无法指定哪个截止期限会生效。
请求
| 名称 | 类型 |
|---|---|
deadline |
zx/Time
|
SetName
为此缓冲区集合中的 VMO 设置名称。名称可能会被截断。该名称仅影响设置后分配的 VMO,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值较大的客户端将胜出。
请求
| 名称 | 类型 |
|---|---|
priority |
uint32
|
name |
string:64
|
SetVerboseLogging
详细日志记录包括通过每个客户端的 SetConstraints() 设置的限制条件、通过 SetDebugClientInfo() 设置的信息以及节点树的结构。
通常,当聚合失败时,sysmem 只会输出一行投诉,其中仅包含聚合失败的具体详细原因,而上下文信息极少。如果只做了一处小改动,并且系统在改动之前一直正常运行,那么这通常足以诊断问题,但对于让新的缓冲区集合首次正常运行,这通常没有特别大的帮助。尤其是在涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树时,详细日志记录可能有助于诊断树的外观以及逻辑分配失败的原因,或者树或子树比预期更早失败的原因。
从性能角度来看,如果仅在少量缓冲区集合上启用,则额外日志记录的意图是可以接受的。如果我们没有在跟踪 bug,就不应该发送此消息。
如果太多参与者让详细日志记录保持启用状态,我们最终可能需要通过其他设置允许系统级 sysmem 详细日志记录,以避免 sysmem 因这条消息而过多地向日志发送垃圾内容。
对于某些节点,这可能是 NOP,因为与节点关联的有意政策,如果我们不信任节点,无法让其开启详细日志记录。
请求
<EMPTY>
同步
确保服务器端已收到之前的消息,包括令牌、集合或群组上的 Duplicate() 消息。
对不是/曾不是有效 sysmem 令牌的令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永远挂起。请参阅 ValidateBufferCollectionToken(),了解如何以一次往返为代价来降低出现恶意/虚假 BufferCollectionToken 的可能性。 另一种方法是将令牌传递给 BindSharedCollection(),该方法也会在将令牌交换为 BufferCollection 通道时验证令牌,然后便可使用 BufferCollection Sync()。
在 Sync() 之后,可以安全地将 token_request 的客户端发送给另一个参与者,因为知道当另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括:等待每个 token.Duplicate() 单独完成(在每个 token.Duplicate() 之后单独调用 token.Sync()),或在通过 BindSharedCollection() 提交令牌后对 BufferCollection 调用 Sync()。
另一种缓解方法是避免对令牌调用 Sync(),而是在原始令牌无效时,稍后处理 BufferCollection.Sync() 的潜在故障。从性能角度来看,此选项可能更可取,但需要客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将复制的令牌转换为 BufferCollection 并收到来自 BufferCollection.Sync() 的成功响应。
请尽可能改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,则调用方必须已经知道此令牌有效/曾经有效,否则 BufferCollectionToken.Sync() 可能会永远挂起。如果令牌尚未被确认为有效,请先参阅 ValidateBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
WaitForBuffersAllocated
当缓冲区已分配时,此请求会完成;如果已尝试分配但失败,则会返回一些失败详细信息。
必须先满足以下条件,然后系统才会分配缓冲区:
- 逻辑 BufferCollectionToken 的所有 BufferCollectionToken 都必须通过 BindSharedCollection() 提交。
- 逻辑 BufferCollection 的所有 BufferCollection 都必须已收到 SetConstraints()。
如果成功,则返回 ZX_OK。
如果请求有效,但由于资源耗尽而无法执行,则返回 ZX_ERR_NO_MEMORY。如果调用方无权获取其请求的缓冲区,则返回 ZX_ERR_ACCESS_DENIED。
如果请求格式不正确,则返回 ZX_ERR_INVALID_ARGS。
如果请求有效但无法满足(可能是由于硬件限制),则返回 ZX_ERR_NOT_SUPPORTED。
buffer_collection_info 包含 VMO 句柄和其他相关信息。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
status |
zx/Result
|
buffer_collection_info |
BufferCollectionInfo_2
|
BufferCollectionToken
在 fuchsia.sysmem/collection.fidl 中定义
BufferCollectionToken 不是 BufferCollection,而是在分配 BufferCollection 之前识别潜在共享 BufferCollection 的一种方式。
我们为 BufferCollectionToken 使用通道,而不是单个事件对(对),因为这样我们可以检测错误情况,例如参与者在创建过程中死亡。
fuchsia.sysmem.BufferCollectionToken 类型尚未弃用,因为它在其他一些协议中使用(目前),但 fuchsia.sysmem.BufferCollectionToken 的所有内部内容均已弃用。令牌通道同时提供 fuchsia.sysmem.BufferCollectionToken 和 fuchsia.sysmem2.BufferCollectionToken。
一旦其他协议将其令牌字段切换到 fuchsia.sysmem2.BufferCollectionToken,此协议将被弃用。
关闭
在 BufferCollectionToken 频道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地 Close() 令牌(然后立即或稍后关闭通道,以响应服务器关闭其端),从而避免导致逻辑缓冲区集合失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,如果 BufferCollection 发生意外故障,服务器会使整个逻辑缓冲区集合发生故障。部分原因是为了在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者希望完全关闭 BufferCollection 视图而不导致逻辑缓冲区集合失败,则可以在关闭 BufferCollection 通道的客户端之前发送 Close()。如果这是最后一个 BufferCollection 视图,则逻辑缓冲区集合仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前发生,则缓冲区集合不需要此节点的限制条件即可进行分配。如果在 SetConstraints() 之后,即使没有通道连接,约束条件也会保留并与任何后续逻辑分配一起汇总。
在 BufferCollectionTokenGroup 渠道上:
默认情况下,BufferCollectionTokenGroup 的意外故障会触发逻辑 BufferCollectionTokenGroup 的故障,并将故障传播到其父级。如需关闭 BufferCollectionTokenGroup 逻辑分组通道,而不导致逻辑分组失败或传播失败,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,则尽管有 Close(),逻辑缓冲区集合仍会失败(因为 sysmem 无法确定是否已创建所有相关子项,因此不确定是否会向 sysmem 提供所有相关限制条件)。如果 Close() 发生在 AllChildrenPresent() 之后,则子级及其所有限制条件将保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
CreateBufferCollectionTokenGroup
大多数 sysmem 客户端和许多参与者通常不需要关注此消息或 BufferCollectionTokenGroup。
BufferCollectionTokenGroup 用于在 N 个子令牌之间创建 N 选 1 的 OR 关系。未在汇总期间选择的子令牌将失败(关闭),潜在参与者应在其 BufferCollection 通道客户端端点看到 PEER_CLOSED 时注意到这一点,从而允许参与者清理最终未发生的推测性使用(类似于正常的 BufferCollection 服务器端在逻辑缓冲区集合失败时关闭)。
请参阅 BufferCollectionTokenGroup 协议的相关注释。
要应用于整个群组的任何 rights_attenuation_mask 或 AttachToken()/SetDispensable() 都可以通过为此目的而创建的令牌(作为群组的直接父级)来实现。
group_request - 由 sysmem 提供服务的 BufferCollectionTokenGroup 通道的服务器端。
请求
| 名称 | 类型 |
|---|---|
group_request |
server_end:BufferCollectionTokenGroup
|
复制
此方法可用于在创建共享 BufferCollection 之前添加参与者。只有在对性能敏感的情况下,才应使用它来代替 DuplicateSync,因为在这些情况下,不希望在每次复制时都等待 sysmem 响应。
在发送一条或多条 Duplicate() 消息后,以及在将创建的令牌发送给其他参与者(或其他分配器通道)之前,客户端应发送 Sync() 并等待其响应。Sync() 调用可以在令牌上进行,也可以在通过将此令牌传递给 BindSharedCollection() 获取的 BufferCollection 上进行。无论哪种方式,都能确保服务器在其他参与者通过单独的分配器通道将令牌发送到服务器之前,知道通过 Duplicate() 创建的令牌。
所有令牌都必须通过 BindSharedCollection() 或 Close() 提交,才能成功创建 BufferCollection。
当客户端调用 BindSharedCollection() 来提交 BufferCollectionToken 时,服务器会先处理所有 Duplicate() 消息,然后再关闭 BufferCollectionToken。这样,客户端就可以使用 BindSharedCollection 复制并立即提交 BufferCollectionToken,然后将 token_request 的客户端端点转移给另一个参与者。服务器会注意到 token_request 的存在,然后才会认为此 BufferCollectionToken 已完全关闭。
此掩码中为零的 rights_attenuation_mask 权限位将不会出现在可通过 token_request 的客户端端点获取的缓冲区 VMO 权限中。这样,发起方或中间参与方就可以削弱参与方可用的权限。这不会让参与者获得其尚未拥有的权限。值 ZX_RIGHT_SAME_RIGHTS 可用于指定不应应用任何衰减。
以下 rights_attenuation_mask 值不会导致衰减:
- ZX_RIGHT_SAME_RIGHTS(首选)
- 0xFFFFFFFF(在计算衰减掩码时,此值是合理的)
- 0(已弃用 - 请勿使用 0 - 否则系统会将 ERROR 写入日志)
token_request 是 BufferCollectionToken 通道的服务器端。
此通道的客户端充当创建共享 BufferCollection 的另一个参与者。
请求
| 名称 | 类型 |
|---|---|
rights_attenuation_mask |
uint32
|
token_request |
server_end:BufferCollectionToken
|
DuplicateSync
此方法可用于在创建共享 BufferCollection 之前添加更多参与者。系统会为 rights_attenuation_masks 数组中的每个条目返回一个新令牌。返回值是每个新参与者令牌的客户端端点。
如果调用令牌可能根本不是有效令牌(因为令牌提供程序可能具有敌意/不受信任),请考虑先使用 ValidateBufferCollectionToken(),而不是在 DuplicateSync() 因调用令牌不是真实令牌而从未响应时可能无限期卡住。
与 Duplicate() 不同,调用此方法后无需 Sync()(请参阅“协议节点”)。
所有令牌都必须通过 BindSharedCollection() 或 Close() 提交,才能成功创建 BufferCollection。
在 rights_attenuation_masks 的每个条目中,值为零的权限位在通过相应返回令牌可获取的缓冲区 VMO 权限中将不存在。这样,发起方或中间参与方就可以削弱参与方可用的权限。这不会让参与者获得其尚未拥有的权限。值 ZX_RIGHT_SAME_RIGHTS 可用于指定不应应用任何衰减。
请求
| 名称 | 类型 |
|---|---|
rights_attenuation_masks |
vector<zx/Rights>:64
|
响应
| 名称 | 类型 |
|---|---|
tokens |
vector<client_end:BufferCollectionToken>:64
|
GetNodeRef
这会获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端不会获得发出此事件信号的权利,因为此句柄只能用作客户端从该节点获取此句柄的证明。
由于这是 get 而不是 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能在不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
IsAlternateFor
此方法会检查调用节点是否位于以公共父级 BufferCollectionTokenGroup 的不同子令牌为根的子树中(相对于传入的 node_ref)。
此调用用于协助准入控制去重和调试。
node_ref 必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时都调用 GetNodeRef()。
如果调用令牌可能根本不是有效令牌(因为令牌提供程序可能具有敌意/不受信任),请先调用 ValidateBufferCollectionToken(),而不是在 IsAlternateFor() 永远不响应时无限期地卡住(因为调用令牌不是真实令牌,即未真正与 sysmem 通信)。另一种方法是先使用此令牌调用 BindSharedCollection,这也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示在与调用节点相同的逻辑缓冲区集合中找不到 node_ref。在逻辑分配之前,且在同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 都会至少持续存在到逻辑分配(包括已执行 Close() 并关闭其通道的节点),并且要返回 ZX_ERR_NOT_FOUND,此节点的通道仍需在服务器端连接,如果整个逻辑分配失败,则不会出现这种情况。在逻辑分配之后或在不同的逻辑分配子树中,此错误还有其他潜在原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此节点的逻辑分配分开)可能会导致其子树删除这些节点,或者可能存在 BufferCollectionTokenGroup,并且可能会选择与 node_ref 所在子树不同的子树,从而导致删除 node_ref 节点。只有在以下情况下,sysmem 才会在节点没有对应通道后保留该节点:使用了 Close() 且节点的子树尚未失败。 导致此错误的另一个原因是,node_ref 是具有足够权限的 eventpair 句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是 eventpair 句柄,或者不具有实际 node_ref 上所需的权限。
此调用不会返回任何其他失败状态代码。不过,sysmem 可能会在未来添加其他代码,因此客户端应针对任何失败状态代码提供合理的默认处理。
如果成功,is_alternate 的含义如下:
- true - 调用节点和 node_ref 节点之间的第一个共同父节点是 BufferCollectionTokenGroup。这意味着, 调用节点和 node_ref 节点不会同时应用其 约束条件,而是 sysmem 会选择其中一个 约束条件,而不会同时选择这两个约束条件。这是因为在逻辑分配期间,系统只会选择 BufferCollectionTokenGroup 的一个子级,并且只有该子级的子树会参与约束条件聚合。
- false - 调用节点与 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同父节点是 BufferCollectionToken 或 BufferCollection(无论是否已 Close())。这意味着,如果所涉及的任何父级 BufferCollectionTokenGroup 都选择了这两个节点,则调用节点和 node_ref 节点可能会在逻辑分配的约束条件汇总期间应用其约束条件。在这种情况下,没有任何 BufferCollectionTokenGroup 会直接阻止两个节点同时被选中且其约束条件同时被汇总,但即使为 false,如果一个或两个节点具有直接或间接父级 BufferCollectionTokenGroup,且该父级 BufferCollectionTokenGroup 选择的子级子树不是包含调用节点或 node_ref 节点的子树,则一个或两个节点仍可能被排除在考虑范围之外。
请求
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
响应
| 名称 | 类型 |
|---|---|
payload |
Node_IsAlternateFor_Result
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可使用这些信息来帮助调试泄漏的内存和等待约束时挂起的问题。|name| 可以是任意字符串,但当前进程名称(请参阅 fsl::GetCurrentProcessName())是一个不错的默认值。|id| 可以是任意 ID,但当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())是一个不错的默认值。
在启用详细日志记录时(请参阅 SetVerboseLogging()),此名称还用于指明哪个客户端首先关闭其通道,从而导致子树失败(如果子树的目的已达到,这可能是正常的,但如果发生的时间早于预期,则从 sysmem 的角度来看,客户端通道专用名称有助于诊断故障首先来自何处)。
默认情况下(除非被此消息覆盖或使用 Allocator.SetDebugClientInfo()),节点会在创建子节点时从其父节点复制信息。虽然这比什么都不做要好,但每个参与者最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 来使信息与当前客户端直接相关。此外,如果怀疑某个节点包含从其父节点复制的信息,则可以使用 SetVerboseLogging() 来帮助消除歧义。
请求
| 名称 | 类型 |
|---|---|
name |
string:64
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制,Sysmem 会记录一条警告。客户端可以调用此方法来更改日志的输出时间。如果多个客户端设置了截止期限,则无法指定哪个截止期限会生效。
请求
| 名称 | 类型 |
|---|---|
deadline |
zx/Time
|
SetDispensable
在逻辑上分配缓冲区后,可丢弃令牌可能会失败,而不会导致其父级(如果有)失败。
在逻辑缓冲区分配之前,可有可无的令牌会与其父级一起参与限制条件汇总。如果可丢弃令牌在逻辑上分配缓冲区之前失败,则失败会传播到可丢弃令牌的父级。
在逻辑上分配缓冲区后,可分配令牌(或可分配令牌的任何子级)的故障不会传播到可分配令牌的父级。失败确实会从可有可无的令牌的普通子级传播到可有可无的令牌。如果子节点已附加,或者子节点可有可无且故障发生在逻辑分配之后,则子节点的故障不会影响其父节点。
在以下情况下,可以使用可有可无的令牌:参与者需要提供限制,但在分配缓冲区后,参与者可能会失败,而不会导致父级视角下的缓冲区收集失败。
相比之下,AttachToken() 可用于创建不与其父级参与约束条件汇总的令牌,其在任何时候的失败都不会传播到其父级,并且其延迟提供约束条件不会阻止父级完成其缓冲区分配。
在某些情况下,发起方可能会选择最初为参与者的给定实例使用可有可无的令牌,然后,如果该参与者的第一个实例失败,则该参与者的新第二个实例可能会获得使用 AttachToken() 创建的令牌。
如果客户端使用此消息,则不应依赖客户端自己的 BufferCollectionToken 或 BufferCollection 通道,因为客户端已通过 SetDispensable() 将任何 BufferCollectionToken 或 BufferCollection 提供给其他进程,这些进程可能会突然发生故障,导致通道从服务器端关闭。因此,客户端应格外注意通过其他方式发现该其他进程的失败。
虽然可以(并且可能有用)在 BufferCollectionTokenGroup 的直接子级上调用 SetDispensable(),但之后无法使用 AttachToken() 将作为群组直接子级的失败可丢弃令牌替换为新令牌(因为群组上没有 AttachToken())。在这种情况下,如需启用 AttachToken() 替换,请创建一个额外的非可丢弃令牌(节点),该令牌是组的直接子级,并将现有的可丢弃令牌设为该额外令牌(节点)的子级。这样,作为组的直接子级的额外令牌(节点)就具有 BufferCollection.AttachToken(),可用于替换失败的可选令牌。
对已可丢弃的令牌调用 SetDispensable() 是幂等的。
请求
<EMPTY>
SetName
为此缓冲区集合中的 VMO 设置名称。名称可能会被截断。该名称仅影响设置后分配的 VMO,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值较大的客户端将胜出。
请求
| 名称 | 类型 |
|---|---|
priority |
uint32
|
name |
string:64
|
SetVerboseLogging
详细日志记录包括通过每个客户端的 SetConstraints() 设置的限制条件、通过 SetDebugClientInfo() 设置的信息以及节点树的结构。
通常,当聚合失败时,sysmem 只会输出一行投诉,其中仅包含聚合失败的具体详细原因,而上下文信息极少。如果只做了一处小改动,并且系统在改动之前一直正常运行,那么这通常足以诊断问题,但对于让新的缓冲区集合首次正常运行,这通常没有特别大的帮助。尤其是在涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树时,详细日志记录可能有助于诊断树的外观以及逻辑分配失败的原因,或者树或子树比预期更早失败的原因。
从性能角度来看,如果仅在少量缓冲区集合上启用,则额外日志记录的意图是可以接受的。如果我们没有在跟踪 bug,就不应该发送此消息。
如果太多参与者让详细日志记录保持启用状态,我们最终可能需要通过其他设置允许系统级 sysmem 详细日志记录,以避免 sysmem 因这条消息而过多地向日志发送垃圾内容。
对于某些节点,这可能是 NOP,因为与节点关联的有意政策,如果我们不信任节点,无法让其开启详细日志记录。
请求
<EMPTY>
同步
确保服务器端已收到之前的消息,包括令牌、集合或群组上的 Duplicate() 消息。
对不是/曾不是有效 sysmem 令牌的令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永远挂起。请参阅 ValidateBufferCollectionToken(),了解如何以一次往返为代价来降低出现恶意/虚假 BufferCollectionToken 的可能性。 另一种方法是将令牌传递给 BindSharedCollection(),该方法也会在将令牌交换为 BufferCollection 通道时验证令牌,然后便可使用 BufferCollection Sync()。
在 Sync() 之后,可以安全地将 token_request 的客户端发送给另一个参与者,因为知道当另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括:等待每个 token.Duplicate() 单独完成(在每个 token.Duplicate() 之后单独调用 token.Sync()),或在通过 BindSharedCollection() 提交令牌后对 BufferCollection 调用 Sync()。
另一种缓解方法是避免对令牌调用 Sync(),而是在原始令牌无效时,稍后处理 BufferCollection.Sync() 的潜在故障。从性能角度来看,此选项可能更可取,但需要客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将复制的令牌转换为 BufferCollection 并收到来自 BufferCollection.Sync() 的成功响应。
请尽可能改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,则调用方必须已经知道此令牌有效/曾经有效,否则 BufferCollectionToken.Sync() 可能会永远挂起。如果令牌尚未被确认为有效,请先参阅 ValidateBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
BufferCollectionTokenGroup
在 fuchsia.sysmem/collection.fidl 中定义
sysmem 实现保证与逻辑/概念模型一致,如下所示:
与往常一样,逻辑分配会考虑根和所有与根连接且不经过 AttachToken() 的节点,或者以 AttachToken() 令牌为根的子树和所有与该子树连接且不经过另一个 AttachToken() 的节点。这称为逻辑分配修剪子树,简称修剪子树。
在约束条件汇总期间,每个 BufferCollectionTokenGroup 都会从其子令牌中选择一个子令牌。其余子级似乎无法通过逻辑分配,而所选子级可能会成功。
如果整体逻辑分配经过修剪的子树中存在多个 BufferCollectionTokenGroup,则两个组之间的相对优先级等同于它们在树的 DFS 前序迭代中的顺序,其中父级的优先级高于子级,左侧子级的优先级高于右侧子级。
当选择某个群组的特定子群组时(无论是在约束条件汇总尝试期间临时选择,还是作为最终选择),未选择该群组的其他子群组可能会“隐藏”这些未选择的子群组下的其他群组。
在逻辑分配中,系统会先尝试进行汇总,方法是临时选择最高优先级组的子级 0,以及下一个最高优先级组(未被到目前为止的临时选择隐藏)的子级 0,以此类推。
如果该汇总尝试失败,系统将尝试使用所有相同组的序号为 0 的子级进行汇总,但优先级最低的非隐藏组除外,该组将临时选择其序号为 1 的子级(然后是子级 2,依此类推)。如果随着临时选择的更新,新的最低优先级群组被取消隐藏,则在更改前一个最低优先级群组中的临时选择之前,系统会按顺序考虑该新取消隐藏的最低优先级群组的所有子节点。从结果来看,这相当于以类似计数的方式系统地枚举所有可能的选择组合,其中优先级最低的群组更新最频繁,优先级最高的群组更新最不频繁。我们可以跳过因隐藏而冗余/等效的组合,而无需对结果进行任何更改,而不是实际尝试使用所有组合进行聚合。
尝试对枚举的非等效选择组合进行聚合会以这种方式继续,直到 (a) 所有聚合尝试都失败(在这种情况下,整体逻辑分配失败),或者 (b) 尝试的聚合成功(在这种情况下,尝试一次缓冲区分配 [如果需要])。如果基于首次成功聚合的缓冲区分配失败,则整体逻辑分配失败(不会重试 / 重新尝试缓冲区分配)。如果缓冲区分配成功(或不需要),则逻辑分配成功。
如果此优先级方案不适用于您的 sysmem 用法,请与 sysmem 人员联系,讨论是否可以添加一种方法来实现您的需求。
请避免为每个逻辑分配创建大量 BufferCollectionTokenGroup,尤其是在总体上有大量子级的情况下,以及在可以合理预期聚合通常会失败(使用序号为 0 的子级,可能还包括后续子级)的情况下。我们预计,通过在考虑的组子组合/选择数量超过特定(相当高,但不是很大)最大数量时直接使逻辑分配失败,可以缓解在过多组中评估过多子组合/选择可能带来的高时间复杂度。更高级(也更复杂)的缓解措施预计在实际中没有必要,也不值得增加复杂性。如果达到或预计会达到上限,请与 sysmem 团队联系,讨论可能的选项。
如果可行,最好在单个 BufferCollectionConstraints 中使用多个 ImageFormatConstraints(当参与者只需要表达使用多个 PixelFormat 的能力时,由 sysmem 选择在所有参与者支持的 PixelFormat 中使用哪个 PixelFormat)。
与 BufferCollectionToken 和 BufferCollection 类似,如果关闭 BufferCollectionTokenGroup 通道时未先发送 Close(),则会导致逻辑缓冲区集合失败(如果使用 SetDispensable() 或 AttachToken(),并且 BufferCollectionTokenGroup 是此类节点下不会将失败传播到其父级的子树的一部分,则会导致子树失败)。
AllChildrenPresent
AllChildrenPresent()
创建所有子级后,客户端必须调用 AllChildrenPresent(),以通知 sysmem 不会再创建子级,以便 sysmem 知道何时可以开始汇总限制。
如果要发送 Close(),应在 AllChildrenPresent() 之后发送,否则仍会触发组故障并将故障传播到组的父级。
请求
<EMPTY>
关闭
在 BufferCollectionToken 频道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地 Close() 令牌(然后立即或稍后关闭通道,以响应服务器关闭其端),从而避免导致逻辑缓冲区集合失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,如果 BufferCollection 发生意外故障,服务器会使整个逻辑缓冲区集合发生故障。部分原因是为了在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者希望完全关闭 BufferCollection 视图而不导致逻辑缓冲区集合失败,则可以在关闭 BufferCollection 通道的客户端之前发送 Close()。如果这是最后一个 BufferCollection 视图,则逻辑缓冲区集合仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前发生,则缓冲区集合不需要此节点的限制条件即可进行分配。如果在 SetConstraints() 之后,即使没有通道连接,约束条件也会保留并与任何后续逻辑分配一起汇总。
在 BufferCollectionTokenGroup 渠道上:
默认情况下,BufferCollectionTokenGroup 的意外故障会触发逻辑 BufferCollectionTokenGroup 的故障,并将故障传播到其父级。如需关闭 BufferCollectionTokenGroup 逻辑分组通道,而不导致逻辑分组失败或传播失败,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,则尽管有 Close(),逻辑缓冲区集合仍会失败(因为 sysmem 无法确定是否已创建所有相关子项,因此不确定是否会向 sysmem 提供所有相关限制条件)。如果 Close() 发生在 AllChildrenPresent() 之后,则子级及其所有限制条件将保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
CreateChild
创建子级 token。在将此令牌的客户端传递给 BindSharedCollection() 之前,必须在 CreateChild() 之后完成 Sync()。或者,客户端可以使用 CreateChildrenSync(),它基本上包含 Sync()。
token_request - 新令牌通道的服务器端。
rights_attenuation_mask - 如果为 ZX_RIGHT_SAME_RIGHTS,则创建的令牌允许持有者获得与父级令牌(组)相同的缓冲区权限。
请求
| 名称 | 类型 |
|---|---|
payload |
BufferCollectionTokenGroupCreateChildRequest
|
CreateChildrenSync
同步创建 1 个或多个子级 token。与 CreateChild() 不同,在将返回的令牌的客户端端点传递给 BindSharedCollection() 之前,不需要完成 Sync()。
rights_attentuation_mask 的大小决定了创建的子令牌的数量。
索引较低的子令牌比索引较高的子令牌具有更高的优先级(更早尝试)。
与所有子令牌一样,成功聚合将从所有已创建的子令牌中(在可能多次调用 CreateChild() 和 CreateChildrenSync() 时创建的所有子令牌中)恰好选择一个子令牌。
每个组允许的子级总数上限以及整个树(从根开始)中的节点总数上限均受限制,这些限制无法通过这些协议进行配置。
请求
| 名称 | 类型 |
|---|---|
rights_attenuation_masks |
vector<zx/Rights>:64
|
响应
| 名称 | 类型 |
|---|---|
tokens |
vector<client_end:BufferCollectionToken>:64
|
GetNodeRef
这会获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端不会获得发出此事件信号的权利,因为此句柄只能用作客户端从该节点获取此句柄的证明。
由于这是 get 而不是 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能在不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
IsAlternateFor
此方法会检查调用节点是否位于以公共父级 BufferCollectionTokenGroup 的不同子令牌为根的子树中(相对于传入的 node_ref)。
此调用用于协助准入控制去重和调试。
node_ref 必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时都调用 GetNodeRef()。
如果调用令牌可能根本不是有效令牌(因为令牌提供程序可能具有敌意/不受信任),请先调用 ValidateBufferCollectionToken(),而不是在 IsAlternateFor() 永远不响应时无限期地卡住(因为调用令牌不是真实令牌,即未真正与 sysmem 通信)。另一种方法是先使用此令牌调用 BindSharedCollection,这也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示在与调用节点相同的逻辑缓冲区集合中找不到 node_ref。在逻辑分配之前,且在同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 都会至少持续存在到逻辑分配(包括已执行 Close() 并关闭其通道的节点),并且要返回 ZX_ERR_NOT_FOUND,此节点的通道仍需在服务器端连接,如果整个逻辑分配失败,则不会出现这种情况。在逻辑分配之后或在不同的逻辑分配子树中,此错误还有其他潜在原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此节点的逻辑分配分开)可能会导致其子树删除这些节点,或者可能存在 BufferCollectionTokenGroup,并且可能会选择与 node_ref 所在子树不同的子树,从而导致删除 node_ref 节点。只有在以下情况下,sysmem 才会在节点没有对应通道后保留该节点:使用了 Close() 且节点的子树尚未失败。 导致此错误的另一个原因是,node_ref 是具有足够权限的 eventpair 句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是 eventpair 句柄,或者不具有实际 node_ref 上所需的权限。
此调用不会返回任何其他失败状态代码。不过,sysmem 可能会在未来添加其他代码,因此客户端应针对任何失败状态代码提供合理的默认处理。
如果成功,is_alternate 的含义如下:
- true - 调用节点和 node_ref 节点之间的第一个共同父节点是 BufferCollectionTokenGroup。这意味着, 调用节点和 node_ref 节点不会同时应用其 约束条件,而是 sysmem 会选择其中一个 约束条件,而不会同时选择这两个约束条件。这是因为在逻辑分配期间,系统只会选择 BufferCollectionTokenGroup 的一个子级,并且只有该子级的子树会参与约束条件聚合。
- false - 调用节点与 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同父节点是 BufferCollectionToken 或 BufferCollection(无论是否已 Close())。这意味着,如果所涉及的任何父级 BufferCollectionTokenGroup 都选择了这两个节点,则调用节点和 node_ref 节点可能会在逻辑分配的约束条件汇总期间应用其约束条件。在这种情况下,没有任何 BufferCollectionTokenGroup 会直接阻止两个节点同时被选中且其约束条件同时被汇总,但即使为 false,如果一个或两个节点具有直接或间接父级 BufferCollectionTokenGroup,且该父级 BufferCollectionTokenGroup 选择的子级子树不是包含调用节点或 node_ref 节点的子树,则一个或两个节点仍可能被排除在考虑范围之外。
请求
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
响应
| 名称 | 类型 |
|---|---|
payload |
Node_IsAlternateFor_Result
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可使用这些信息来帮助调试泄漏的内存和等待约束时挂起的问题。|name| 可以是任意字符串,但当前进程名称(请参阅 fsl::GetCurrentProcessName())是一个不错的默认值。|id| 可以是任意 ID,但当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())是一个不错的默认值。
在启用详细日志记录时(请参阅 SetVerboseLogging()),此名称还用于指明哪个客户端首先关闭其通道,从而导致子树失败(如果子树的目的已达到,这可能是正常的,但如果发生的时间早于预期,则从 sysmem 的角度来看,客户端通道专用名称有助于诊断故障首先来自何处)。
默认情况下(除非被此消息覆盖或使用 Allocator.SetDebugClientInfo()),节点会在创建子节点时从其父节点复制信息。虽然这比什么都不做要好,但每个参与者最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 来使信息与当前客户端直接相关。此外,如果怀疑某个节点包含从其父节点复制的信息,则可以使用 SetVerboseLogging() 来帮助消除歧义。
请求
| 名称 | 类型 |
|---|---|
name |
string:64
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制,Sysmem 会记录一条警告。客户端可以调用此方法来更改日志的输出时间。如果多个客户端设置了截止期限,则无法指定哪个截止期限会生效。
请求
| 名称 | 类型 |
|---|---|
deadline |
zx/Time
|
SetName
为此缓冲区集合中的 VMO 设置名称。名称可能会被截断。该名称仅影响设置后分配的 VMO,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值较大的客户端将胜出。
请求
| 名称 | 类型 |
|---|---|
priority |
uint32
|
name |
string:64
|
SetVerboseLogging
详细日志记录包括通过每个客户端的 SetConstraints() 设置的限制条件、通过 SetDebugClientInfo() 设置的信息以及节点树的结构。
通常,当聚合失败时,sysmem 只会输出一行投诉,其中仅包含聚合失败的具体详细原因,而上下文信息极少。如果只做了一处小改动,并且系统在改动之前一直正常运行,那么这通常足以诊断问题,但对于让新的缓冲区集合首次正常运行,这通常没有特别大的帮助。尤其是在涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树时,详细日志记录可能有助于诊断树的外观以及逻辑分配失败的原因,或者树或子树比预期更早失败的原因。
从性能角度来看,如果仅在少量缓冲区集合上启用,则额外日志记录的意图是可以接受的。如果我们没有在跟踪 bug,就不应该发送此消息。
如果太多参与者让详细日志记录保持启用状态,我们最终可能需要通过其他设置允许系统级 sysmem 详细日志记录,以避免 sysmem 因这条消息而过多地向日志发送垃圾内容。
对于某些节点,这可能是 NOP,因为与节点关联的有意政策,如果我们不信任节点,无法让其开启详细日志记录。
请求
<EMPTY>
同步
确保服务器端已收到之前的消息,包括令牌、集合或群组上的 Duplicate() 消息。
对不是/曾不是有效 sysmem 令牌的令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永远挂起。请参阅 ValidateBufferCollectionToken(),了解如何以一次往返为代价来降低出现恶意/虚假 BufferCollectionToken 的可能性。 另一种方法是将令牌传递给 BindSharedCollection(),该方法也会在将令牌交换为 BufferCollection 通道时验证令牌,然后便可使用 BufferCollection Sync()。
在 Sync() 之后,可以安全地将 token_request 的客户端发送给另一个参与者,因为知道当另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括:等待每个 token.Duplicate() 单独完成(在每个 token.Duplicate() 之后单独调用 token.Sync()),或在通过 BindSharedCollection() 提交令牌后对 BufferCollection 调用 Sync()。
另一种缓解方法是避免对令牌调用 Sync(),而是在原始令牌无效时,稍后处理 BufferCollection.Sync() 的潜在故障。从性能角度来看,此选项可能更可取,但需要客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将复制的令牌转换为 BufferCollection 并收到来自 BufferCollection.Sync() 的成功响应。
请尽可能改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,则调用方必须已经知道此令牌有效/曾经有效,否则 BufferCollectionToken.Sync() 可能会永远挂起。如果令牌尚未被确认为有效,请先参阅 ValidateBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
节点
在 fuchsia.sysmem/collection.fidl 中定义
关闭
在 BufferCollectionToken 频道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地 Close() 令牌(然后立即或稍后关闭通道,以响应服务器关闭其端),从而避免导致逻辑缓冲区集合失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,如果 BufferCollection 发生意外故障,服务器会使整个逻辑缓冲区集合发生故障。部分原因是为了在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者希望完全关闭 BufferCollection 视图而不导致逻辑缓冲区集合失败,则可以在关闭 BufferCollection 通道的客户端之前发送 Close()。如果这是最后一个 BufferCollection 视图,则逻辑缓冲区集合仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前发生,则缓冲区集合不需要此节点的限制条件即可进行分配。如果在 SetConstraints() 之后,即使没有通道连接,约束条件也会保留并与任何后续逻辑分配一起汇总。
在 BufferCollectionTokenGroup 渠道上:
默认情况下,BufferCollectionTokenGroup 的意外故障会触发逻辑 BufferCollectionTokenGroup 的故障,并将故障传播到其父级。如需关闭 BufferCollectionTokenGroup 逻辑分组通道,而不导致逻辑分组失败或传播失败,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,则尽管有 Close(),逻辑缓冲区集合仍会失败(因为 sysmem 无法确定是否已创建所有相关子项,因此不确定是否会向 sysmem 提供所有相关限制条件)。如果 Close() 发生在 AllChildrenPresent() 之后,则子级及其所有限制条件将保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
GetNodeRef
这会获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端不会获得发出此事件信号的权利,因为此句柄只能用作客户端从该节点获取此句柄的证明。
由于这是 get 而不是 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能在不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
IsAlternateFor
此方法会检查调用节点是否位于以公共父级 BufferCollectionTokenGroup 的不同子令牌为根的子树中(相对于传入的 node_ref)。
此调用用于协助准入控制去重和调试。
node_ref 必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时都调用 GetNodeRef()。
如果调用令牌可能根本不是有效令牌(因为令牌提供程序可能具有敌意/不受信任),请先调用 ValidateBufferCollectionToken(),而不是在 IsAlternateFor() 永远不响应时无限期地卡住(因为调用令牌不是真实令牌,即未真正与 sysmem 通信)。另一种方法是先使用此令牌调用 BindSharedCollection,这也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示在与调用节点相同的逻辑缓冲区集合中找不到 node_ref。在逻辑分配之前,且在同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 都会至少持续存在到逻辑分配(包括已执行 Close() 并关闭其通道的节点),并且要返回 ZX_ERR_NOT_FOUND,此节点的通道仍需在服务器端连接,如果整个逻辑分配失败,则不会出现这种情况。在逻辑分配之后或在不同的逻辑分配子树中,此错误还有其他潜在原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此节点的逻辑分配分开)可能会导致其子树删除这些节点,或者可能存在 BufferCollectionTokenGroup,并且可能会选择与 node_ref 所在子树不同的子树,从而导致删除 node_ref 节点。只有在以下情况下,sysmem 才会在节点没有对应通道后保留该节点:使用了 Close() 且节点的子树尚未失败。 导致此错误的另一个原因是,node_ref 是具有足够权限的 eventpair 句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是 eventpair 句柄,或者不具有实际 node_ref 上所需的权限。
此调用不会返回任何其他失败状态代码。不过,sysmem 可能会在未来添加其他代码,因此客户端应针对任何失败状态代码提供合理的默认处理。
如果成功,is_alternate 的含义如下:
- true - 调用节点和 node_ref 节点之间的第一个共同父节点是 BufferCollectionTokenGroup。这意味着, 调用节点和 node_ref 节点不会同时应用其 约束条件,而是 sysmem 会选择其中一个 约束条件,而不会同时选择这两个约束条件。这是因为在逻辑分配期间,系统只会选择 BufferCollectionTokenGroup 的一个子级,并且只有该子级的子树会参与约束条件聚合。
- false - 调用节点与 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同父节点是 BufferCollectionToken 或 BufferCollection(无论是否已 Close())。这意味着,如果所涉及的任何父级 BufferCollectionTokenGroup 都选择了这两个节点,则调用节点和 node_ref 节点可能会在逻辑分配的约束条件汇总期间应用其约束条件。在这种情况下,没有任何 BufferCollectionTokenGroup 会直接阻止两个节点同时被选中且其约束条件同时被汇总,但即使为 false,如果一个或两个节点具有直接或间接父级 BufferCollectionTokenGroup,且该父级 BufferCollectionTokenGroup 选择的子级子树不是包含调用节点或 node_ref 节点的子树,则一个或两个节点仍可能被排除在考虑范围之外。
请求
| 名称 | 类型 |
|---|---|
node_ref |
handle<event>
|
响应
| 名称 | 类型 |
|---|---|
payload |
Node_IsAlternateFor_Result
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可使用这些信息来帮助调试泄漏的内存和等待约束时挂起的问题。|name| 可以是任意字符串,但当前进程名称(请参阅 fsl::GetCurrentProcessName())是一个不错的默认值。|id| 可以是任意 ID,但当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())是一个不错的默认值。
在启用详细日志记录时(请参阅 SetVerboseLogging()),此名称还用于指明哪个客户端首先关闭其通道,从而导致子树失败(如果子树的目的已达到,这可能是正常的,但如果发生的时间早于预期,则从 sysmem 的角度来看,客户端通道专用名称有助于诊断故障首先来自何处)。
默认情况下(除非被此消息覆盖或使用 Allocator.SetDebugClientInfo()),节点会在创建子节点时从其父节点复制信息。虽然这比什么都不做要好,但每个参与者最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 来使信息与当前客户端直接相关。此外,如果怀疑某个节点包含从其父节点复制的信息,则可以使用 SetVerboseLogging() 来帮助消除歧义。
请求
| 名称 | 类型 |
|---|---|
name |
string:64
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制,Sysmem 会记录一条警告。客户端可以调用此方法来更改日志的输出时间。如果多个客户端设置了截止期限,则无法指定哪个截止期限会生效。
请求
| 名称 | 类型 |
|---|---|
deadline |
zx/Time
|
SetName
为此缓冲区集合中的 VMO 设置名称。名称可能会被截断。该名称仅影响设置后分配的 VMO,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值较大的客户端将胜出。
请求
| 名称 | 类型 |
|---|---|
priority |
uint32
|
name |
string:64
|
SetVerboseLogging
详细日志记录包括通过每个客户端的 SetConstraints() 设置的限制条件、通过 SetDebugClientInfo() 设置的信息以及节点树的结构。
通常,当聚合失败时,sysmem 只会输出一行投诉,其中仅包含聚合失败的具体详细原因,而上下文信息极少。如果只做了一处小改动,并且系统在改动之前一直正常运行,那么这通常足以诊断问题,但对于让新的缓冲区集合首次正常运行,这通常没有特别大的帮助。尤其是在涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树时,详细日志记录可能有助于诊断树的外观以及逻辑分配失败的原因,或者树或子树比预期更早失败的原因。
从性能角度来看,如果仅在少量缓冲区集合上启用,则额外日志记录的意图是可以接受的。如果我们没有在跟踪 bug,就不应该发送此消息。
如果太多参与者让详细日志记录保持启用状态,我们最终可能需要通过其他设置允许系统级 sysmem 详细日志记录,以避免 sysmem 因这条消息而过多地向日志发送垃圾内容。
对于某些节点,这可能是 NOP,因为与节点关联的有意政策,如果我们不信任节点,无法让其开启详细日志记录。
请求
<EMPTY>
同步
确保服务器端已收到之前的消息,包括令牌、集合或群组上的 Duplicate() 消息。
对不是/曾不是有效 sysmem 令牌的令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永远挂起。请参阅 ValidateBufferCollectionToken(),了解如何以一次往返为代价来降低出现恶意/虚假 BufferCollectionToken 的可能性。 另一种方法是将令牌传递给 BindSharedCollection(),该方法也会在将令牌交换为 BufferCollection 通道时验证令牌,然后便可使用 BufferCollection Sync()。
在 Sync() 之后,可以安全地将 token_request 的客户端发送给另一个参与者,因为知道当另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括:等待每个 token.Duplicate() 单独完成(在每个 token.Duplicate() 之后单独调用 token.Sync()),或在通过 BindSharedCollection() 提交令牌后对 BufferCollection 调用 Sync()。
另一种缓解方法是避免对令牌调用 Sync(),而是在原始令牌无效时,稍后处理 BufferCollection.Sync() 的潜在故障。从性能角度来看,此选项可能更可取,但需要客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将复制的令牌转换为 BufferCollection 并收到来自 BufferCollection.Sync() 的成功响应。
请尽可能改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,则调用方必须已经知道此令牌有效/曾经有效,否则 BufferCollectionToken.Sync() 可能会永远挂起。如果令牌尚未被确认为有效,请先参阅 ValidateBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
SecureMem
在 fuchsia.sysmem/secure_mem.fidl 中定义
SecureMem
客户端为 sysmem。服务器是 securemem 驱动程序。
TEE - 可信执行环境。
REE - 富执行环境。
使 sysmem 能够调用 securemem 驱动程序,以获取通过 TEE(或通过 securemem 驱动程序)配置的任何安全堆,并设置通过 sysmem 配置的任何物理安全堆。
目前,动态分配的安全堆通过 sysmem 进行配置,因为它在启动期间很早就启动,并且可以成功预留连续的物理内存。目前,固定位置的安全堆通过 TEE 进行配置,因为管道从引导加载程序连接到 TEE。不过,此协议有意不关心哪些堆是动态分配的,哪些堆是固定位置的。
AddSecureHeapPhysicalRange
sysmem 向 securemem 驱动程序发出的此请求会传达要添加的物理范围,该物理范围适用于通过 sysmem 设置了物理范围的堆。
只有 sysmem 可以调用此方法,因为只有 sysmem 会通过 RegisterSecureMem() 获得提供此协议的 FIDL 通道的客户端。securemem 驱动程序是此协议的服务器端。
securemem 驱动程序必须先将所有涵盖的偏移量配置为受保护,然后才能成功响应此消息。
如果失败,securemem 驱动程序必须确保未创建受保护范围。
如果 dynamic_protection_ranges 为 false,Sysmem 最多只能调用此方法一次。
如果 dynamic_protection_ranges 为 true,则只要当前范围数量不超过 max_protected_range_count,sysmem 就可以多次调用此函数。
调用方不得尝试添加与现有范围匹配的范围。添加的范围可以相互重叠,只要没有两个范围完全匹配即可。
错误:
- ZX_ERR_BAD_STATE - 在 !dynamic_protection_ranges 时调用了多次。添加会导致堆总数超过 max_protected_range_count 的堆。
- ZX_ERR_INVALID_ARGS - 堆不符合预期,或范围不符合 protected_range_granularity。 * ZX_ERR_INTERNAL - 通用内部错误(例如,与不生成 zx_status_t 错误的 TEE 通信时)。
- 其他错误也可能发生,例如通信失败或 zx_status_t 失败的服务器传播。
请求
| 名称 | 类型 |
|---|---|
heap_range |
SecureHeapAndRange
|
响应
| 名称 | 类型 |
|---|---|
payload |
SecureMem_AddSecureHeapPhysicalRange_Result
|
DeleteSecureHeapPhysicalRange
此请求从 sysmem 发送到 securemem 驱动程序,用于传达要删除的物理范围,针对的是通过 sysmem 设置了物理范围的堆。
只有 sysmem 可以调用此方法,因为只有 sysmem 会通过 RegisterSecureMem() 获得提供此协议的 FIDL 通道的客户端。securemem 驱动程序是此协议的服务器端。
securemem 驱动程序必须先将所有涵盖的偏移量配置为不受保护,然后才能成功响应此消息。
如果失败,securemem 驱动程序必须确保受保护范围未被删除。
如果 dynamic_protection_ranges 为 false,Sysmem 不得调用此方法。
如果 dynamic_protection_ranges 为 true,则 sysmem 可以在调用时存在的各种范围内重复调用此方法。
如果被删除范围的任何部分未被其他受保护范围覆盖,则对整个范围的任何部分进行的任何正在进行的 DMA 都可能会中断 / 失败,这可能会对整个系统造成破坏(总线锁定或类似情况,具体取决于设备详细信息)。 因此,调用方必须确保没有正在进行的 DMA 访问要删除的范围的任何部分,除非调用方有其他有效范围覆盖要删除的范围的每个块。正在进行的与所删除范围之外的块之间的 DMA 绝不会受到删除操作的影响。
错误: * ZX_ERR_BAD_STATE - 在 !dynamic_protection_ranges 时调用。 * ZX_ERR_INVALID_ARGS - 意外堆或不符合 protected_range_granularity 的范围。
- ZX_ERR_INTERNAL - 通用内部错误(例如,在与不生成 zx_status_t 错误的 TEE 通信时)。
- ZX_ERR_NOT_FOUND - 找不到指定的范围。
- 其他错误也可能发生,例如通信失败或 zx_status_t 失败的服务器传播。
请求
| 名称 | 类型 |
|---|---|
heap_range |
SecureHeapAndRange
|
响应
| 名称 | 类型 |
|---|---|
payload |
SecureMem_DeleteSecureHeapPhysicalRange_Result
|
GetPhysicalSecureHeapProperties
此请求从 sysmem 发送到 securemem 驱动程序,用于获取受保护/安全堆的属性。
这仅处理具有单个连续物理区段的堆。
如果此请求需要一些物理空间来自动检测有多少个范围可供 REE 使用,则会指明堆的整个物理范围。在完成此请求之前,所有临时硬件保护范围都将被删除。
请求
| 名称 | 类型 |
|---|---|
entire_heap |
SecureHeapAndRange
|
响应
| 名称 | 类型 |
|---|---|
payload |
SecureMem_GetPhysicalSecureHeapProperties_Result
|
GetPhysicalSecureHeaps
获取通过 TEE 配置了物理范围的任何安全堆的物理地址和长度。
目前,这些将是固定的物理地址和长度,并通过 TEE 探测位置。
如果不需要任何特殊的堆特定 VMO 设置或拆解,则此方法优于 ['fuchsia.hardware.sysmem.Sysmem/RegisterHeap']。
在 securemem 驱动程序成功响应此请求之前,物理范围必须由 TEE 保护。
Sysmem 应仅调用此方法一次。返回零个堆不属于失败。
错误: * ZX_ERR_BAD_STATE - 调用了多次。 * ZX_ERR_INTERNAL - 通用内部错误(例如,与不生成 zx_status_t 错误的 TEE 通信时)。
- 允许其他错误;任何其他错误都应与 ZX_ERR_INTERNAL 相同。
请求
<EMPTY>
响应
| 名称 | 类型 |
|---|---|
payload |
SecureMem_GetPhysicalSecureHeaps_Result
|
ModifySecureHeapPhysicalRange
此请求从 sysmem 发送到 securemem 驱动程序,用于传达要修改的物理范围及其新的基址和长度,适用于通过 sysmem 设置物理范围的堆。
只有 sysmem 可以调用此方法,因为只有 sysmem 会通过 RegisterSecureMem() 获得提供此协议的 FIDL 通道的客户端。securemem 驱动程序是此协议的服务器端。
securemem 驱动程序必须先将范围配置为仅涵盖新偏移量,然后才能成功响应此消息。
如果失败,securemem 驱动程序必须确保范围未更改。
如果 dynamic_protection_ranges 为 false,Sysmem 不得调用此方法。如果 !is_mod_protected_range_available,Sysmem 不得调用此方法。
如果 dynamic_protection_ranges 为 true,则 sysmem 可以在调用时存在的各种范围内重复调用此方法。
只能修改范围的一端,不能同时修改两端。 如果范围正在缩短,并且未覆盖的块未被其他活跃范围覆盖,则对正在缩短的整个范围进行的任何正在进行的 DMA 都可能以破坏整个系统(总线锁定或类似情况)的方式失败,因此调用方必须确保没有 DMA 正在对正在缩短的范围的任何部分进行,除非通过修改此范围而未覆盖的块都被其他活跃范围覆盖,在这种情况下,不会对正在进行的 DMA 造成干扰。
如果范围被修改为长度小于或等于零,则该范围会被删除。
错误: * ZX_ERR_BAD_STATE - 在 !dynamic_protection_ranges 时调用。 * ZX_ERR_INVALID_ARGS - 意外堆,或 old_range 或 new_range 不符合 protected_range_granularity,或 old_range 和 new_range 在开头和结尾都不同(不允许)。
- ZX_ERR_INTERNAL - 通用内部错误(例如,在与不生成 zx_status_t 错误的 TEE 通信时)。
- ZX_ERR_NOT_FOUND - 找不到指定的范围。
- 其他错误也可能发生,例如通信失败或 zx_status_t 失败的服务器传播。
请求
| 名称 | 类型 |
|---|---|
range_modification |
SecureHeapAndRangeModification
|
响应
| 名称 | 类型 |
|---|---|
payload |
SecureMem_ModifySecureHeapPhysicalRange_Result
|
ZeroSubRange
将通过 AddSecureHeapPhysicalRange() 添加的现有物理范围的子范围归零。子范围必须完全由一个物理范围覆盖,并且不得与任何其他物理范围重叠。
is_covering_range_explicit - 如果为 true,则覆盖范围必须是通过 AddSecureHeapPhysicalRange() 明确创建的范围之一,可能自此之后进行了修改。如果为 false,则覆盖范围不得是通过 AddSecureHeapPhysicalRange() 显式创建的范围之一,但覆盖范围必须作为不是通过 AddSecureHeapPhysicalRange() 创建的覆盖范围存在。覆盖范围通常是由 TEE 配置的堆的整个物理范围(或覆盖范围更广的范围),其配置通过 GetPhysicalSecureHeaps() 传达给 sysmem。
此请求不会中断正在进行的 DMA。
请求
| 名称 | 类型 |
|---|---|
is_covering_range_explicit |
bool
|
heap_range |
SecureHeapAndRange
|
响应
| 名称 | 类型 |
|---|---|
payload |
SecureMem_ZeroSubRange_Result
|
STRUCTS
BufferCollectionConstraints
在 fuchsia.sysmem/constraints.fidl 中定义
对 BufferCollection 参数的限制。这些限制条件可以针对每个参与者进行指定。sysmem 服务会汇总来自多个参与者的限制条件。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
usage |
BufferUsage
|
当存在多个兼容选项时,该用法仅作为提示,帮助 sysmem 选择更优的 PixelFormat 或类似格式。 汇总 BufferCollectionConstraints 时,这些值会进行按位或运算。 必须至少指定一个使用位,除非整个 BufferCollectionConstraints 由于 !has_constraints 而在逻辑上为 null。 |
无默认应用 |
min_buffer_count_for_camping |
uint32
|
每个参与者可同时持有并独占使用非瞬时时间段(驻留)的缓冲区数量。 例如,视频解码器会指定(至少)参考帧数上限 + 当前正在解码到的 1 帧。 参与者不得占用超过此处指定的缓冲区数量(除非时间非常短暂),否则处理可能会卡住。 汇总 BufferCollectionConstraints 时,这些值会相加。 在测试场景中,如果长时间占用超过此数量的缓冲区,则可能会(理想情况下会)被标记为失败。在测试场景中,参与者同时获得的缓冲区数量不得超过此数量。 |
无默认应用 |
min_buffer_count_for_dedicated_slack |
uint32
|
每个参与者因松弛原因所需的缓冲区数量下限,以便更好地重叠处理 / 提高性能。 汇总 BufferCollectionConstraints 时,这些值会相加。 参与者通常应在此处指定 0 或 1。如果 min_buffer_count_for_camping 已足以让参与者在稍微落后时保持 100% 的忙碌状态,则通常指定 0 即可;如果比 min-camping 原因严格需要的缓冲区多 1 个缓冲区,则可以提供足够的余量来保持 100% 的忙碌状态(在稍微落后时,与没有额外缓冲区时的较低百分比相比),则指定 1 即可。 在测试场景中,此字段可能会被强制设为 0,并且所有参与者都应继续工作,而不会卡住。如果出于向前推进的原因需要缓冲区,则应在 min_buffer_count_for_camping 中考虑该缓冲区。 |
无默认应用 |
min_buffer_count_for_shared_slack |
uint32
|
与 min_buffer_count_for_dedicated_slack 类似,不同之处在于,在汇总这些值时,采用最大值(而不是相加)。此处的值不会与任何参与者的 min_buffer_count_for_dedicated_slack 共享。 如果参与者希望确保整体上有一些空闲时间,但不需要专门留出这些空闲时间,则可以在此处指定 > 0。 选择使用 min_buffer_count_for_dedicated_slack 还是 min_buffer_count_for_shared_slack(或两者都使用)通常取决于额外空闲空间对性能的提升程度。 在测试场景中,此字段可能会被强制设为 0,并且所有参与者都应继续工作,而不会卡住。如果出于向前推进的原因需要缓冲区,则应在 min_buffer_count_for_camping 中考虑该缓冲区。 |
无默认应用 |
min_buffer_count |
uint32
|
不幸的是,特别挑剔的参与者可能需要严格限制 buffer_count 的范围,甚至需要指定 buffer_count。此字段应保持为 0,除非参与者确实必须设置此字段来限制整体 BufferCollectionInfo_2.buffer_count。任何此类参与者仍应填写上述 min_buffer_count_for_* 字段。 |
无默认应用 |
max_buffer_count |
uint32
|
0 会被视为 0xFFFFFFFF。 |
无默认应用 |
has_buffer_memory_constraints |
bool
|
BufferCollectionSettings.buffer_settings 的限制条件。 如果参与者打算指定 image_format_constraints_count > 1,通常会通过 image_format_constraints 隐式指定最小缓冲区空间,并且可能仅通过 buffer_memory_constraints 指定最大缓冲区空间。 |
无默认应用 |
buffer_memory_constraints |
BufferMemoryConstraints
|
无默认应用 | |
image_format_constraints_count |
uint32
|
对存储在 BufferCollection 缓冲区中的图片的图片格式参数的可选限制。这包括像素格式和图片布局。这些限制条件是按像素格式设置的,因此可以设置多个。列表中的条目必须具有唯一的 pixel_formats。 汇总时,系统只会保留所有参与者指定的具有非零 image_format_constraints_count(且非 Null)BufferCollectionConstraints 的像素格式。 |
无默认应用 |
image_format_constraints |
array<ImageFormatConstraints, 32>
|
无默认应用 |
BufferCollectionInfo 资源
在 fuchsia.sysmem/collections_deprecated.fidl 中定义
已弃用。使用 ['fuchsia.sysmem2.BufferCollectionInfo']。
此类型已针对新代码弃用,但仍由一些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
buffer_count |
uint32
|
集合中的缓冲区数量。 |
无默认应用 |
format |
BufferFormat
|
描述缓冲区内容的表示方式。 集合中的所有缓冲区都具有相同的格式。 |
无默认应用 |
vmos |
array<handle<vmo>?, 64>
|
集合中每个缓冲区的 VMO 句柄。 仅当缓冲区由 VMO 支持时,VMO 才会存在。 如果存在,则 |
无默认应用 |
vmo_size |
uint64
|
每个提供的 VMO 的大小。 仅当缓冲区由 VMO 支持时,此属性才会存在。 |
0 |
BufferCollectionInfo_2 资源
在 fuchsia.sysmem/constraints.fidl 中定义
关于缓冲区集合及其缓冲区的信息。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
buffer_count |
uint32
|
缓冲区总数。 |
无默认应用 |
settings |
SingleBufferSettings
|
这些设置适用于初始缓冲区分配中的所有缓冲区。 |
无默认应用 |
buffers |
array<VmoBuffer, 64>
|
集合中每个缓冲区的 VMO 句柄(和 vmo_usable_start 偏移量)。 如果存在,则索引 所有缓冲区 VMO 句柄都具有相同的大小和访问权限。大小在 settings.buffer_settings.size_bytes 中。 VMO 访问权限取决于客户端在分配缓冲区集合时指定的用途。例如,表示只读用法的客户端将收到没有写入权限的 VMO。此外,还可以通过 BufferCollectionToken.Duplicate() 调用的参数来削弱权限。 |
无默认应用 |
BufferFormat
在 fuchsia.sysmem/formats_deprecated.fidl 中定义
描述缓冲区内容的表示方式。 每种类型的缓冲区都由其自己的表进行描述。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
tag |
uint32
|
由于此结构体过去是单成员联合体,因此我们保留了标记,以避免任何传输格式更改。该标记必须设置为 |
0 |
image |
ImageFormat
|
无默认应用 |
BufferMemoryConstraints
在 fuchsia.sysmem/constraints.fidl 中定义
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
min_size_bytes |
uint32
|
0 | |
max_size_bytes |
uint32
|
0 会被视为 0xFFFFFFFF。 |
4294967295 |
physically_contiguous_required |
bool
|
false | |
secure_required |
bool
|
如果为 true,则至少有一个参与者需要安全内存。 汇总 BufferCollectionConstraints 时,这些值会进行布尔值 OR 运算。 |
false |
ram_domain_supported |
bool
|
默认情况下,参与者必须确保 CPU 可以在不执行缓存操作的情况下对缓冲区执行数据读写操作。如果它们支持使用 RAM 网域,则数据必须在 RAM 中可用(具有 CPU 缓存状态,以便 RAM 数据不会因脏 CPU 缓存行将不正确的数据写入 RAM 而损坏),并且使用 CPU 读取的消费者必须在读取之前使 CPU 缓存失效(生产者不保证零过时“干净”缓存行) |
false |
cpu_domain_supported |
bool
|
true | |
inaccessible_domain_supported |
bool
|
false | |
heap_permitted_count |
uint32
|
可选的堆限制。不关心在哪个堆上分配内存的参与者应将此字段留空。 |
无默认应用 |
heap_permitted |
array<HeapType, 32>
|
无默认应用 |
BufferMemorySettings
在 fuchsia.sysmem/constraints.fidl 中定义
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
size_bytes |
uint32
|
无默认应用 | |
is_physically_contiguous |
bool
|
无默认应用 | |
is_secure |
bool
|
无默认应用 | |
coherency_domain |
CoherencyDomain
|
无默认应用 | |
heap |
HeapType
|
从中分配缓冲区的特定堆。 请参阅此文件中上文的堆标识符值。 |
无默认应用 |
BufferUsage
在 fuchsia.sysmem/usages.fidl 中定义
描述客户端将如何访问缓冲区的内容。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
none |
uint32
|
无默认应用 | |
cpu |
uint32
|
无默认应用 | |
vulkan |
uint32
|
无默认应用 | |
display |
uint32
|
无默认应用 | |
video |
uint32
|
无默认应用 |
ColorSpace
在 fuchsia.sysmem/image_formats.fidl 中定义
描述图片中的像素应如何呈现。 简单色彩空间只需要一个类型。 参数化色彩空间可能需要其他属性。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
type |
ColorSpaceType
|
无默认应用 |
FormatModifier
在 fuchsia.sysmem/format_modifier.fidl 中定义
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
value |
uint64
|
高 8 位是 FormatModifierVendor 枚举中分配的供应商代码。低 56 位由供应商定义。 出于兼容性原因,此字段和该字段中的值采用这种定义方式。 |
无默认应用 |
ImageFormat
在 fuchsia.sysmem/image_formats_deprecated.fidl 中定义
描述图片的表示方式。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
width |
uint32
|
行宽度(以像素为单位)。 |
无默认应用 |
height |
uint32
|
行数。 |
无默认应用 |
layers |
uint32
|
多层图片中的层数。 如果未指定,则默认为 1。 |
1 |
pixel_format |
PixelFormat
|
像素格式。 已弃用:23 已添加:7
|
无默认应用 |
color_space |
ColorSpace
|
色彩空间。 已弃用:23 已添加:7
|
无默认应用 |
planes |
array<ImagePlane, 4>
|
已弃用:23 已添加:7
|
无默认应用 |
ImageFormatConstraints
在 fuchsia.sysmem/constraints.fidl 中定义
描述缓冲区中图片数据布局的限制。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
pixel_format |
PixelFormat
|
以下限制条件适用的 PixelFormat。参与者可能支持多个 PixelFormat,在这种情况下,该参与者可以使用 ImageFormatConstraints 列表,其中每个 PixelFormat 对应一个条目。ImageFormatConstraints 的其他字段因 PixelFormat 而异的情况并不少见,例如,线性格式支持的最大尺寸小于平铺格式。 |
无默认应用 |
color_spaces_count |
uint32
|
留空会导致错误。冗余条目属于错误。任意排序不是错误。 |
无默认应用 |
color_space |
array<ColorSpace, 32>
|
无默认应用 | |
min_coded_width |
uint32
|
允许的最小宽度(以像素为单位)。 例如,视频解码器参与者可以将此字段设置为数据流可能指定的最小 coded_width。相反,required_min_coded_width 将设置为数据流指定的当前 coded_width。min_coded_width 通过取最大值进行汇总,而 required_min_coded_width 通过取最小值进行汇总。 另请参阅 required_min_coded_width。 |
无默认应用 |
max_coded_width |
uint32
|
最大宽度(以像素为单位)。例如,Scenic 可能会将此字段(直接或通过子参与者)设置为可合成的最大宽度。0 会被视为 0xFFFFFFFF。 |
无默认应用 |
min_coded_height |
uint32
|
最小高度(以像素为单位)。例如,视频解码器参与者可以将此字段设置为数据流指定的 coded_height。 |
无默认应用 |
max_coded_height |
uint32
|
最大高度(以像素为单位)。例如,Scenic 可能会将此字段(直接或通过子参与者)设置为可合成的最大高度。 0 会被视为 0xFFFFFFFF。 |
无默认应用 |
min_bytes_per_row |
uint32
|
必须大于等于平面 0 的 min_coded_width 所隐含的值。 |
无默认应用 |
max_bytes_per_row |
uint32
|
必须大于等于平面 0 的 max_coded_width 所暗示的值。 0 会被视为 0xFFFFFFFF。 |
无默认应用 |
max_coded_width_times_coded_height |
uint32
|
图片面积上限(以像素为单位)通过 BufferSettings.size_bytes 间接限制,也可以通过此字段直接强制执行。0 会被视为 0xFFFFFFFF。 |
4294967295 |
layers |
uint32
|
多层图片中的层数。 0 会被视为 1。 |
1 |
coded_width_divisor |
uint32
|
coded_width % width_divisor 必须为 0。 0 会被视为 1。 |
1 |
coded_height_divisor |
uint32
|
coded_height % height_divisor 必须为 0。 0 会被视为 1。 |
1 |
bytes_per_row_divisor |
uint32
|
bytes_per_row % bytes_per_row_divisor 必须为 0。 0 会被视为 1。 |
1 |
start_offset_divisor |
uint32
|
vmo_usable_start % start_offset_divisor 必须为 0。 0 会被视为 1。 |
1 |
display_width_divisor |
uint32
|
display_width % display_width_divisor 必须为 0。 0 会被视为 1。 |
1 |
display_height_divisor |
uint32
|
display_height % display_height_divisor 必须为 0。 0 会被视为 1。 |
1 |
required_min_coded_width |
uint32
|
required_ dimension bounds。 与开头没有“required_”的对应字段相比,这些字段(设置为非零值时)表示一项要求,即生成的汇总 non-required_ 字段指定的空间完全包含每个参与者的 required_ 字段表示的空间。 例如,如果消费者愿意接受任何内容,那么生产者视频解码器会非常乐意,并且视频解码器并不想限制可能在数据流中看到且消费者可能接受的潜在尺寸空间,但视频解码器需要确保生成的尺寸范围至少包含从数据流中解码的当前尺寸。 同样,如果发起方考虑了特定的动态维度场景,可能希望预先要求参与方同意至少处理发起方在该场景中预期的维度范围(否则,尽早失败,而不是稍后失败,可能会尝试使用较小的 required_ 空间再次尝试)。 与使用者相比,生产者或发起者设置这些字段的情况要常见得多。 虽然 non-required_ 字段通过取交集进行汇总,但 required_ 字段通过取并集进行汇总。 如果设置了 required_max_coded_width 和 required_max_coded_height,则分配的缓冲区将足够大,可以容纳 required_max_coded_width * required_max_coded_height 的图片。 TODO(dustingreen): Make it easier to allocate buffers of minimal size that can (optionally) also handle 90 degree rotated version of the max dimensions / alternate required bounds for another main aspect ratio. 0 会被视为 0xFFFFFFFF。 |
无默认应用 |
required_max_coded_width |
uint32
|
无默认应用 | |
required_min_coded_height |
uint32
|
0 会被视为 0xFFFFFFFF。 |
无默认应用 |
required_max_coded_height |
uint32
|
无默认应用 | |
required_min_bytes_per_row |
uint32
|
0 会被视为 0xFFFFFFFF。 |
无默认应用 |
required_max_bytes_per_row |
uint32
|
无默认应用 |
ImageFormat_2
在 fuchsia.sysmem/constraints.fidl 中定义
描述图片的表示方式。
此类型已弃用,不适用于新代码,但仍由一些相机代码和 StreamProcessor 使用(目前)。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
pixel_format |
PixelFormat
|
像素格式。 |
无默认应用 |
coded_width |
uint32
|
缓冲区中存在的行宽度(以像素为单位)。必须大于等于 display_width。 可以小于 stride_bytes 隐含的宽度。 |
无默认应用 |
coded_height |
uint32
|
行数。必须大于等于 display_height。 |
无默认应用 |
bytes_per_row |
uint32
|
平面 0 的跨距(以字节为单位)。平面 0 之外的平面(如果有,具体取决于 pixel_format)与平面 0 的步幅具有已知的固定关系。对于 Intel 平铺纹理,步幅适用于纹理的线性化版本。 |
无默认应用 |
display_width |
uint32
|
要显示的行宽度(以像素为单位)。此值可以小于或等于 coded_width。所有裁剪都发生在图片的右侧(而非左侧)。 |
无默认应用 |
display_height |
uint32
|
要显示的行数。此值可以 <= coded_height,且在底部(而非顶部)进行任何剪裁。 |
无默认应用 |
layers |
uint32
|
多层映像中的层数。 |
1 |
color_space |
ColorSpace
|
色彩空间。 |
无默认应用 |
has_pixel_aspect_ratio |
bool
|
pixel_aspect_ratio_width : pixel_aspect_ratio_height 是亮度(又称 Y)样本的像素宽高比(又称样本宽高比,即 SAR)。pixel_aspect_ratio 为 1:1 表示方形像素。pixel_aspect_ratio 为 2:1 表示显示的像素宽度是高度的两倍。编解码器实现应通过约分(将两个值都除以最大公约数)来确保这两个值互质(如有必要)。 如果 has_pixel_aspect_ratio == false,则 pixel_aspect_ratio 未知。 在某些情况下,默认值 1:1 可能合适,但与往常一样,消费者可以通过 OOB 方式确定实际的 pixel_aspect_ratio。 |
false |
pixel_aspect_ratio_width |
uint32
|
1 | |
pixel_aspect_ratio_height |
uint32
|
1 |
ImagePlane
在 fuchsia.sysmem/image_formats_deprecated.fidl 中定义
此类型已被弃用,没有直接替代项(有意为之),因为 fuchsia.images2 不需要单独描述每个平面。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
byte_offset |
uint32
|
平面起始位置相对于图片起始位置的字节偏移量。 |
无默认应用 |
bytes_per_row |
uint32
|
每行的步幅(以字节为单位)。 仅对线性缓冲区格式有意义。 |
无默认应用 |
ImageSpec
在 fuchsia.sysmem/image_formats_deprecated.fidl 中定义
描述分配所需形式的映像的限制条件。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
min_width |
uint32
|
最小宽度(以像素为单位)。 |
无默认应用 |
min_height |
uint32
|
最小高度(以像素为单位)。 |
无默认应用 |
layers |
uint32
|
多层图片中的层数。 如果未指定,则默认为 1。 |
1 |
pixel_format |
PixelFormat
|
像素格式。 |
无默认应用 |
color_space |
ColorSpace
|
色彩空间。 |
无默认应用 |
Node_IsAlternateFor_Response
在 fuchsia.sysmem/collection.fidl 中定义
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
is_alternate |
bool
|
无默认应用 |
PixelFormat
在 fuchsia.sysmem/image_formats.fidl 中定义
描述图片中的像素是如何表示的。 简单格式只需要类型。 参数化像素格式可能需要其他属性。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
type |
PixelFormatType
|
无默认应用 | |
has_format_modifier |
bool
|
此 bool 实际上使 format_modifier 成为可选,以满足“ForDeprecatedCBindings”和“FIDL Simple C Bindings”。 |
无默认应用 |
format_modifier |
FormatModifier
|
无默认应用 |
SecureMem_AddSecureHeapPhysicalRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SecureMem_DeleteSecureHeapPhysicalRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SecureMem_GetPhysicalSecureHeapProperties_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
properties |
SecureHeapProperties
|
无默认应用 |
SecureMem_GetPhysicalSecureHeaps_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
heaps |
SecureHeapsAndRanges
|
无默认应用 |
SecureMem_ModifySecureHeapPhysicalRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SecureMem_ZeroSubRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SingleBufferInfo 资源
在 fuchsia.sysmem/constraints.fidl 中定义
目前没有此类型的替代方案,但如果您的用例需要在单个集合中进行增量缓冲区分配,请与我们联系。
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
settings |
SingleBufferSettings
|
无默认应用 | |
buffer |
VmoBuffer
|
无默认应用 |
SingleBufferSettings
在 fuchsia.sysmem/constraints.fidl 中定义
在初始缓冲区分配后,可以关闭旧缓冲区并分配新缓冲区。分配新缓冲区时,其设置可能与集合中的其余缓冲区不同,并且单个缓冲区的设置通过 OnSingleBufferAllocated() 使用以下结构体传递:
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
buffer_settings |
BufferMemorySettings
|
无默认应用 | |
has_image_format_constraints |
bool
|
如果缓冲区包含的数据不是未压缩的图片数据,则不会设置此字段。可以为包含未压缩图片数据的缓冲区设置此字段。 至少在目前,更改 PixelFormat 需要重新分配缓冲区。 |
无默认应用 |
image_format_constraints |
ImageFormatConstraints
|
无默认应用 |
VmoBuffer 资源
在 fuchsia.sysmem/constraints.fidl 中定义
| 字段 | 类型 | 说明 | 默认 |
|---|---|---|---|
vmo |
handle<vmo>?
|
多个 CodecBuffer(仅限具有相同 buffer_lifetime_ordinal 的 CodecBuffer)可以使用同一个 VMO,但每个 VMO 句柄必须是单独的句柄。 如果这是 BufferCollectionInfo_2 中位于 BufferCollectionInfo_2.buffer_count 处或超出 BufferCollectionInfo_2.buffer_count 的 VmoBuffer,则 vmo 字段可以为 0。 |
无默认应用 |
vmo_usable_start |
uint64
|
第一个可用字节的 VMO 中的偏移量。必须小于 VMO 的大小(以字节为单位),并在 VMO 结束前为 BufferMemorySettings.size_bytes 留出足够的空间。 |
无默认应用 |
枚举
CoherencyDomain strict
类型:uint32
在 fuchsia.sysmem/constraints.fidl 中定义
“无法访问”仅适用于无法通过 CPU 访问缓冲区的情况。即使 secure_required 缓冲区只能在 CPU 以安全模式(或类似模式)运行时由 CPU 访问,该缓冲区仍可以具有 CoherencyDomain Cpu 或 Ram。相反,CPU 无法访问的设备本地内存属于 CoherencyDomain Inaccessible,即使可以使设备(物理或虚拟)将数据从 Inaccessible 缓冲区复制到 CPU 可见的缓冲区也是如此。
| 名称 | 值 | 说明 |
|---|---|---|
CPU |
0 |
|
RAM |
1 |
|
INACCESSIBLE |
2 |
ColorSpaceType strict
类型:uint32
在 fuchsia.sysmem/image_formats.fidl 中定义
此列表针对色彩空间标准的每个变体都有一个单独的条目。
因此,如果我们添加对 709 的 RGB 变体的支持,则会为此变体向此列表添加一个单独的条目。2020 或 2100 的 RGB 变体也是如此。2020 的 YcCbcCrc 变体也是如此。2100 的 ICtCp 变体也是如此。
给定的 ColorSpaceType 可能允许与 PixelFormatType 结合使用,后者提供的每个样本的位数与 ColorSpaceType 的官方规范兼容。并非所有符合规范的组合都一定受支持。 如需了解最佳支持程度,请参阅 ImageFormatIsSupportedColorSpaceForPixelFormat(),但该函数返回“true”并不保证任何给定的参与者组合都支持所需的 ColorSpaceType 和 PixelFormatType 组合。
sysmem 服务有助于找到相互支持的组合并分配适当的缓冲区。
ColorSpaceType 的规范不会隐式扩展为支持非标准每样本位数(R、G、B 或 Y 样本)。例如,对于 2020 和 2100,sysmem 不支持每个 Y 样本 8 位,因为 2020 或 2100 的规范中没有每个 Y 样本 8 位。如果 sysmem 参与者尝试通告对非标准 PixelFormat + ColorSpace 的支持,会导致 sysmem 拒绝该组合并无法分配(这是有意为之,目的是强烈不建议指定定义不充分的组合)。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 名称 | 值 | 说明 |
|---|---|---|
无效 |
0 |
不是有效的色彩空间类型。 |
SRGB |
1 |
sRGB |
REC601_NTSC |
2 |
601 NTSC(“525 行”)YCbCr 基色,窄 |
REC601_NTSC_FULL_RANGE |
3 |
601 NTSC(“525 行”)YCbCr 基色,宽 |
REC601_PAL |
4 |
601 PAL(“625 行”)YCbCr 基色,窄 |
REC601_PAL_FULL_RANGE |
5 |
601 PAL(“625 行”)YCbCr 基色,宽 |
REC709 |
6 |
709 YCbCr(非 RGB) |
REC2020 |
7 |
2020 YCbCr(非 RGB,非 YcCbcCrc) |
REC2100 |
8 |
2100 YCbCr(非 RGB,非 ICtCp) |
PASS_THROUGH |
9 |
像素格式不表示颜色,或者它位于应用特定的色彩空间中,无法通过此枚举中的其他条目进行描述。 |
DO_NOT_CARE |
4294967294 |
sysmem 客户端明确表示,sysmem 客户端不关心选择 / 使用哪个色彩空间。 新增:10
|
HeapType strict
类型:uint64
在 fuchsia.sysmem/constraints.fidl 中定义
已知堆类型。 设备特定类型应设置第 60 位。高位保留,不应设置。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 名称 | 值 | 说明 |
|---|---|---|
SYSTEM_RAM |
0 |
|
AMLOGIC_SECURE |
1152921504606912512 |
用于 Amlogic 受保护内存的堆。 |
AMLOGIC_SECURE_VDEC |
1152921504606912513 |
在解密和视频解码之间用于 amlogic 受保护内存的堆。 |
GOLDFISH_DEVICE_LOCAL |
1152921504606978048 |
Goldfish Vulkan 用于设备本地内存的堆。 |
GOLDFISH_HOST_VISIBLE |
1152921504606978049 |
Goldfish Vulkan 用于主机可见内存的堆。 |
FRAMEBUFFER |
1152921504607043585 |
用于显示帧缓冲区的堆。这由仅限于位于特定物理地址的单个帧缓冲区的显示驱动程序使用。 借助帧缓冲区堆,可以为帧缓冲区创建缓冲区集合,并在这些驱动程序中启用 sysmem 支持。 |
PixelFormatType strict
类型:uint32
在 fuchsia.sysmem/image_formats.fidl 中定义
格式名称中的声道顺序反映了声道的实际布局。
这些值中的每一个都对其中可包含的色彩空间有明确规定(与 Vulkan 相反)。
此值应与 fuchsia.sysmem2.PixelFormatType 保持同步。
此类型已针对新代码弃用,但仍由某些相机代码使用。
| 名称 | 值 | 说明 |
|---|---|---|
无效 |
0 |
|
R8G8B8A8 |
1 |
仅限 RGB,每个 R/G/B/A 样本 8 位 与 VK_FORMAT_R8G8B8A8_UNORM 兼容。 |
BGRA32 |
101 |
32bpp BGRA,1 个平面。仅限 RGB,每个 B/G/R/A 样本 8 位。 与 VK_FORMAT_B8G8R8A8_UNORM 兼容。 |
I420 |
102 |
仅限 YUV,每个 Y 样本 8 位 与 VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM 兼容。 |
M420 |
103 |
仅限 YUV,每个 Y 样本 8 位 与任何 Vulkan 格式都不兼容。 |
NV12 |
104 |
仅限 YUV,每个 Y 样本 8 位 与 VK_FORMAT_G8_B8R8_2PLANE_420_UNORM 兼容。 |
YUY2 |
105 |
仅限 YUV,每个 Y 样本 8 位 与 VK_FORMAT_G8B8G8R8_422_UNORM 兼容。 |
MJPEG |
106 |
|
YV12 |
107 |
仅限 YUV,每个 Y 样本 8 位
与 VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM 兼容。U 平面可能位于图片的 B 或 R 平面中(V 平面也是如此);可以通过查看 |
BGR24 |
108 |
24bpp BGR,1 个平面。仅限 RGB,每个 B/G/R 样本 8 位 与 VK_FORMAT_B8G8R8_UNORM 兼容。 |
RGB565 |
109 |
16bpp RGB,1 个平面。5 位 R、6 位 G、5 位 B 与 VK_FORMAT_R5G6B5_UNORM_PACK16 兼容。 |
RGB332 |
110 |
8bpp RGB,1 个平面。3 位 R、3 位 G、2 位 B 与任何 Vulkan 格式都不兼容。 |
RGB2220 |
111 |
8bpp RGB,1 个平面。2 位 R、2 位 G、2 位 B 与任何 Vulkan 格式都不兼容。 |
L8 |
112 |
8bpp,仅亮度(红色、绿色和蓝色具有相同的值)。 与 VK_FORMAT_R8_UNORM 兼容。 |
R8 |
113 |
8bpp,仅红色(绿色和蓝色应解释为 0)。 与 VK_FORMAT_R8_UNORM 兼容。 |
R8G8 |
114 |
16bpp RG,1 个平面。8 位 R,8 位 G。 与 VK_FORMAT_R8G8_UNORM 兼容。 |
A2R10G10B10 |
115 |
32bpp RGBA,1 个平面。2 位 A,10 位 R/G/B。 与 VK_FORMAT_A2R10G10B10_UNORM_PACK32 兼容。 |
A2B10G10R10 |
116 |
32bpp BGRA,1 个平面。2 位 A,10 位 R/G/B。 与 VK_FORMAT_A2B10G10R10_UNORM_PACK32 兼容。 |
DO_NOT_CARE |
4294967294 |
sysmem 客户端明确表示,sysmem 客户端不关心选择 / 使用哪种像素格式。设置此值时,sysmem 客户端不得设置 format_modifier_value。 新增:10
|
TABLES
BufferCollectionTokenGroupCreateChildRequest 资源
在 fuchsia.sysmem/collection.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
token_request |
server_end:BufferCollectionToken
|
必须设置。 |
2 |
rights_attenuation_mask |
uint32
|
如果未设置,则默认值为 ZX_RIGHT_SAME_RIGHTS。 |
SecureHeapAndRange
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
heap |
HeapType
|
|
2 |
range |
SecureHeapRange
|
SecureHeapAndRangeModification
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
heap |
HeapType
|
|
2 |
old_range |
SecureHeapRange
|
|
3 |
new_range |
SecureHeapRange
|
SecureHeapAndRanges
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
heap |
HeapType
|
这是指哪个安全/受保护的堆。 |
2 |
ranges |
vector<SecureHeapRange>:128
|
物理范围列表。此列表必须按 physical_address(较低的地址在前)进行排序,且不得有任何重叠范围。允许直接相邻(不重叠)的范围。 |
SecureHeapProperties
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
heap |
HeapType
|
为方便起见,此处重复了 HeapType。 |
2 |
dynamic_protection_ranges |
bool
|
如果为 true,则允许对同一堆多次调用 SetPhysicalSecureHeap()。如果为 false,则仅允许调用一次 SetPhyscialSecureHeap(),并且不允许调用 DeleteSecureHeapPhysicalRange() 或 ModifySecureHeapPhysicalRange()。即使此值为 false,如果受保护的范围在热重启期间不会被清理,SecureMem 服务器(驱动程序)仍负责在热重启之前取消保护。 |
3 |
protected_range_granularity |
uint32
|
保护范围的精细程度。如果开始时间的粒度与结束时间或长度的粒度不同,则此值为这些值中的最大粒度值。 此值必须是 2 的幂。客户端不得请求指定更小粒度的范围。 即使硬件可以实现更小的粒度,此值也必须至少为 zx_system_page_size()。 |
4 |
max_protected_range_count |
uint64
|
如果 SecureMem 服务器需要执行任何此类模拟,则 SecureMem 服务器不应计算 SecureMem 服务器在内部使用的预留范围,以便从范围集 A 转换到范围集 B。通常,SecureMem 服务器无需进行此类模拟。如果 SecureMem 服务器预留了任何范围,则 SecureMem 客户端无法使用这些预留范围。 如果范围数量仅受可用内存限制,则 SecureMem 服务器可以为此值报告 0xFFFFFFFFFFFFFFFF。该字段仍必须设置。与往常一样,SecureMem 服务器应确保 SetPhysicalSecureHeapRanges() 以原子方式成功或失败(在完成之前完全更新或回滚)。 |
5 |
is_mod_protected_range_available |
bool
|
当且仅当此值为 true 时,ModifySecureHeapPhysicalRange() 才会实现。当 is_mod_protected_range_available 为 false 时,禁止调用 ModifySecureHeapPhysicalRange()。请勿尝试通过调用 ModifySecureHeapPhysicalRange() 来检测其可用性,以查看其是否失败;它可能会导致 ZX_PANIC()。 |
SecureHeapRange
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
physical_address |
uint64
|
必须至少与 heap_range_granularity 对齐。 |
2 |
size_bytes |
uint64
|
必须至少与 heap_range_granularity 对齐。 |
SecureHeapsAndRanges
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 字段 | 类型 | 说明 |
|---|---|---|---|
1 |
heaps |
vector<SecureHeapAndRanges>:32
|
UNIONS
Node_IsAlternateFor_Result strict
在 fuchsia.sysmem/collection.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
Node_IsAlternateFor_Response
|
|
2 |
err |
zx/Status
|
SecureMem_AddSecureHeapPhysicalRange_Result strict
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
SecureMem_AddSecureHeapPhysicalRange_Response
|
|
2 |
err |
zx/Status
|
SecureMem_DeleteSecureHeapPhysicalRange_Result strict
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
SecureMem_DeleteSecureHeapPhysicalRange_Response
|
|
2 |
err |
zx/Status
|
SecureMem_GetPhysicalSecureHeapProperties_Result strict
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
SecureMem_GetPhysicalSecureHeapProperties_Response
|
|
2 |
err |
zx/Status
|
SecureMem_GetPhysicalSecureHeaps_Result strict
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
SecureMem_GetPhysicalSecureHeaps_Response
|
|
2 |
err |
zx/Status
|
SecureMem_ModifySecureHeapPhysicalRange_Result strict
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
SecureMem_ModifySecureHeapPhysicalRange_Response
|
|
2 |
err |
zx/Status
|
SecureMem_ZeroSubRange_Result strict
在 fuchsia.sysmem/secure_mem.fidl 中定义
| 序数 | 变体 | 类型 | 说明 |
|---|---|---|---|
1 |
response |
SecureMem_ZeroSubRange_Response
|
|
2 |
err |
zx/Status
|
常量
| 名称 | 值 | 类型 | 说明 |
|---|---|---|---|
| FORMAT_MODIFIER_ARM_AFBC_16X16 |
576460752303423489
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_ARM_AFBC_16X16_SPLIT_BLOCK_SPARSE_YUV |
576460752303423601
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_ARM_AFBC_16X16_SPLIT_BLOCK_SPARSE_YUV_TE |
576460752303427697
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_ARM_AFBC_16X16_SPLIT_BLOCK_SPARSE_YUV_TE_TILED_HEADER |
576460752303435889
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_AFBC_16X16_SPLIT_BLOCK_SPARSE_YUV_TILED_HEADER |
576460752303431793
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_AFBC_16X16_TE |
576460752303427585
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_ARM_AFBC_16X16_YUV_TILED_HEADER |
576460752303431697
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_AFBC_32X8 |
576460752303423490
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_AFBC_32X8_TE |
576460752303427586
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_BCH_BIT |
2048
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_LINEAR_TE |
576460752303427584
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_SPARSE_BIT |
64
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_SPLIT_BLOCK_BIT |
32
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_TE_BIT |
4096
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_TILED_HEADER_BIT |
8192
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_ARM_YUV_BIT |
16
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_GOOGLE_GOLDFISH_OPTIMAL |
648518346341351425
|
uint64 |
已弃用:23 已添加:7
|
| FORMAT_MODIFIER_INTEL_CCS_BIT |
16777216
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_INTEL_I915_X_TILED |
72057594037927937
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_INTEL_I915_YF_TILED |
72057594037927939
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_INTEL_I915_YF_TILED_CCS |
72057594054705155
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_INTEL_I915_Y_TILED |
72057594037927938
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_INTEL_I915_Y_TILED_CCS |
72057594054705154
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_INVALID |
FORMAT_MODIFIER_VALUE_RESERVED
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_LINEAR |
0
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_NONE |
0
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VALUE_RESERVED |
72057594037927935
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_AMD |
144115188075855872
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_ARM |
576460752303423488
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_BROADCOM |
504403158265495552
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_GOOGLE |
648518346341351424
|
uint64 |
此值的含义已被弃用。请改用 fuchsia.images2.FORMAT_MODIFIER_VENDOR_GOOGLE,其值不同。 已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_INTEL |
72057594037927936
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_NONE |
0
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_NVIDIA |
216172782113783808
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_QCOM |
360287970189639680
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_SAMSUNG |
288230376151711744
|
uint64 |
已弃用:23 新增:7
|
| FORMAT_MODIFIER_VENDOR_VIVANTE |
432345564227567616
|
uint64 |
已弃用:23 新增:7
|
| MAX_COUNT_BUFFER_COLLECTION_CONSTRAINTS_IMAGE_FORMAT_CONSTRAINTS |
32
|
uint32 |
|
| MAX_COUNT_BUFFER_COLLECTION_INFO_BUFFERS |
64
|
uint32 |
|
| MAX_COUNT_BUFFER_MEMORY_CONSTRAINTS_HEAP_PERMITTED |
32
|
uint32 |
|
| MAX_COUNT_CREATE_CHILDREN |
64
|
int32 |
在大多数典型场景中,实际上不建议创建这么多子级,但出于测试原因,以及为了以防万一在不寻常的场景中需要这样做,系统并未阻止这样做。为了缓解 sysmem 中可能出现的高时间复杂度,在聚合尝试中考虑的实际组子组合数量将限制为单独的最大值,该最大值无法通过这些协议进行设置。sysmem 令牌树中的节点总数上限受限于一个单独的上限,该上限无法通过这些协议进行设置。 已弃用:23 新增:9
|
| MAX_COUNT_DUPLICATES |
64
|
uint32 |
已弃用:23 新增:7
|
| MAX_COUNT_IMAGE_FORMAT_CONSTRAINTS_COLOR_SPACES |
32
|
uint32 |
|
| MAX_HEAPS_COUNT |
32
|
uint32 |
已弃用:23 新增:7
|
| MAX_RANGES_COUNT |
128
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_INDEX_BUFFER |
4194304
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_INDIRECT_BUFFER |
16777216
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_STORAGE_BUFFER |
2097152
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_STORAGE_TEXEL_BUFFER |
524288
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_TRANSFER_DST |
131072
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_TRANSFER_SRC |
65536
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_UNIFORM_BUFFER |
1048576
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER |
262144
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_BUFFER_USAGE_VERTEX_BUFFER |
8388608
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_COLOR_ATTACHMENT |
16
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_INPUT_ATTACHMENT |
128
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_SAMPLED |
4
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_STENCIL_ATTACHMENT |
32
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_STORAGE |
8
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_TRANSFER_DST |
2
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_TRANSFER_SRC |
1
|
uint32 |
已弃用:23 新增:7
|
| VULKAN_IMAGE_USAGE_TRANSIENT_ATTACHMENT |
64
|
uint32 |
已弃用:23 新增:7
|
| cpuUsageRead |
1
|
uint32 |
已弃用:23 新增:7
|
| cpuUsageReadOften |
2
|
uint32 |
已弃用:23 新增:7
|
| cpuUsageWrite |
4
|
uint32 |
已弃用:23 新增:7
|
| cpuUsageWriteOften |
8
|
uint32 |
已弃用:23 新增:7
|
| displayUsageCursor |
2
|
uint32 |
已弃用:23 新增:7
|
| displayUsageLayer |
1
|
uint32 |
已弃用:23 新增:7
|
| noneUsage |
1
|
uint32 |
已弃用:23 新增:7
|
| videoUsageCapture |
8
|
uint32 |
已弃用:23 新增:7
|
| videoUsageDecryptorOutput |
16
|
uint32 |
已弃用:23 新增:7
|
| videoUsageHwDecoder |
1
|
uint32 |
已弃用:23 新增:7
|
| videoUsageHwDecoderInternal |
32
|
uint32 |
已弃用:23 新增:7
|
| videoUsageHwEncoder |
2
|
uint32 |
已弃用:23 新增:7
|
| videoUsageHwProtected |
4
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageColorAttachment |
16
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageInputAttachment |
128
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageSampled |
4
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageStencilAttachment |
32
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageStorage |
8
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageTransferDst |
2
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageTransferSrc |
1
|
uint32 |
已弃用:23 新增:7
|
| vulkanUsageTransientAttachment |
64
|
uint32 |
已弃用:23 新增:7
|