体 系 结 构 导 航 软 件 使 用 实 例 1 JNI 调 用 关 系 Android 系 统 以 Java 语 言 提 供 接 口, 但 大 多 数 功 能 都 使 用 C/C++ 来 实 现, 或 者 二 者 配 合 实 现,JNI 是 上 下 层 的 桥 梁,JNI 调 用 过 程 的 分 析 是 系 统 分 析 中 不 可 缺 少 的 一 环 ; 系 统 中 有 些 接 口 直 接 通 过 JNI 到 下 层 进 行 功 能 实 现, 有 些 接 口 则 通 过 系 统 服 务 来 实 现 用 户 需 求, 而 系 统 服 务 往 往 也 是 通 过 JNI 在 下 层 实 现 具 体 功 能, 在 系 统 分 析 时, 我 们 往 往 希 望 能 清 晰 的 看 到 系 统 进 行 JNI 调 用 的 层 面, 以 及 JNI 调 用 的 具 体 代 码 位 置 因 此, 体 系 结 构 导 航 软 件 补 充 了 JNI 调 用 关 系 数 据, 在 分 析 过 程 中 可 以 清 楚 定 位 JNI 层 的 调 用, 下 面 以 两 个 实 例 来 分 析 导 航 软 件 对 系 统 分 析 的 辅 助 作 用 1.1 Android API 实 现 的 辅 助 分 析 Android 官 方 公 布 的 API 是 应 用 开 发 的 规 范 接 口, 在 进 行 系 统 优 化 或 者 移 植 过 程 中, 往 往 会 以 系 统 API 的 成 功 运 行 为 阶 段 目 标, 一 个 API 类 基 本 上 包 含 了 一 个 较 为 完 善 的 功 能, 可 以 很 好 地 作 为 分 析 牵 引 者 或 验 证 目 标, 可 以 从 接 口 层 出 发, 经 服 务 层 JNI 本 地 库 HAL 最 终 到 内 核 层, 进 行 一 整 套 的 分 析, 从 而 更 加 完 整 更 加 系 统 的 分 析 验 证 某 一 项 功 能 或 服 务 在 出 现 问 题 时, 配 合 体 系 结 构 导 航 软 件 可 以 很 好 地 进 行 调 用 分 析 和 问 题 排 查 以 音 频 系 统 为 例, 官 方 提 供 的 API 类 包 括 AudioTrack 和 AudioRecord, 二 者 分 别 用 于 播 放 和 录 音, 当 然 可 以 播 放 音 频 的 API 类 还 包 括 MediaPlayer, 不 过 它 包 含 的 内 容 较 为 宽 泛, 还 包 括 音 视 频 解 码 等 内 容 在 移 植 音 频 系 统 时, 我 们 首 先 会 对 Android 音 频 系 统 进 行 简 单 分 析 了 解,Android 的 音 频 系 统 分 为 上 层 服 务 和 下 层 服 务, 上 层 服 务 主 要 是 AudioService, 用 于 控 制 音 量, 音 频 设 备 插 拔 处 理 等 ; 下 层 服 务 主 要 是 AudioFlinger 和 AudioPolicyService, 前 者 和 底 层 设 备 打 交 道, 通 过 HAL 层 访 问 底 层 音 频 设 备,AudioPolicyService 则 是 进 行 策 略 控 制, 例 如 应 该 从 听 筒 耳 机 接 口 还 是 蓝 牙 设 备 进 行 输 出 在 完 成 三 个 服 务 的 移 植 启 动 后, 为 测 试 移 植 功 能 是 否 可 用, 以 AudioTrack 接 口 为 例 播 放 wav 音 频 文 件 此 时 会 发 生 各 种 各 样 的 问 题, 最 直 接 的 问 题 : 播 放 没 有 任 何 声 音 这 个 问 题 可 能 由 很 多 原 因 引 起, 首 先 想 到 的 就 是 底 层 设 备 没 有 接 受 到 数 据, 如 果 没 有 收 到 数 据, 那 么 到 底 是 哪 一 部 分 出 现 了 问 题 此 时 我 们 不 可 能 直 接 扎 入 代 码 进 行 分 析, 因 为 那 样 很 可 能 需 要 做 很 多 无 用 功, 单 单 上 层
一 个 AudioService.java 文 件 就 有 6000 行 代 码, 当 然 幸 运 的 时 候 你 可 能 直 接 看 到 问 题 所 在, 但 是 大 部 分 情 况 下 稍 微 复 杂 一 点 的 系 统 就 需 要 花 费 很 多 时 间 ; 那 么 上 层 AudioService 服 务 在 数 据 传 输 时 是 否 产 生 了 影 响 呢? 此 时, 通 过 体 系 结 构 导 航 软 件 进 行 初 步 分 析 梳 理, 就 可 以 对 某 些 问 题 进 行 排 查 确 认 首 先 在 体 系 结 构 导 航 软 件 中 找 到 AudioTrack 这 个 API 类, 选 择 版 本 5.1, 主 页 上 Frameworks 层 的 API 层 中 很 明 显 有 Media_API 模 块,AudioTrack 包 前 缀 为 android.media, 进 入 该 模 块 后 可 以 看 到 包 含 的 所 有 文 件, 包 括 AudioTrack.java, 如 下 : (1) 首 先 右 键 查 看 AudioTrack 这 个 文 件 的 调 用 关 系
很 明 显 看 到 有 一 个 JNI 调 用, 而 且 这 个 JNI 调 用 的 名 字 专 门 针 对 AudioTrack, 那 么 一 般 这 种 情 况 下, 该 类 的 主 要 实 现 是 直 接 通 过 JNI 实 现 的, 此 时 需 要 通 过 AudioTrack.java 包 含 的 接 口 进 行 进 一 步 确 认 (2) 双 击 进 入 AudioTrack.java 文 件, 可 以 看 到 它 只 有 一 个 AudioTrack 类, 进 入 这 个 类 可 以 看 到 它 包 含 的 成 员 函 数 成 员 变 量 和 内 部 类, 如 下 所 示 : 这 里 面 包 含 很 多 函 数, 但 是 通 过 查 找, 可 以 看 到 在 进 行 接 口 测 试 时 使 用 的 接 口,play write 和 stop 函 数, 右 键 查 看 其 各 自 调 用 关 系, 如 下 所 示 : 很 明 显 的 看 到 了 native_start 和 native_stop 函 数, 右 键 分 别 查 看 这 两 个 函 数 的 调 用 关
系, 结 果 如 下 : 相 信 看 到 这 里, 就 能 够 很 清 楚 的 知 道, 我 们 在 调 用 接 口 AudioTrack 的 时 候, 其 实 是 直 接 通 过 JNI 和 下 层 交 互 的, 音 频 数 据 的 传 输 并 没 有 经 过 上 层 的 AudioService 服 务, 也 就 是 说 音 量 设 置 和 数 据 传 输 是 分 开 进 行 的 此 时 我 们 可 以 先 暂 时 不 去 考 虑 分 析 上 层 的 AudioService.java 文 件, 而 是 可 以 直 接 转 入 下 层 的 服 务 进 行 分 析 1.2 特 定 服 务 执 行 过 程 的 辅 助 分 析 Android 系 统 提 供 了 各 类 服 务, 在 优 化 或 移 植 过 程 中, 往 往 会 针 对 某 个 关 注 服 务 进 行 重 点 分 析, 梳 理 其 代 码 逻 辑, 确 定 需 要 优 化 或 者 适 配 的 点 上 层 Java 服 务 往 往 都 是 通 过 JNI 在 下 层 实 现 具 体 功 能, 配 合 导 航 软 件 可 以 很 方 面 的 获 知 其 代 码 的 调 用 过 程, 配 合 源 码 联 动 可 以 直 接 查 看 函 数 实 现 内 容 例 如, 以 输 入 系 统 为 例, 输 入 系 统 肯 定 是 要 和 底 层 鼠 标 键 盘 设 备 打 交 道, 如 果 要 对 Android 输 入 系 统 进 行 修 改, 改 变 其 输 入 事 件 的 来 源, 那 么 就 需 要 知 道, 输 入 系 统 是 在 哪 里 实 现 和 底 层 设 备 的 交 互 在 Android 启 动 服 务 中 可 以 很 明 显 的 看 到 inputmanagerservice 这 个 服 务, 但 是 它 是 在 java 层 启 动 的 服 务, 那 么 很 容 易 就 猜 想 inputmanagerservice 是 通 过 JNI 到 Native 层 进 行 设 备 访 问, 或 者 是 通 过 访 问 Native 层 的 某 个 服 务 获 取 数 据? 此 时 可 以 通 过 体 系 结 构 导 航 软 件, 对 猜 想 进 行 快 速 确 认, 并 配 合 源 码 查 看 功 能, 进 行 内 容 分 析 (1) 该 服 务 在 SystemServer.java 中 启 动, 调 用 其 构 造 函 数 进 行 服 务 添 加 后, 调 用 start 函 数 进 行 启 动 在 主 页 面 中 查 看 Frameworks 层 ->Service->Core_Service, 进 入 内 部 模 块 services, 可 以 看 到 该 模 块 下 所 有 的 文 件, 这 些 都 是 系 统 Java 层 的 主 要 服 务 类, 通 过 下 拉 框 选 择 目 录 input, 可 以 很 方 面 的 按 照 系 统 目 录 选 择 要 关 注 的 内 容
右 键 查 看 InputManagerService.java 的 调 用 关 系, 可 以 很 清 楚 的 看 到 它 在 系 统 各 个 层 次 中 的 调 用 关 系 包 括 JNI 调 用 ( 服 务 的 JNI 调 用 封 装 于 libandroid_servers 模 块 中, 考 虑 到 其 不 属 于 系 统 接 口 的 JNI 层, 应 该 更 倾 向 于 服 务 的 支 持 内 容, 因 此 现 阶 段 被 划 分 到 了 Server_support 模 块, 属 于 Support 层 ) 双 击 进 入 InputManagerService.java 内 部, 包 含 一 个 类 InputManagerService, 进 入 该 类 内 部, 就 可 以 看 到 所 有 包 含 的 函 数 和 变 量 以 服 务 开 始 函 数 start 为 分 析 目 标, 寻 找 到 该 函 数, 右 键 查 看 其 调 用 关 系
可 以 大 体 知 道 start 函 数 中 主 要 做 了 什 么 操 作, 如 果 熟 悉 导 航 软 件 风 格 和 系 统 源 码 的 话, 就 可 以 知 道 函 数 startotherservices 是 SystemServer 用 来 添 加 服 务 的, 函 数 i 肯 定 是 log 的 调 用, 而 nativestart 显 然 就 是 真 正 的 下 层 构 造 实 现 的 调 用 接 口, 右 键 查 看 其 调 用 关 系, 可 以 查 看 到 对 应 的 JNI 接 口, 借 助 源 码 联 动 平 台 可 以 查 看 源 码 实 现, 继 续 往 下 分 析 至 此, 我 们 可 以 肯 定 InputManagerService 在 启 动 函 数 start 中, 基 本 没 有 做 太 多 操 作, 很 快 就 通 过 JNI 调 用 转 入 下 层 实 现 2 版 本 差 异 性 比 对 Android 系 统 的 版 本 更 新 比 较 快, 在 做 系 统 优 化 或 者 移 植 的 时 候, 往 往 需 要 针 对 新 版 本 的 出 现 进 行 相 应 的 修 改, 如 果 能 很 快 地 确 定 系 统 关 注 点 是 否 有 修 改 大 体 有 哪 些 修 改, 对 于 升 级 操 作 就 有 非 常 大 的 帮 助, 体 系 结 构 导 航 软 件 实 现 了 4.0.4->5.1,5.1->6.0, 5.1->x865.1 的 源 码 版 本 差 异 性 比 对, 对 于 关 注 模 块 的 跨 版 本 分 析 有 很 好 的 导 向 作 用 以 图 形 部 分 为 例, 图 形 子 系 统 是 一 个 比 较 独 立 的 子 系 统, 从 Frameworks 层 到 HAL 层, 在 各 个 层 都 有 相 关 实 现, 贯 穿 前 后 在 对 图 形 系 统 进 行 跨 版 本 的 优 化 或 移 植 时, 就 需 要 知 道 各 个 层 在 两 个 版 本 之 间 的 具 体 变 化 点, 同 时 也 需 要 知 道 多 个 版 本 的 具 体 差 异 变 化, 以 很 好 的 对 多 版 本 适 配 进 行 规 划
例 如 :1 在 进 行 图 形 子 系 统 移 植 的 版 本 升 级 时, 应 该 从 哪 个 地 方 入 手, 应 该 关 注 于 哪 个 点?2 为 了 适 应 更 多 的 版 本, 在 移 植 时 应 该 在 哪 些 地 方 进 行 更 多 的 分 析, 以 减 少 后 续 升 级 的 工 作 量? 2.1 两 个 版 本 的 差 异 性 比 对 辅 助 分 析 (1)Framework 层 的 比 对 : 图 形 部 分 的 Frameworks 层 最 重 要 的 部 分 就 是 SurfaceFlinger 服 务 和 相 关 的 图 形 库, 因 其 不 对 外 提 供 服 务 接 口, 主 要 用 于 内 部 调 用, 属 于 支 撑 内 容, 因 此 暂 时 划 分 在 Support 层 以 4.0.4 到 5.1 的 图 形 分 析 为 例, 这 两 个 版 本 的 变 化 比 较 大, 以 UI_Support 模 块 为 关 注 点, 查 看 SurfaceFlinger 的 变 化, 如 下 所 示 : 可 以 看 出 其 变 化 量 是 非 常 巨 大 的, 双 击 进 入 该 模 块, 查 看 具 体 的 文 件 变 化 情 况, 结 果 如 下, 可 以 看 到 5.1 新 增 了 很 多 文 件, 当 然 也 删 除 了 很 多 4.0.4 的 文 件 ( 页 面 上 暂 未 显 示 ) 至 此, 可 以 回 答 开 头 的 第 一 个 问 题, 在 4.0.4 到 5.1 的 SurfaceFlinger 移 植 或 者 优 化
升 级 时, 因 其 结 构 变 化 巨 大, 需 要 对 整 个 代 码 逻 辑 进 行 重 新 梳 理 (2)HAL 层 的 比 对 : 以 5.1 到 x865.1 的 图 形 分 析 为 例, 按 照 版 本 比 对 操 作, 最 终 可 以 得 到 主 模 块 的 差 异 性, 其 中 可 以 很 明 显 的 看 到,HAL 层 有 新 增 模 块 drm_gralloc 该 模 块 是 图 形 部 分 的 HAL 层 实 现, 在 进 行 图 形 分 析 时, 可 以 很 清 楚 的 知 道 X865.1 在 HAL 层 做 了 改 变, 需 要 重 点 关 注 ; 通 过 进 一 步 详 细 分 析 可 以 得 知 :Android5.1 使 用 的 是 gralloc.default.so, 路 径 为 hardware/libhardware/modules/gralloc/, 而 AndroidX865.1 虽 然 也 保 留 了 该 模 块, 但 是 实 际 使 用 的 galloc 是 gralloc.drm.so, 路 径 为 hardware/drm_gralloc/ 至 此, 可 以 回 答 开 头 的 第 一 个 问 题, 在 5.1 到 x865.1 的 HAL 层 移 植 或 者 优 化 升 级 时, 应 该 更 加 关 注 新 增 模 块 drm_gralloc 的 分 析 2.2 多 个 版 本 的 差 异 性 比 对 辅 助 分 析 针 对 UI_Support 模 块 4.0.4->5.1,5.1->6.0 和 5.1->x865.1 的 比 对 结 果 依 次 如 下 :
可 见, 除 了 4.0.4->5.1 的 变 化 巨 大 外,5.1->6.0 和 5.1->x865.1 的 变 化 不 是 很 大, 还 是 针 对 surfaceflinger, 进 入 模 块 内 部 查 看 具 体 文 件 变 化,4.0.4->5.1 的 变 化 在 前 面 已 经 做 了 展 示, 后 面 两 个 版 本 的 具 体 变 化 如 下 : 上 面 两 张 图 在 这 里 没 有 清 晰 的 展 示 具 体 的 变 化, 从 上 图 中 可 以 很 清 楚 的 知 道, 哪 些 文 件 发 生 了 变 化, 总 体 来 说 后 续 版 本 的 变 化 比 较 小 ; 在 移 植 或 优 化 时 一 定 会 进 行 一 些 代 码 修 改, 而 如 果 修 改 的 地 方 在 多 个 版 本 中 常 常 发 生 变 化, 那 么 我 们 应 该 进 行 多 版 本 重 点 分 析, 合 理 设 计 修 改 逻 辑, 或 者 在 逻 辑 允 许 的 情 况 下 尽 量 减 少 这 些 位 置 的 修 改, 以 更 好 的 适 应 各 个 版 本, 减 少 在 版 本 升 级 中 的 工 作 至 此, 针 对 开 头 的 第 二 个 问 题, 给 出 了 较 为 明 确 的 方 向