SDK 运行时可见度设计方案

SDK 运行时中的广告 SDK 无法访问发布商的视图层次结构。实际上,运行时中的 SDK 有自己的视图。SDK 无法使用与它在 SDK 运行时外部使用的相同 View API 来确定是否要向用户展示广告,因为广告视图不会附加到应用窗口。这包括了多个 Android View API,例如 getLocationOnScreengetLocationInWindowgetVisibility,它们都不会返回预期值。

支持广告可见度衡量是 SDK 运行时的一项核心要求。此设计方案旨在实现对 Open Measurement 以及类似衡量服务的支持。本文讨论的解决方案可能也适用于 Attribution Reporting API

功能

此设计旨在协助广告 SDK 或衡量合作伙伴计算以下可见度数据(名称是临时的,可能会发生变化):

插图:SDK 运行时可见度组件如何实现互操作
SDK 运行时可见度概览。
  • viewport [Rect]:表示设备屏幕或应用窗口几何形状,具体取决于平台的功能。
  • uiContainerGeometry [Rect]:正在渲染的 SandboxedSdkView 的几何形状。
  • alpha [float]:正在渲染的 SandboxedSdkView 的不透明度。
  • onScreenGeometry [Rect]:不被父视图裁剪的 uiContainerGeometry 的子集,取决于所包含的 viewport
  • occludedGeometry [Rect]onScreenGeometry 中被应用层次结构内的任何视图遮挡的部分。每个遮挡部分包含一个 Rect,分别对应于与 SandboxedSdkView onScreenGeometry 相交的 0 个、1 个或多个应用视图

要求

  • uiContainerGeometryonScreenGeometryoccludedGeometry 的值以 viewport 坐标空间中的坐标表示。
  • 以最短延迟时间报告可见度更改。
  • 可见度在广告视图的整个生命周期内(从首次展示到最后一次展示)都是可衡量的。

设计方案

此方案的基础是使用客户端和提供方界面库进行界面呈现的方式。我们将扩展界面库,以允许 SDK 注册一个或多个界面会话的观察器。每当检测到对功能部分中的数据类型做出修改的相关事件时,观察器就会收到可见度信息。SDK 运行时中的衡量 SDK(OMIDMRAID 实现)可将此观察器附加到界面会话,以便直接将此信息发送给这些 SDK。衡量合作伙伴可将从界面库获取的信息与已有内容的数据相结合(例如,使用注入到广告素材中的衡量脚本时可用的数据),从而生成 JavaScript 可见度事件。

可见度控制流。
可见度控制流。

客户端库通过事件监听器(例如 ViewTreeObserver)监听广告界面中的更改。每当客户端库确定广告界面发生的更改可能会影响可见度衡量时,客户端库就会检查上次通知是在何时发送给观察器的。如果上次更新超出了允许的延迟时间(可由 SDK 配置,移动设备上的最短延迟时间上限为 200 毫秒),系统便会创建一个新的 AdContainerInfo 对象,并向观察器派发一条通知。与目前 Android 上由大多数 OMID 实现进行轮询的做法相比,这种基于事件的模型有助于改善系统运行状况。

API

以下内容将添加到 privacysandbox.ui.core 库:

  • SessionObserver:通常由衡量 SDK 实现,附加到 SDK 通过 privacysandbox.ui 返回的会话。此接口还允许衡量 SDK 选择使用特定类别的可见度信号。另一方面,此接口可让界面客户端库只收集观察器感兴趣的信号,这有助于改善系统的总体运行状况。
  • registerObserver():添加到 Session 类后,此方法允许任何有权访问会话的 SDK 注册观察器。如果在界面会话已打开的状态下注册观察器,系统会立即将缓存的 AdContainerInfo 发送给这些 SDK。如果在会话打开之前注册观察器,系统会在会话打开时将 AdContainerInfo 发送给这些 SDK。
  • AdContainerInfo:一个带有 getter 的类,可让观察器获取上述功能部分中所列数据类型的只读广告容器信息。来自这些 getter 的返回值将尽可能与对 View 及其子类调用现有 getter 后收到的 Parcelable 返回值对应。如果广告容器是使用 Jetpack Compose 创建的,这会公开容器的语义属性。此类可用于计算与可见度相关的 MRAID 和 OMID 事件。
  • SessionObserverotifyAdContainerChanged():用于在可见度发生变化时通知观察器。它会传递一个 AdContainerInfo 对象。每当检测到影响“功能”部分中所列数据类型的事件时,系统就会调用此方法。注意:除了对会话调用方法之外,系统也可能会调用此方法。例如,系统会调用 Session.notifyResized() 以请求 SDK 调整广告的大小,当这种情况发生时,系统也会调用 SessionObserver.notifyAdContainerChanged()
  • SessionObserverotifySessionClosed():通知观察器会话已关闭。

未来的增强功能

如果应用遭到破解,应用进程中运行的任何代码(包括 privacysandbox.ui.client 库中的代码)都可以被修改。因此,应用进程中运行的任何信号收集逻辑都很容易被应用代码篡改。这同样适用于在 Privacy Sandbox 可用之前部署并在应用进程中运行的 SDK 代码。所以,由界面库收集信号并不会使安全状况变差。

此外,SDK 运行时中的代码可以使用一个名为 setTrustedPresentationCallback 的平台 API,该 API 可以通过框架更好地保证广告界面呈现效果。setTrustedPresentationCallback 在 Surface 级运行,可通过指定最低呈现阈值(例如可见像素的百分比、屏幕停留时间或比例)来帮助对包含广告界面的 Surface 进行断言。您可以将这些数据与界面客户端库提供的可见度数据(如上文所述)进行对比检查。由于框架提供的数据更加可靠,因此,对于来自界面库的任何事件,如果其数据与框架提供的数据不一致,该事件就可能被舍弃。例如,如果调用了提供给 setTrustedPresentationCallback 的监听器,并且通知屏幕上将不显示任何广告界面像素,而客户端界面库在屏幕上显示了非零数量的像素,那么来自后者的数据就可能被舍弃。

开放性问题

  1. 您对哪些可见度信号感兴趣,但本说明文章中却未提及?
  2. 当前方案是:在界面有相关更改的前提下,可见度的更新频率不低于每 200 毫秒一次。您能接受这个频率吗?如果不能接受,您希望采用什么频率?
  3. 当界面库提供的数据与 setTrustedPresentationCallback 数据不匹配时,您是希望自行分析来自 setTrustedPresentationCallback 的信息,还是希望提供方界面库舍弃客户端界面库提供的数据?
  4. 您如何使用可见度信号?请通过回答这些问题来提交反馈意见,帮助我们了解您的用例。