原文地址:https://source.android.google.cn/devices/tv/
Android TV Input Framework (TIF) 简化了向 Android TV 传送直播内容的过程。Android TIF 为制造商提供了一个标准 API,用于创建能够控制 Android TV 的输入模块,并让他们可以通过 TV Input 发布的元数据来搜索和推荐直播电视内容。
此框架的目的并不在于实施电视标准或区域性要求,而是在于让设备制造商不必重新实现就能够更轻松地满足区域性数字电视广播标准。对于想要创建自定义 TV Input 的第三方应用开发者来说,本部分文档可能也非常实用。
Android TIF 的实现包括 TV Input Manager。TIF 可与 TV 应用(一款第三方应用无法替代的系统应用)搭配使用来访问内置频道和 IP 调谐器频道。此 TV 应用通过 TV Input Manager 与设备制造商或其他方提供的 TV Input 模块进行通信。
TIF 由以下几个部分组成:
com.android.providers.tv.TvProvider
):具有频道、节目和相关权限的数据库com.android.tv.TvActivity
):处理用户互动操作的应用android.media.tv.TvInputManager
):使 TV Input 可与 TV 应用进行通信tv_input
模块):一种硬件定义,实现后可让系统 TV Input 访问电视专用硬件下面将详细介绍这些组件。有关 Android TIF 架构的详细视图,请参见下图。
图 1. Android TV Input Framework (TIF) 架构
下面列出了此架构的运作流程:
signatureOrSystem
TV Input 和 TV 应用拥有对 TV Provider 数据库的完全访问权限,并且能够接收 KeyEvent。TV_INPUT_HARDWARE
权限,向 TV Input Manager Service 发送信号,以通知 TV Input Service 在启动时调用 TV Input Manager Service 并添加其 TV Input。借助此权限,硬件 TV Input 应用可通过一个 TV Input Service 支持多个 TV Input,并能够动态地添加和移除支持的 TV Input。TV Provider 数据库会存储来自 TV Input 的频道和节目。TV Provider 还发布和管理相关权限,以使 TV Input 只能查看自身的记录。例如,特定的 TV Input 只能查看它自己提供的频道和节目,并被禁止访问任何其他 TV Input 的频道和节目。
TV Provider 在内部将“广播类型”映射到“规范类型”。TV Input 负责使用基本广播标准中的值填充“广播类型”,而“规范类型”字段将使用来自 android.provider.TvContract.Genres
的正确相关类型自动填充。例如,对于广播标准 ATSC A/65 和类型为 0x25(意为“体育”)的节目,TV Input 将使用字符串“Sports”填充“广播类型”,并且 TV Provider 将使用映射的值android.provider.TvContract.Genres.SPORTS
填充“规范类型”字段。
有关 TV Provider 的详细视图,请参见下图。
图 2. Android TV Provider
只有在经授权的系统分区中的应用才能读取整个 TV Provider 数据库。
直通 TV Input 不存储频道和节目。
除了频道和节目的标准字段以外,TV Provider 数据库还在 TV Input 可能用来存储任意数据的每个表格中提供 BLOB 类型字段 (COLUMN_INTERNAL_PROVIDER_DATA
)。该 BLOB 数据可能包括自定义信息(如相关调谐器的频率),并可通过协议缓冲区或其他形式提供。还提供“可搜索”字段,用于确保搜索结果中不显示某些频道(例如,为了满足某些国家/地区对于内容保护的特定要求)。
TV Provider 支持频道 (android.provider.TvContract.Channels
) 和节目 (android.provider.TvContract.Programs
) 表格中的结构化数据。这些表格由 TV Input 和系统应用(如 TV 应用)进行填充和访问。这些表格具有四种类型的字段:
COLUMN_DISPLAY_NAME
) 或数字 (COLUMN_DISPLAY_NUMBER
) 或正在观看的节目的标题。COLUMN_TRANSPORT_STREAM_ID
)、原始网络 ID (COLUMN_ORIGINAL_NETWORK_ID
) 和服务 ID (COLUMN_SERVICE_ID
)。COLUMN_INTERNAL_PROVIDER_DATA
)是可自定义的 BLOB 字段,TV Input 可以在这些字段中存储有关其频道或节目的任意元数据。COLUMN_SEARCHABLE
:在某些地区可能要求禁止搜索某些频道。COLUMN_SEARCHABLE = 0
表示不应在搜索结果中显示此频道。COLUMN_BROWSABLE
:仅对系统应用可见。禁止应用浏览频道。COLUMN_BROWSABLE = 0
表示频道列表中不应包含此频道。COLUMN_LOCKED
:仅对系统应用可见。禁止未输入 PIN 码的无效帐号观看频道。COLUMN_LOCKED = 1
表示此频道应受家长控制保护。有关这些字段的更为详尽的列表,请参阅 android/frameworks/base/media/java/android/media/tv/TvContract.java
有权访问相应行的任何人都可以查看所有字段。用户无法直接访问任何字段;他们仅可看到 TV 应用、系统应用或 TV Input 显示的内容。
PACKAGE_NAME
,即拥有该行的软件包(应用),可通过 TvProvider.java 在“查询”、“插入”、“更新”语句中获得该名称。TV Input 仅可以访问它自己写入的信息,无法访问其他 TV Input 提供的信息。signatureOrSystem
应用才可以获取访问整个数据库的 ACCESS_ALL_EPG_DATA
权限。TV Input Manager 为整个 Android TIF 提供了一个中央系统 API。它对应用与 TV Input 之间的交互进行控制,并提供家长控制功能。TV Input Manager 必须与 TV Input 创建一对一的会话。TV Input Manager 允许应用访问安装的 TV Input,以便应用可以:
对于会话,TV Input(除了可使用 TvContract.buildChannelUriForPassthroughInput()
调谐的直通 TV Input)只能由 TV 应用调谐至已被 TV 应用添加到 TV Provider 数据库中的 URI。TV Input 也可以自己设置音量。由设备制造商(签名应用)或安装于系统分区中的其他应用提供和签名的 TV Input 具有对整个 TV Provider 数据库的访问权限。此访问权限可用于构建应用,以浏览和搜索所有可用的电视频道和节目。
应用可以通过 android.media.tv.TvInputManager
创建和注册一个 TvInputCallback
,并在 TV Input 的状态发生改变或添加/移除 TV Input 时进行该回调。例如,TV 应用可以在 TV Input 断开连接时做出以下响应:显示该 TV Input 已断开连接并阻止它被选中。
TV Input Manager 使 TV 应用和 TV Input 之间的通信变得抽象化。TV Input Manager 和 TV Input 标准界面使多个设备制造商可以创建自己的 TV 应用,同时让所有第三方 TV Input 适用于所有 TV 应用。
TV Input 具有 AndroidManifest.xml 并且会预安装或通过 Play 商店、旁加载进行安装,因此是 Android 应用。Android TV 支持预安装的系统应用、由设备制造商签名的应用和第三方 TV Input。
某些输入源(如 HDMI 或内置调谐器输入源)只能由制造商提供,因为它们与底层硬件直接通信。其他输入源(如 IPTV、易地播放和外接机顶盒)可由第三方将其作为 APK 在 Google Play 商店中进行提供。一旦被下载并安装,便可以在 TV 应用中选择这一新的输入源。
图 3. Android TV 系统输入源
在上述示例中,由设备制造商提供的 TV Input 是可信输入源,并拥有对 TV Provider 的完全访问权限。作为直通 TV Input,它不会向 TV Provider 注册任何频道或节目。要获取用于引用直通输入源的 URI,请使用android.media.tv.TvContract
实用程序方法buildChannelUriForPassthroughInput(String inputId)
。TV 应用与 TV Input Manager 进行通信,从而访问 HDMI TV Input。
图 4. Android TV 内置调谐器输入源
在上述示例中,由设备制造商提供的内置调谐器 TV Input 是可信输入源,具有对 TV Provider 的完全访问权限。
图 5. Android TV 第三方输入源
在上述示例中,外接机顶盒 TV Input 由第三方提供。由于此 TV Input 无法直接访问传入的 HDMI 视频 Feed,所以必须借助 TV Input Manager 并使用设备制造商提供的 HDMI TV Input。
通过 TV Input Manager,外接机顶盒 TV Input 可以与 HDMI TV Input 进行通信,并请求它在 HDMI1 上显示视频。因此,机顶盒 TV Input 可以控制电视,而制造商提供的 HDMI TV Input 则可呈现视频。
图 6. Android TV KeyEvent
上图显示了遥控器上的按钮事件如何传递到特定的 TV Input,从而实现画中画 (PIP) 显示。按下按钮的操作由设备制造商提供的硬件驱动程序进行解析,从而将硬件扫描码转换为 Android 键码,并将它们作为KeyEvent 传递到标准的 Android 输入通道 InputReader
和 InputDispatcher
函数。当 TV 应用获得焦点时,它们就会在 TV 应用上触发事件。
只有系统 TV Input 才有资格接收 InputEvents
(前提是这些系统 TV Input 具有 RECEIVE_INPUT_EVENT
系统权限)。TV Input 负责确定要消费哪些 InputEvent,并允许 TV 应用处理它不需要消费的按键。
TV 应用负责确定哪些系统 TV Input 处于有效状态(即用户已选择)、区分传入的 KeyEvents
并将它们路由到正确的 TV Input Manager 会话,以及调用dispatchInputEvent()
以将事件传递到相关联的 TV Input。
下图详细说明了 KeyEvents
如何通过 Android TIF 进行路由。
图 7. Android TV 红色按钮示例
上图描绘了红色按钮应用的流程,该按钮在欧洲较为常用,使用户能够访问电视机上的交互式应用。应用可以通过此传输流程进行传送。用户点击此按钮后,便可以与这些广播应用进行交互。例如,您可以使用这些广播应用来访问相关网页或体育赛事比分。
请参阅“广播应用”部分,了解广播应用如何与 TV 应用进行互动。
在此示例中:
KeyEvents
(例如:红色按钮)作为 InputEvents.
被传递到处于有效状态的 TV Input。RECEIVE_INPUT_EVENT
系统权限。KeyEvents
当做 InputEvents
进行消费,然后广播应用获得焦点并处理InputEvents
直到应用被关闭。注意:第三方 TV Input 从不接收按键事件。
在开发 TV Input 以访问电视专用硬件的过程中,TV Input HAL 起到了辅助作用。与其他 Android HAL 一样,TV Input HAL (tv_input
) 可在 AOSP 源码树中获取,由供应商制定其实现方法。
系统 TV 应用向用户呈现直播电视内容。Android 平台提供了一个参考 TV 应用 (Live TV),设备制造商可以直接按原样使用该应用、对其进行定制、扩展或将其替换掉。Android 开放源代码项目中提供了源代码,您可以按照参考 TV 应用一文中的说明开始构建 TV 应用。
设备制造商可以扩展他们的 TV 应用来实现适用于特定设备制造商或国家/地区的功能,但这不属于 TIF 或参考 TV 应用的职责范畴。
系统 TV 应用至少需处理以下任务:
随着新 Android 版本的发布,平台 TIF API 得到扩展,此功能集将有所增加。CTS 验证程序涵盖了相关的兼容性测试。
Android TV 提供面向第三方 TV Input 的开发者 API,使安装的应用能够将软件频道与直播电视体验相融合。为确保 Android 设备实现保持兼容性,系统 TV 应用有责任向用户显示第三方 TV Input 和频道。参考 Live TV 应用提供了兼容的实现方法;如果要替换系统 TV 应用,则设备制造商必须确保自己的应用提供类似的兼容性,以满足开发者对所有 Android TV 设备的期望。
系统 TV 应用必须在设备的默认直播电视服务旁边显示第三方输入源。开发者 API 的承诺是,用户能够在其标准电视体验中找到频道(安装后)。
根据 Android CDD 的“TV 应用”部分的定义,内置频道和第三方频道之间可存在外观差异。
以下部分说明了 Live TV 应用如何满足 CDD 要求。
新频道设置
用户可首先通过从应用商店(如 Google Play)中查找和安装 TV Input,开始添加新的第三方输入源/频道。
某些第三方 TV Input 可自动将频道添加到 TvProvider 数据库中。然而,大多数 TV Input 将提供“设置”操作组件,使用户能够设置他们的频道、提供登录详细信息及执行其他操作。系统 TV 应用需要确保用户可以启用此“设置”操作组件,因此 CDD 要求在主 TV 应用中只需极少的导航操作便可进入第三方输入源。
参考 Live TV 应用提供了“频道来源”菜单,以供用户访问输入源。
图 8. 转到设置。
图 9. 转到“设置”中的频道来源。
图 10. 从列表中选择您的频道来源。
图 11. 从您的频道来源中添加频道
此外,在安装新的 TvInput 之后,TV 应用菜单的顶部会出现一张通知卡片,让用户直接转到“设置”页面:
图 12. 表示有可用新频道来源的通知。
如果用户通过通知进行操作,他们可以选择设置频道来源,如图 10 所示。
请参阅定义您的 TV Input Service,了解开发者对此领域的期望。
自定义频道列表
设备制造商可以提供一个界面来隐藏某些频道,并让用户能够管理自己的 EPG。Live TV 包括此项功能。
图 13. 在设置中打开频道列表。
图 14. 自定义您的频道列表。
EPG
第三方输入源开发者需要确信,用户可以在常规使用过程中在所有兼容的 Android TV 设备上轻松转到他们的频道。
来自第三方输入源的频道必须作为设备的标准直播电视体验 EPG 的一部分展示出来。可以对第三方频道在外观上加以区别或将其归入单独的类别(请参阅 Android CDD 的“TV 应用”部分),而最重要的是让用户能够找到所安装的频道。
搜索
为确保最佳用户体验,制造商必须实现以下 TV 应用功能:纳入能够满足全局搜索请求的搜索结果。Live TV 提供了一种实现方法(请参阅 com.android.tv.search.TvProviderSearch),它可提供来自第三方输入源(对于平台兼容性而言是必要的)以及内置输入源的结果。
时移
对于运行 Android 6.0 及更高版本的设备,TV 应用必须支持 Android 框架时移 API。此外,制造商必须在 TV 应用中实现播放控件,让用户可以对播放内容执行暂停、继续、快退和快进播放等操作。
对于支持时移的 TV Input,TV 应用需显示播放控件。
图 15. 播放控件
DVR
对于运行 Android 7.0 及更高版本的设备,TV 应用必须支持 Android 框架电视录制 API,从而支持、列出和播放录制的节目。
这样,设备制造商就可以将其 DVR 子系统插入 TIF,并显著减少在电视设备上启用或集成 DVR 功能所需的集成工作量。它还使第三方能够提供可插入 Android TV 设备的售后市场 DVR 系统。
除了录制直播内容外,TV 应用还可以处理资源冲突。例如,如果设备配备了两个调谐器,它便可以同时录制两档节目。如果用户要求录制三档节目,则 TV 应用必须处理这种冲突,并且应该显示通知或要求用户为这些请求安排优先级。
TV 应用还可以实现更复杂的逻辑安排,例如,在用户请求录制一集剧集时询问用户是否希望录制所有后续剧集。
请参阅以下图表,了解可以在 Android TV 中完成的 DVR 实现。
图 16. Android TV 中的数字录像功能
要详细了解如何在 TV Input Service 中实现录制功能,请参阅电视录制一文。
家长控制使用户能够屏蔽不希望播放的频道和节目,但通过输入 PIN 码便可绕过该屏蔽。
TV 应用、TV Input Manager Service、TV Provider 和 TV Input 共同承担实现家长控制功能的责任。
家长控制是强制性的,且在 CTS 验证程序的涵盖范围之内。
许多国家/地区已定义了 TV Input 可以通过 TVContentRating API 使用的分级制度。此外,TV Input 可以按照 CTS 验证程序测试(引入了“假”分级制度)所演示的步骤注册自己的自定义分级制度。在存在标准分级制度的国家/地区,我们鼓励设备制造商将 TIF 家长控制与他们可能包含的任何其他机制结合到一起。
现在,每个频道行都有一个 COLUMN_LOCKED
字段,用于锁定特定频道,使用户在未输入 PIN 码的情况下无法观看这些频道。节目字段COLUMN_CONTENT_RATING
仅针对显示操作,而不用于落实家长控制。
TV Input Manager 会存储所有已屏蔽的 TvContentRating
,并对 isRatingBlocked()
作出响应,从而建议是否应该屏蔽具有给定评级的内容。
当所显示内容的评级发生变化(因节目或频道发生变化)或家长控制设置发生变化(在 ACTION_BLOCKED_RATINGS_CHANGED
和ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED
上)时,TV Input 可通过对 TV Input Manager 调用isRatingBlocked()
来检查是否应该屏蔽当前内容。如果应屏蔽此内容,TV Input 会停用相关音频和视频,并通过调用notifyContentBlocked(TvContentRating)
通知 TV 应用当前内容已被屏蔽。如果不应屏蔽此内容,TV Input 将启用音频和视频,并通过调用notifyContentAllowed()
通知 TV 应用当前内容可播放。
要满足家长控制 API 的要求并创建一个兼容的平台,系统 TV 应用需要为用户提供一种管理家长控制的方式,包括使具体应用能够注册任何自定义评级制度。
当 TV Input 通知 TV 应用当前内容已被屏蔽或当用户尝试查看已屏蔽的频道时,TV 应用将显示 PIN 码界面。
TV 应用不直接存储家长控制设置。当用户更改家长控制设置时,TV Input Manager 会存储所有已屏蔽的 TvContentRating
,TV Provider 则存储已屏蔽的频道。
TV 应用需要声明 android.permission.MODIFY_PARENTAL_CONTROLS
权限,才能更改家长控制设置。
我们鼓励设备制造商进行如下操作:
借助 HDMI-CEC,一台设备可以控制另一台设备,从而让用户通过单个遥控器控制家庭影院中的多台设备。Android TV 使用 HDMI-CEC 来加快设置过程,并允许通过中央 TV 应用远程控制多个 TV Input。例如,它可以切换输入源、开启或关闭设备等。
Android TIF 可将 HDMI-CEC 作为 HDMI 控制服务进行实现,以便设备制造商可以跳过更加复杂的商业逻辑,只需开发与轻量级 Android TV HAL 进行交互的低级驱动程序。Android 提供标准实现的目的是,通过减少分散的实现和选择性功能支持来消除兼容性问题。HDMI 控制服务会使用现有的 Android 服务(包括输入和电源)。
这意味着现有 HDMI-CEC 实现将需要重新设计,才能与 Android TIF 进行互操作。我们建议硬件平台纳入微处理器,以接收 CEC 开机命令和其他命令。
图 17. Android TV 上的 CEC 集成
ActiveSourceChangeListeners
。ActiveSourceChangeListener
获取来源更改通知。setMain
。由于每个国家/地区都具有针对广播的特定要求(MHEG、电视文字广播、HbbTV 等),制造商需要为广播应用提供他们自己的解决方案,例如:
在 Android L 版本中,Android TV 希望设备制造商针对区域性电视堆栈使用系统集成器或 Android 解决方案,将 Surface 传递到电视软件堆栈,或传递与传统堆栈进行交互所需的按键代码。
广播应用和 TV 应用的交互方式如下:
对于语音搜索/推荐功能,广播应用可能支持以语音搜索的方式进行应用内搜索。