SDK 运行时

提供反馈

Android 平台使用应用沙盒的概念来维持应用代码的稳健执行和安全边界,以及维持进程边界。在应用中包含第三方代码(通常采用 SDK 的形式,例如广告 SDK 或分析 SDK)是一种常见的做法。这种重用使得应用开发者能够专注于开发其应用特有的功能,同时利用主题专家的工作成果来扩展其应用的执行能力,使其超出应用本身可以轻松达到的程度。

和大多数操作系统一样,在 Android 中,SDK 在主应用的沙盒内执行,完全继承主应用的特权和权限,并且有权访问主应用的内存和存储空间。虽然这种架构能够使 SDK 和应用灵活集成,但也为在未披露的情况下收集和共享用户数据提供了可乘之机。此外,应用开发者可能并不完全了解第三方 SDK 的功能范围及其访问的数据,这使得考虑其应用的数据收集和共享实践变得非常困难。

在 Android 13 中,我们计划添加一项新的平台功能,让第三方 SDK 可以在专用运行时环境中运行,该功能称为 SDK 运行时。SDK 运行时可为用户数据收集和共享提供以下更强的安全保障和保证:

  • 经过修改的执行环境
  • 为 SDK 明确定义的权限和数据访问权

目标

该方案力求实现以下目标:

  • 通过进程隔离以及明确定义的 API 和数据访问权限控制,减少第三方 SDK 在未披露的情况下访问和共享用户的应用数据。如需详细了解进程隔离,请参阅本文档中的单独部分。
  • 通过限制 SDK 访问专属的永久标识符,减少第三方 SDK 在未披露的情况下跟踪用户的应用使用情况数据。
  • 通过减轻应用开发者和最终用户的负担,安全地加快向应用分发 SDK 更新的速度。如需详细了解我们提议的可信 SDK 分发模型,请参阅本文档中的另一部分。
  • 帮助应用开发者更好地考虑其应用的数据访问和共享实践。
  • 通过限制某些不安全的语言构造(例如反射和 JNI 代码),帮助 SDK 开发者防范其他 SDK 的篡改行为。
  • 通过完全控制用于显示媒体的远程视图,帮助广告 SDK 检测和防范无效流量和广告欺诈。
  • 尽可能减少对应用开发者和 SDK 开发者的不当影响。

SDK 在独立进程中执行

借助我们提议的 SDK 运行时,兼容的 SDK(在本文档中的其余部分称为“启用运行时 [RE] 的 SDK”)可在相应应用的单独进程中运行。平台可促进应用进程与其 SDK 运行时之间的双向通信。如需了解详情,请参阅本文档中的“通信”部分。非 RE SDK 将像现在一样保留在应用进程中。图 1 展示了这些变化:

之前:


之后:

图 1. 启用了运行时的 SDK 在添加到 SDK 运行时之前和之后的相对位置。“之前”示意图(第一个)显示,SDK 调用代码以及从该代码接收调用的 SDK 都位于应用进程中。“之后”示意图(第二个)显示,在应用的前台进程中,SDK 调用代码会与 SDK 接口进行通信。然后,这些接口会跨越进程边界进入 SDK 运行时进程,以调用 SDK 本身。

适用于 SDK 的全新可信分发模型

这种将 SDK 与应用进行分离的提议引发了另一个分离概念,就是将 SDK 分发和应用分发进行分离。我们的方案需要可信的分发和安装机制,以确保在应用的 SDK 运行时内安装正确的 SDK。这有助于防范用户和应用开发者加载无效的 SDK,同时让应用商店显著减轻应用开发者的 SDK 分发负担。

在将 SDK 上传到应用商店进行分发之前,不再需要将 SDK 静态关联到应用,也不再需要将其与应用打包在一起。现在,取而代之的是以下过程:

  1. SDK 开发者可以将其版本化 SDK 上传到应用商店(与应用本身分开)。
  2. 应用开发者可以按版本指定 SDK 依赖项,进行构建,然后上传不包含实际 SDK 依赖项的应用版本。
  3. 当用户下载此应用时,安装进程可以使用应用的指定 SDK 依赖项,这样一来便可以从应用商店下载它们。

借助这种新颖的分发机制,SDK 开发者可以对其 SDK 进行非破坏性更改(即不更改 API 或其语义),并分发到设备,而且无需应用开发者参与。您可以部署或回滚这些非破坏性 SDK 更改,而无需等待应用开发者使用新的 SDK 重新构建其应用,也无需等待最终用户更新其应用。破坏性更改仍需要由应用开发者进行更新,但 SDK 开发者能够以更加统一的方式更快地向更多人分发其最新的非破坏性更改和修复程序,理想情况下可以最大限度地减少版本支持需求。

图 2 展示了我们在 SDK 分发方面提议的更改:

之前:

“之前”示意图

之后:

“之后”示意图
图 2. 在引入 SDK 运行时之前和之后的 SDK 分发设计。SDK 开发者不再将其 SDK 直接发送到应用,而是使用 SDK 上传界面将其 SDK 发布到应用商店。然后,应用商店会处理分发操作,将应用以及所有 SDK 依赖项分发到最终用户的设备。

对 SDK 与应用的构建、运行和分发方式进行更改

这是初始方案,旨在实现灵活的 SDK 运行时和分发技术。下面各个部分针对以下广泛类别提议了一系列更改:

  • 访问权限:权限、内存、存储空间
  • 执行:语言、运行时更改、生命周期、媒体呈现
  • 通信:“从应用到 SDK”和“从 SDK 到 SDK”
  • 开发:如何在此模型中进行构建、调试和测试
  • 分发:如何跨 Android、应用和 SDK 的各个版本分发、更新、回滚

本文档还包含常见问题解答,以帮助解决常见问题。

这是初始设计方案。我们了解,对于生态系统的某些成员来说,这可能是一项非常有意义的改变。因此,我们正在积极征求您的反馈,您可以通过这个问题跟踪器将您的建议告诉我们。

访问权限

管理系统的隐私保护意味着管理不同方可以如何访问不同的资源。为了实现我们在隐私保护方面的价值主张,我们提议更新用于访问应用、SDK 和用户数据的模型,以遵循最小权限原则,进而防范在未披露的情况下访问潜在敏感数据。

SDK 权限

作为一个单独的进程,SDK 运行时将拥有自己的一组明确定义的权限,而不是继承用户授予应用的权限。根据对广告相关 SDK 所用权限进行的初步研究,我们提议 SDK 运行时内的 SDK 将默认拥有以下权限:

  • INTERNET:互联网访问权限,以便与网络服务通信。
  • ACCESS_NETWORK_STATE:网络相关信息访问权限。
  • 隐私保护 API 访问权限,这些 API 能够提供核心广告功能,而无需访问跨应用标识符。权限名称尚未最终确定,但这些 API 将受制于应用是否拥有这些权限。
  • AD_ID:能够请求广告 ID。这同样受制于应用是否拥有此权限。
  • BIND_GET_INSTALL_REFERRER_SERVICE:能够使用 Google Play Install Referrer API 来确定应用安装来源。

我们正在调查是否需要以及如何授予其他权限,以便从隐私保护和易用性角度限制对最终用户的影响。如果您遇到任何可能无法通过这组权限满足要求的用例,可以向我们提供反馈

内存

如本文档中的“SDK 权限”部分所述,SDK 运行时将拥有自己的独立内存空间,因为它拥有自己的进程。默认情况下,这种结构会拒绝 SDK 访问应用的内存空间,并且应用同样无法访问 SDK 的内存空间。我们建议保持这种默认行为,以便与最小权限原则保持一致。

存储空间

该方案旨在平衡 SDK 对于访问存储空间以执行其正常操作的需求,并最大限度地减少使用永久性存储空间的跨应用跟踪和跨进程跟踪。我们提议对当今的存储空间访问方式进行以下更新:

  • 应用将无法直接访问其 SDK 存储空间,反之亦然。
  • SDK 将无法访问设备的外部存储空间。
  • 在每个 SDK 运行时内,将具有可供所有 SDK 访问的存储空间,以及指定 SDK 专用的存储空间。

与当前的存储模型一样,存储空间本身没有大小或时长方面的任意限制(换言之,它不是暂时性的,而是在应用卸载时被移除)。

执行

为了确保应用、SDK 和用户之间存在私享系统,执行上下文本身(代码格式、语言构造、可访问的 API,以及系统数据)需要强化这些隐私边界,或至少不会引入能够规避它们的可乘之机。同时,我们希望保留对富功能平台的访问权限,以及 SDK 当前拥有的大部分运行时功能。我们在此建议对运行时环境进行一组更新,以实现这种平衡。

代码

Android 代码(应用和 SDK)主要由 Android 运行时 (ART) 解读,无论代码是使用 Kotlin 还是 Java 编程语言编写的,都是如此。ART 及其提供的语言构造的丰富功能,再加上与替代方案(特别是原生代码)相比时所具有的可验证性,似乎能够适当地平衡功能和隐私保护。我们提议 SDK 代码完全由 Dex 字节码组成,而不是支持 JNI 访问。

我们知道,有些用例(例如使用自定义的已打包 SQLite)因为使用了原生代码,需要替换为 Android SDK 的内置版 SQLite 等替代方案。

SELinux

在 Android 中,每个进程(包括作为 root 运行的进程)都使用特定的 SELinux 上下文运行,这使得内核能够管理对系统服务、文件、设备和其他进程的访问权限控制。为了保留大部分 SDK 用例,同时尽量减少对我们正在努力推进的隐私保护措施的规避行为,我们提议从非系统应用的 SELinux 上下文中为 SDK 运行时进行以下更新:

  • 将有数量有限的一组系统服务可供访问。(我们正在积极进行相关设计)
  • SDK 将只能在其 APK 中加载和执行代码。
  • 将有数量有限的一组系统属性可供访问。(我们正在积极进行相关设计)

API

尽管大部分基于 Java 的语言 API 都支持我们正努力在 SDK 运行时内实现的隐私保护模型,但仍有一些基于 Java 的 API 使得保留用户和 SDK 隐私保护功能变得非常困难,例如反射和调用 API。因此,我们提议阻止从 SDK 运行时内访问这两组 API(可能还会阻止我们正在积极调查的其他 API),并针对会对各种用例造成的影响征求反馈。我们将在日后的更新中分享完整方案。

此外,为了加强隐私保护,近期推出的 Android 平台版本对访问永久标识符的限制越来越多。对于 SDK 运行时,我们提议进一步限制访问可用于进行跨应用跟踪的标识符。

最后,无论在任何时间,RE SDK 都将无法使用通知 API 来发送用户通知。

生命周期

应用 SDK 目前遵从主应用的生命周期,也就是说,当应用进入或离开前台、关闭或因内存压力而被操作系统强行停止时,应用的 SDK 也会如此。我们提议将应用的 SDK 拆分到另一个进程中,这意味着生命周期将发生以下变化:

  • 应用可被用户或操作系统终止。之后,SDK 运行时将立即自动终止。
  • 在出现诸如以下情况时,SDK 运行时可被操作系统终止:内存压力,或 SDK 中存在未处理的异常。

    SDK 运行时的运行优先级略低于关联的应用;因此,在 SDK 运行时因内存压力而终止后,应用很可能会在不久会终止。如果不是这样,或者有其他原因,我们的方案向应用开发者提供了相关的生命周期回调方法,以便他们处理这种异常并通过 init() 调用(会重新加载 SDK 运行时)重新初始化 SDK 运行时。

    如果出现持续失败的情况,应用开发者需要计划在不使用 SDK 的情况下进行优雅降级,或者如果 SDK 对于应用的核心功能来说至关重要,则通知用户。如需进一步详细了解这种“从应用到 SDK”的交互,请参阅本文档中的“通信”部分

非 RE SDK 可以继续使用可用于其嵌入式应用的标准操作系统基元(包括服务、activity 和广播),RE SDK 则无法使用它们。

媒体呈现

有些 SDK 是在应用指定的视图中呈现文本、图片和视频等内容。为了实现这一点,我们提议了一种远程呈现方法。在采用该方法时,SDK 将从 SDK 运行时内呈现媒体,但会使用 SurfaceControlViewHost API 以允许媒体在应用指定的视图中呈现。这使得 SDK 能够以用户专享的方式呈现相应媒体,同时有助于防范和检测与呈现的媒体之间的无效或欺诈性用户互动。

SDK 运行时内的 SDK 将支持原生广告,即那些不是由 SDK 而是由应用呈现的广告。信号收集和广告素材提取过程与呈现非原生广告时一致;不过,SDK 运行时的呈现保护功能(由 SDK 为典型 WebView 呈现提供的保护功能)可能无法实现。我们正在对该领域进行积极调查。

插播视频广告是指在视频播放期间插播的广告,在应用内的播放器中显示。鉴于视频在应用内的播放器中播放,而不是在 SDK 中的播放器或视图中播放,因此呈现模型与其他广告格式的不同。我们正在积极探索相关机制,以便同时支持服务器端广告插播和基于 SDK 的广告插播。

系统运行状况

我们希望尽可能降低 SDK 运行时对最终用户设备的系统运行状况造成的影响,并且正在设计实现这一目标的方法。不过,由于 SDK 运行时会对系统运行状况造成影响,因此一些系统资源非常有限的入门级 Android 13 设备(例如 Android [Go 版本])很可能不支持 SDK 运行时。我们很快将分享成功使用 SDK 运行时需要达到的最低要求。

通信

由于应用和 SDK 目前在同一进程中运行,因此它们之间的通信不受约束且不经过任何中间环节。此外,Android 允许应用间通信,即使通信的起点和终点是 SDK,也没有问题。这种自由流动通信模型支持多种用例,但同时也为在未披露的情况下在应用之间、应用内的 SDK 之间以及应用之间共享数据提供了可乘之机。我们提议对这种通信模型进行以下更新,力争在发挥此类通信的价值和实现我们的既定目标之间取得平衡。

从应用到 SDK

应用和 SDK 之间的接口是向 SDK 进行通信的最常用通信路径,而 SDK 的 API 则是许多面向用户的独特功能和创新功能的所在之处。我们力争将 SDK 的创新功能和独特功能保留在此处。因此,我们的方案可助力 SDK 向应用公开 API,并确保应用可以受益于所有这些创新功能。

鉴于 SDK 运行时的进程边界结构,我们提议构建一个可在应用内访问的编组层,以便在应用和 SDK 之间跨此边界传送 API 调用和响应或回调。我们提议由 SDK 开发者定义该编组层的接口,并通过我们将开发的官方开源构建工具生成这个接口。

通过此方案,我们希望使应用开发者和 SDK 开发者无需再进行样板编组工作,同时让 SDK 开发者能够灵活地进行开发,并确保 SDK 代码在 SDK 运行时内运行,以实现我们的隐私保护目标。如果我们采用这种路径,则需要根据您的意见和建议设计 API 定义语言和工具。

一般交互模型将如下所示:

  • 应用通过接口调用 SDK,以便传入回调。
  • SDK 以异步方式满足请求,并使用回调进行响应。
  • 这可以泛化到任何“发布商-订阅者”模型,即意味着应用可以通过回调来订阅 SDK 中的事件,当这些事件发生时,将会触发回调。

此方案采用的这种新的跨进程结构导致的一个后果是,需要管理两个进程生命周期:一个是应用本身的进程生命周期,另一个是 SDK 运行时的进程生命周期。我们的方案旨在尽可能多地实现自动化,以便最大限度地减少对应用开发者和 SDK 开发者的影响。图 3 显示了我们正在考虑的一种方法:

示意图
图 3. 应用和 SDK 启动期间的“从应用到 SDK”交互的序列示意图。

该平台将为应用公开新的 API,以便将 SDK 动态加载到 SDK 运行时进程,接收关于进程状态更改的通知,并与加载到 SDK 运行时的 SDK 进行交互。

  • 首先,应用将注册一个回调,以便在发生 SDK 运行时进程启动(重启)或 SDK 将数据发回到应用等事件时收到通知。例如,应用可能会在应用启动期间注册回调。

    以下代码片段提供了一个说明性的 API 示例:

    SdkRuntimeManager.registerSdkRuntimeCallback(SdkRuntimeCallback callback,
        Executor executor)
    
  • 应用必须先请求平台加载 SDK,然后才能与 SDK 交互。为了确保系统的完整性,应用将在清单文件中指定想要加载的 SDK,这些 SDK 将是唯一可加载的 SDK。应用将能够请求加载特定的 SDK 或其清单中定义的所有 SDK。这样一来,应用将能够在应用启动期间或 SDK 运行时重启时加载 SDK。

    以下代码片段提供了一个说明性的 API 示例:

    SdkRuntimeManager.loadSdk(String sdkName, LoadSdkCallback callback,
        Executor executor)
    
    SdkRuntimeManager.loadAllSdks(LoadAllSdksCallback callback,
        Executor executor)
    
  • SDK 加载到 SDK 运行时之后,我们的方案允许应用通过从 SDK 的接口生成的编组层与 SDK 进行交互。在后台,调用会通过 sendData() API 进行编组。说明性示例:

    SdkRuntimeManager.sendData(String sdkName, Bundle data)
    
  • 如本文档中的“媒体呈现”部分所述,为了使应用获取 SDK 以便在视图中呈现媒体,应用可以调用 requestSurfacePackage() 并获取相应的 SurfaceControlViewHost.SurfacePackage

    以下代码片段提供了一个说明性的 API 示例:

    SdkRuntimeManager.requestSurfacePackage(String sdkName, IBinder appToken,
        int displayId, Bundle extraParams,
        RequestSurfacePackageCallback callback, Executor executor)
    
  • 这样一来,应用便可以通过 SurfaceView 中的 setChildSurfacePackage API 将返回的 SurfacePackage 嵌入到 SurfaceView 中。

    以下代码片段提供了一个说明性的 API 示例:

    SurfaceView.setChildSurfacePackage(SurfacePackage surfacePackage)
    

我们的方案是,sendData()requestSurfacePackage() API 是通用的,并且不能由应用直接调用。相反,这些 API 将由生成的 API 引用(如上所述)来调用,以减轻应用开发者的负担。

从 SDK 到 SDK

这种情况是指同一个应用中的两个 SDK 需要进行通信。当指定的 SDK 设计为包含多个组成 SDK 时,可能会发生这种情况,并且当来自不同方的两个 SDK 需要协作以满足来自调用方应用的请求时,也可能会发生这种情况。

您需要考虑以下两种主要情况:

  • 两个 SDK 均为 RE。在这种情况下,两个 SDK 都是在 SDK 运行时内运行,并可获享其所有保护功能,包括缺少用于发现的反射功能。SDK 将无法像现在那样在应用中进行通信。因此,我们正在设计 SDK 运行时内用于进行 SDK 注册和发现的 API,以促进通信。
  • 只有一个 SDK 为 RE
    • 如果调用方 SDK 在应用内运行,这与应用本身调用 SDK 运行时内的第二个 SDK 没有什么不同。
    • 如果调用方 SDK 在 SDK 运行时内运行,我们提议公开一个通用 sendData(...) 调用,让应用中的代码监听、处理和响应系统提供的回调。我们正在对此进行积极调查。

在设计这些基元时,我们会考虑以下用例:

  1. 中介和出价。许多广告 SDK 都提供中介或出价功能,以便 SDK 调用各种其他 SDK 来进行广告展示(中介),或调用各种其他 SDK 来收集信号以运行竞价(出价)。通常,协调 SDK 将通过其提供的适配器调用其他 SDK。有了上述基元后,协调 SDK(无论是否为 RE)都应该能够访问所有 RE SDK 和非 RE SDK,以进行正常操作。我们正在对这种上下文中的呈现功能进行积极调查。
  2. 功能推介。有些 SDK 产品由较小的 SDK 组成,这些较小的 SDK 通过 SDK 间发现进程来确定向应用开发者公开的最终功能集。我们希望注册和发现基元支持此用例。
  3. 发布器订阅模型。有些 SDK 将有一个核心的事件发布器,其他 SDK 或应用将能够订阅该发布器,以便通过回调接收通知。上面的基元应支持此用例。

从应用到应用

这是应用间通信,在这种情况下,两个通信的进程中至少有一个是 RE SDK。由于这是跨应用通信,因此不可避免地会为在未披露的情况下共享数据提供可乘之机。

这导致的后果是,SDK 运行时将无法通过任何方式(包括广播和 intent)向任何其他应用进程通信。这样一来,SDK 运行时内的任何 SDK 都将无法与任何其他应用或由其他应用托管的任何 RE SDK 进行通信。

开发

该方案的一个主要原则是,尽可能降低对开发者生态系统的影响。因此,该方案将为开发者提供一整套开发工具,以便他们编写、构建、调试 RE 应用和 SDK。不过,为了确保该方案的完整性,我们将对 RE 应用和 SDK 的配置、编写和构建方式进行一些更改。

编写

Android Studio 和相关工具将更新为 SDK 运行时感知型,以便帮助确保开发者已正确配置其 RE 应用和 SDK,并确保旧版调用或不受支持的调用会更新为相关的较新替代方案。在编写阶段,我们的方案中有一些需要开发者执行的步骤。

应用开发者

应用将需要在其应用清单中指定其 RE SDK 和 SDK 证书依赖项。在我们的方案中,我们将此视为应用开发者提供的可信来源。例如:

  • 名称:SDK 或库的软件包名称。
  • 主要版本:SDK 的主要版本代码。
  • 证书摘要:SDK build 的证书摘要。对于指定的 build,我们提议 SDK 开发者通过相关的应用商店获取并注册此值。

这仅适用于通过应用商店分发的 SDK(无论是否为 RE)。静态关联 SDK 的应用将使用当前的依赖项机制。

鉴于我们的目标是尽可能降低对开发者的影响,因此做到以下一点至关重要:一旦指定了支持 SDK 运行时的目标 API 级别,应用开发者便只需要一个 build,这可以是在支持 SDK 运行时的设备上运行的 build,也可以是在不支持 SDK 运行时的设备上运行的 build。

SDK 开发者

在我们提议的设计中,RE SDK 开发者需要在清单中明确声明一个代表 SDK 或库实体的新元素。此外,还需要提供一组与依赖项类似的值,以及一个次要版本:

  • 名称:SDK 或库的软件包名称。
  • 主要版本:SDK 的主要版本代码。
  • 次要版本:SDK 的次要版本代码。

如果 RE SDK 开发者使用其他 RE SDK 作为构建时依赖项,他们可能需要按照应用开发者声明这些依赖项的方式来声明它们。依赖于非 RE SDK 的 RE SDK 将静态关联它们。如果非 RE SDK 需要 SDK 运行时不支持的功能,或者必须在应用的进程中运行,这种静态关联可能会引发一些问题,而系统会在构建时或测试通过期间检测到这些问题。

RE SDK 开发者可能希望继续支持非 RE 设备,例如搭载 Android 12 或更低版本的设备,以及系统资源非常有限的入门级 Android 13 设备(如本文档中的“系统运行状况”部分所述)。我们正在设法确保 SDK 开发者可以保留单个代码库来支持 RE 环境和非 RE 环境。

构建

应用开发者

我们预计应用开发者在构建步骤中需要执行的操作只有很小的变化。SDK 依赖项(无论是在本地分发还是通过应用商店分发,也无论是否为 RE)将需要存在于机器上,以便执行 lint 请求、编译和构建操作。我们提议 Android Studio 在正常使用情况下从应用开发者那里获取这些详细信息,并使其尽可能公开透明。

虽然我们预计调试 build 将需要包含调试 build 中存在的所有代码和符号,以实现可调试性,但发布 build 将可以选择从最终工件中移除所有通过应用商店分发的 SDK(无论是否为 RE)。

我们目前处于设计阶段的早期,并将在实现这一点时分享更多信息。

SDK 开发者

我们正在努力确保 SDK 的非 RE 版本和 RE 版本都可以内置到单个工件中以进行分发。这样一来,应用开发者将无需为 SDK 的 RE 版本和非 RE 版本分别支持单独的 build。

与应用非常相似,任何通过应用商店分发的依赖项 SDK 都将需要存在于机器上,以便执行 lint 请求、编译和构建操作,并且我们预计 Android Studio 应该能够无缝地促进这一点。

测试

应用开发者

正如我们的方案中所述,应用开发者将能够在搭载 Android 13 的设备上按照正常方式测试其应用。开发者构建应用后,应用将能够安装在 RE 设备或模拟器上。此安装过程可确保将正确的 SDK 安装到设备或模拟器的 SDK 运行时内,无论 SDK 是从远程 SDK 存储库中提取的,还是从构建系统的缓存中提取的。

SDK 开发者

SDK 开发者通常在设备和模拟器上使用内部测试应用来测试其开发成果。我们的方案不会改变这一点,并且应用内验证将遵循上面针对应用开发者介绍的相同步骤,并且使用同时适用于 RE 应用和非 RE 应用的单个构建工件。SDK 开发者将能够单步调试其代码(无论是否位于 SDK 运行时内),但在使用高级调试和性能剖析工具方面可能存在一些限制。我们正在对该领域进行积极调查。

分发

我们将应用与其 SDK 进行分离的设计方案为通过应用商店分发 SDK 创造了可能。这种可能性涵盖了所有应用商店,而非仅限于任何特定应用商店。这种方式的好处显而易见:

  • 确保 SDK 的质量和一致性。
  • 为 SDK 开发者简化发布工作。
  • 加快向已安装的应用分发 SDK 次要版本更新。

为了支持 SDK 分发,应用商店可能需要提供以下大部分功能:

  • 可供 SDK 开发者执行以下操作的机制:将其可通过应用商店分发的 SDK 上传到商店、更新这些应用、回滚这些应用,可能还会移除这些应用。
  • 可实现以下目标的机制:确保 SDK 及其来源的完整性,确保应用及其来源的可靠性,以及解析其依赖项。
  • 可实现以下目标的机制:以始终可靠且高效的方式将它们部署到设备上。

常见问题解答

  1. 什么是广告相关 SDK?

    一个 SDK,在不是归广告主所有的应用上,可促进出于商业目的通过消息定位用户的任何环节。这包括但不限于可以为后续定位创建用户组的分析 SDK、广告服务 SDK、适用于广告的防滥用和防欺诈 SDK、互动 SDK 和归因 SDK。

  2. 任何 SDK 都可以在 SDK 运行时内运行吗?

    虽然最初的侧重点是广告相关 SDK,但非广告相关 SDK 的开发者如果寻求保护隐私并相信它们可以在上述条件下运行,则可以分享有关其 SDK 在 SDK 运行时内运行的反馈。不过,SDK 运行时并非与所有 SDK 设计都兼容。除了已记录的限制,SDK 运行时可能不适合需要与主应用进行实时通信或高吞吐量通信的 SDK。

  3. 为什么我们选择进程隔离,而不是在进程的基于 Java 的运行时内隔离?

    我们致力于为 Android 用户提供隐私保证,但基于 Java 的运行时目前不能促进实现这一保证所必需的安全边界。尝试实现此类边界可能需要多年的努力,而且不一定能成功。因此,我们选择使用进程边界,这是一种经过时间考验且易于理解的技术。