尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
comprehensive-rust 教程:在 AOSP 中构建、部署与调用 Rust Binder 服务(birthday_server 实战指南)
comprehensive-rust 教程在 AOSP 中构建、部署与调用 Rust Binder 服务birthday_server 实战指南【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust本指南以 comprehensive-rust 课程中 Android AIDL 章节的deploy一课为核心完整讲解如何把用 Rust 编写的 Binder 服务birthday_server构建、推送到设备并启动再通过service check与service call验证其可用性。读完本文你将掌握 AOSP Soong 构建、adb部署、服务注册检查与 Parcel 结果解析的完整闭环能够独立将课程中的 Birthday Service 示例跑通。背景我们要部署什么在课程中Birthday Service 是一套完整的接口 — 服务实现 — 服务端 — 客户端示例用于演示用 Rust 调用 Android Binder。整个流程由 src/android/aidl/birthday-service.md 起头依次经过定义 AIDL 接口IBirthdayService见 src/android/aidl/birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl在 Rust 中实现该接口src/android/aidl/birthday_service/src/lib.rs编写服务端进程birthday_serversrc/android/aidl/birthday_service/src/server.rs与客户端birthday_clientsrc/android/aidl/birthday_service/src/client.rs。而deploy这一步要解决的是当代码写完之后如何在真实 AOSP 环境里把它变成设备上可用的系统服务。deploy.md原文src/android/aidl/example-service/deploy.md给出的核心操作只有build、push、start三个词但其背后依赖的构建脚本与 Binder 注册机制正是本文要展开的部分。部署前置条件在运行部署命令之前需要满足以下环境要求依据课程构建脚本 src/android/build_all.sh 的头部注释整理AOSP 源码树脚本必须在 AOSP checkout 中执行且需要完成source build/envsetup.sh与lunch课程示例使用aosp_cf_x86_64_phone-userdebug目标即 Cuttlefish 虚拟设备镜像可用的adb环境已连接设备或模拟器adb正常工作让m能看到课程源码AOSP 的构建系统只能看到放在源码树内的Android.bp因此需要把课程仓库放进 AOSP checkout或用 bind mount 挂载例如cd $ANDROID_BUILD_TOP mkdir comprehensive-rust sudo mount -o bind ../path/to/comprehensive-rust/src comprehensive-rust挂载后即可用m hello_rust之类的目标验证构建系统是否识别课程中的模块。build_all.sh中所有m目标如birthday_server、birthday_client、hello_rust等正是依赖这种方式才能被 AOSP 发现并编译。第一步构建并启动服务deploy.md中引用的构建、推送、启动命令实际来自 src/android/build_all.sh 中birthday_server函数内的ANCHOR: birthday_server代码段。原文档通过 mdBook 的{{#include}}机制将脚本片段嵌入页面展开后的完整命令如下m birthday_server adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/tmp adb root adb shell /data/local/tmp/birthday_server逐条解释命令作用m birthday_server调用 Soong 构建系统编译birthday_server这个rust_binary目标产物输出到$ANDROID_PRODUCT_OUT/system/bin/adb push ... /data/local/tmp把编译出的二进制推送到设备上的/data/local/tmp目录adb root以 root 身份重启 adbd。/data/local/tmp需要 root 权限运行且注册 Binder 系统服务通常也需要较高权限adb shell /data/local/tmp/birthday_server在设备上直接启动服务进程它会在前台运行并开始监听 Binder 请求需要特别注意的是birthday_server是一个前台进程启动后会一直占用终端因为服务端调用了join_thread_pool阻塞等待请求。因此在build_all.sh中脚本用birthday_server 将其放到后台运行并记录 PID部署一节也要求在另一个终端中检查服务状态。这与客户端birthday_client不同——后者是短生命周期程序调用完即退出。构建目标对应的 Soong 配置m birthday_server之所以能够成立是因为 src/android/aidl/birthday_service/Android.bp 中定义了对应的 Soong 模块rust_binary { name: birthday_server, crate_name: birthday_server, srcs: [src/server.rs], rustlibs: [ com.example.birthdayservice-rust, libbirthdayservice, ], prefer_rlib: true, // To avoid dynamic link error. }关键点rustlibs引用了两个依赖com.example.birthdayservice-rustAIDL 接口生成的 Rust crate与libbirthdayservice服务实现所在的rust_library定义见同文件ANCHOR: libbirthdayservice段prefer_rlib: true注释明确说明是为了避免动态链接错误即要求静态链接 Rust 库保证二进制在设备上可独立运行AIDL 接口 crate 本身由 src/android/aidl/birthday_service/aidl/Android.bp 中的aidl_interface模块生成其中backend.rust.enabled true表明Rust 后端默认未启用需要显式打开这是 Rust AIDL 与 Java/C 后端的显著差异。第二步用service check验证服务已注册服务启动后在另一个终端执行service check确认它已经被 Android 服务管理器ServiceManager登记adb shell service check birthdayservice预期输出Service birthdayservice: found这里birthdayservice正是服务端代码 src/android/aidl/birthday_service/src/server.rs 中定义的注册名const SERVICE_IDENTIFIER: str birthdayservice; ... binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder()) .expect(Failed to register service);service check返回found意味着注册成功也印证了部署流程中启动服务 → 注册到 ServiceManager这一环是通的。build_all.sh中还有一个配套细节脚本在启动birthday_server后会用循环等待服务真正注册完成while adb shell service check birthdayservice | grep -q not found; do echo Waiting on birthdayservice... sleep 3 done这说明服务注册是异步过程——进程启动后需要一点时间完成 Binder 初始化与add_service调用立即service check可能得到not found。服务端注册的完整机制server.rs的main函数完整展示了 Rust Binder 服务的注册四步曲deploy 的start环节能成立的原因fn main() { let birthday_service BirthdayService; // 1. 创建服务实例 let birthday_service_binder BnBirthdayService::new_binder( // 2. 包装为 Bn* 类型 birthday_service, binder::BinderFeatures::default(), ); binder::add_service(SERVICE_IDENTIFIER, birthday_service_binder.as_binder()) // 3. 注册 .expect(Failed to register service); binder::ProcessState::join_thread_pool(); // 4. 加入线程池 }BirthdayService是 src/android/aidl/birthday_service/src/lib.rs 中实现IBirthdayServicetrait 的类型BnBirthdayService由 AIDL 编译器生成相当于 C Binder 世界中的BnBinder基类角色由于 Rust 没有继承这里通过组合把自定义服务实例放进生成的BnBirthdayService中binder::add_service将服务以字符串标识注册进 ServiceManagerjoin_thread_pool让当前线程加入 Binder 线程池开始监听连接——这正是服务端进程不退出、持续响应请求的原因。课程中还特别强调wishHappyBirthday等 AIDL 方法签名是self而非mut self因为 Binder 在线程池中并行处理多个请求服务方法只能拿到共享引用若服务需要可变状态应放入Mutex之类的同步原语中。第三步用service call直接调用接口方法deploy.md进一步演示了不写客户端代码、直接用service call从 shell 调用 Binder 方法的技巧adb shell service call birthdayservice 1 s16 Bob i32 24该命令的参数含义为参数含义birthdayservice服务注册名与service check一致1调用的接口方法索引AIDL 接口中方法从 1 开始编号1对应IBirthdayService中第一个方法wishHappyBirthday见 IBirthdayService.aidl 中方法声明顺序s16 Bob第一个参数UTF-16 字符串Bob对应String namei32 24第二个参数32 位整数24对应int years返回结果是原始 Parcel 十六进制转储Result: Parcel( 0x00000000: 00000000 00000036 00610048 00700070 ....6...H.a.p.p. 0x00000010: 00200079 00690042 00740072 00640068 y. .B.i.r.t.h.d. 0x00000020: 00790061 00420020 0062006f 0020002c a.y. .B.o.b.,. . 0x00000030: 006f0063 0067006e 00610072 00750074 c.o.n.g.r.a.t.u. 0x00000040: 0061006c 00690074 006e006f 00200073 l.a.t.i.o.n.s. . 0x00000050: 00690077 00680074 00740020 00650068 w.i.t.h. .t.h.e. 0x00000060: 00320020 00200034 00650079 00720061 .2.4. .y.e.a.r. 0x00000070: 00210073 00000000 s.!..... )这段转储的可读文本列右侧 ASCII 区把每个 16 位字解码后拼出了Happy Birthday Bob, congratulations with the 24 years!这正是lib.rs中wishHappyBirthday的实现逻辑fn wishHappyBirthday(self, name: str, years: i32) - binder::ResultString { Ok(format!(Happy Birthday {name}, congratulations with the {years} years!)) }同时也可以从转储中看到 Binder 字符串的编码特点文本以 UTF-16 存储注意00610048等每个字符占 2 字节00000036是长度为 0x3654 个字符的数据长度前缀。理解这条命令与输出就能在没有客户端的情况下快速验证接口的行为是排查服务端逻辑问题的利器。方法索引的确定方式方法索引1不是随意取的。对照 IBirthdayService.aidlinterface IBirthdayService { String wishHappyBirthday(String name, int years); // transaction code 1 String wishWithInfo(in BirthdayInfo info); // 2 String wishWithProvider(IBirthdayInfoProvider provider); // 3 String wishWithErasedProvider(IBinder provider); // 4 String wishFromFile(in ParcelFileDescriptor infoFile); // 5 }wishHappyBirthday位于首位故交易码为1。若要调用其他方法需要相应调整索引并注意其参数类型的编码例如wishWithInfo需要传入 parcelablewishFromFile需要传文件描述符。部署后的完整验证链路deploy.md之外build_all.sh还给出了与部署配套的客户端验证方式属于ANCHOR: birthday_client段可作为部署成功的最终确认m birthday_client adb push $ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/tmp adb shell /data/local/tmp/birthday_client Charlie 60客户端源码src/android/aidl/birthday_service/src/client.rs通过binder::get_interface::dyn IBirthdayService(SERVICE_IDENTIFIER)获取服务端接口然后调用wishHappyBirthday(name, years)打印结果。与service call相比客户端走的是类型安全的 Rust API而非手写交易码。部署与验证的完整时序可归纳为m birthday_server构建adb pushadb shell .../birthday_server启动服务前台/后台皆可adb shell service check birthdayservice轮询直到输出found选择验证方式快速验证adb shell service call birthdayservice 1 s16 Bob i32 24类型安全验证编译并运行birthday_client验证结束杀掉服务进程build_all.sh中为pkill -f birthday_server。常见问题与排查要点结合构建脚本与源码部署环节最容易踩的坑集中在以下几点m birthday_server找不到目标课程仓库未挂载进 AOSP checkout。按前置条件一节执行 bind mount并确认m hello_rust能正常工作service check长时间not found服务可能未启动成功或注册名拼写不一致。核对SERVICE_IDENTIFIER常量birthdayservice与命令中的名称是否一致也可检查服务进程是否因 panic 崩溃add_service失败会触发expect直接退出service call返回异常 Parcel交易码或参数类型写错。核对方法索引与 AIDL 声明顺序确认参数类型标记s16、i32与方法签名匹配动态链接错误若未设置prefer_rlib: true设备上可能缺少对应的动态库。这是 birthday_service/Android.bp 注释中明确提示的风险。小结deploy一课打通了 Rust Binder 服务从代码到设备上可调用服务的最后一公里通过m完成 Soong 构建用adb推送并启动birthday_server用service check确认服务注册用service call完成免客户端的接口级验证。整个过程背后是 AIDL 的 Rust 后端、BnBirthdayService组合包装、add_service注册与join_thread_pool线程池监听等机制在支撑——这些机制的具体实现均可在 src/android/aidl/birthday_service 目录与 src/android/build_all.sh 中找到对应源码。跑通本教程后你便掌握了在 AOSP 中部署任意 Rust Binder 服务的通用套路定义接口、实现服务、编译部署、shell 验证。【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

如何用 dart_roll_helper.py 把新的 Dart SDK 版本 roll 进 Flutter 引擎

如何用 dart_roll_helper.py 把新的 Dart SDK 版本 roll 进 Flutter 引擎

如何用 dart_roll_helper.py 把新的 Dart SDK 版本 roll 进 Flutter 引擎 【免费下载链接】flutter Flutter makes it easy and fast to build beautiful apps for mobile and beyond 项目地址: https://gitcode.com/GitHub_Trending/flutter41/flutter Flutter 仓库通过…

📅 2026/9/10 15:36:06
SQL基础语句精要:从查询到优化的实用指南

SQL基础语句精要:从查询到优化的实用指南

1. SQL基础语句概述SQL作为关系型数据库的标准查询语言,是每个开发者必须掌握的核心技能。我在实际工作中发现,80%的数据库操作都集中在20%的基础SQL语句上。本文将系统梳理这些高频使用的SQL基础语句,涵盖数据查询、操作、表管理等核心功能模…

📅 2026/9/10 15:36:06
Gogs 连接 MySQL 报 Error 1071 “key was too long“ 怎么处理

Gogs 连接 MySQL 报 Error 1071 “key was too long“ 怎么处理

Gogs 连接 MySQL 报 Error 1071 "key was too long" 怎么处理 【免费下载链接】gogs The painless way to host your own Git service 项目地址: https://gitcode.com/GitHub_Trending/go/gogs 用 MySQL 或 MariaDB 作为 Gogs 的后端数据库时,启动…

📅 2026/9/10 15:36:06
MORE NEWS

更多资讯

📰

AI Agent+DevEco CLI:从零自动生成、构建并安装鸿蒙应用全流程实测

最近我一直在折腾一件事:让AI Agent不停留在“生成代码片段”这个层面,而是真正自己把一个鸿蒙应用从零写出来、编译通过、装进设备。搞了一圈之后发现,完成这条链路的关键不是AI模型选哪个,而是DevEco CLI这套命令行工具链能不能…

📰

Solid Query 查询失效指南:invalidateQueries 的精确匹配、后台重取与底层实现

Solid Query 查询失效指南:invalidateQueries 的精确匹配、后台重取与底层实现 【免费下载链接】query 🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Q…

📰

燕千云:国产IT运维解决方案助力企业数字化转型

1. 燕千云:本土企业IT运维体系的破局者在数字化转型浪潮中,IT运维体系正面临前所未有的挑战。传统运维工具效率低下、响应迟缓,而国际主流平台如ServiceNow又存在本地化适配不足、数据安全合规风险等问题。燕千云作为国产IT运维解决方案的代表…

📰

方向难找不用愁:2026有AR增强现实导航定位系统推荐

2026年,随着公共场馆、工业园区及医疗机构数字化升级加速,AR增强现实导航定位系统成为解决室内寻路难题的关键工具。面对市场上繁杂的方案,如何精准选型?本文将以北京大希科技有限公司的全链条服务能力为例,从选型维度…

📰

opencode不是工具,而是源码级开发行为与环境治理方法论

1. “opencode”不是产品名,而是一类开发行为的统称——从热词混乱中厘清真实语义你搜“opencode”,页面弹出一堆 npm 报错、VS Code 插件失效、ARM 头文件找不到、PowerShell 执行被拒……但翻遍 GitHub、npm 官网、主流 AI 工具平台,根本找…

📰

会议录音不发云端:Buzz 三步离线转文字的完整走法

会议录音不发云端:Buzz 三步离线转文字的完整走法 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz Buzz 是一款离线…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬