【tomcat源码调试】【小游戏源码资源】【linux内核源码社区】androidcmd源码

1.android.bp
2.ADBLib 在 android 中的源码使用
3.AndroidFramework 之启动 ServiceManager

androidcmd源码

android.bp

       å¼•ç”¨åŽŸæ–‡

        早期的Android系统都是采用Android.mk的配置来编译源码,从Android 7.0开始引入Android.bp。

        Android 7.0引入ninja和kati

        Android 8.0使用Android.bp来替换Android.mk,引入Soong

        Android 9.0强制使用Android.bp

        1.1 模块

        定义一个模块从模块的类型开始,模块有不同的类型,如前面例子中的cc_library_shared,当然类型还有很多种,譬如cc_binary android_app cc_library_static等等。模块包含一些属性格式为“property-name:property-value”,其中name属性必须指定,其属性值必须是全局唯一的。

        srcs 属性以字符串列表的形式指定用于编译模块的源文件。您可以使用模块引用语法 “:” 来引用生成源文件的其他模块的输出,如 genrule 或 filegroup。

        1.2 变量

        变量范围限定为声明它们的文件的其余部分,可以使用 “=” 号赋值, 但是不能使用 “:=” 赋值。变量是不可变的,但有一个例外它们可以附上+= 赋值,但仅在变量被引用之前。

        1.3 注释

        Android.bp使用单行注释//和多行注释/* */两种方式。

        1.4类型

        具体支持以下几种类型:

        1.5 操作符

        String类型、字符串列表类型和Map类型支持操作符“+”。

        1.6 支持模块类型

        Android.bp可以支持android_app、cc_binary、cc_binary_host等多种类型,具体定义在Android源码的build/soong/androidmk/cmd/androidmk/android.go

        1.7 支持预编译类型

        1.8 条件式编译

ADBLib 在 android 中的使用

       ADBLib在Android中的使用

       在Android中,我们利用代码执行adb命令,源码如:

       Runtime runtime = Runtime.getRuntime();

       Process proc = runtime.exec(cmd);

       但部分adb命令因权限不足被拒绝。源码特别是源码tomcat源码调试自Android P版本后,权限控制更为严格,源码比如获取CPU信息时,源码小游戏源码资源因权限问题被拒绝执行。源码此时,源码需要使用更高权限执行adb命令,源码ADBLib则成为解决这一问题的源码利器。

       尽管网上关于ADBLib资料较少,源码但其源码简单,源码可访问开源地址: /cgutman/AdbLib。源码linux内核源码社区在Google Play上亦有应用提供ADBLib的源码apk源码。

       使用步骤如下:

       将tcpip端口设置为

       生成加密密钥

       获取手机IP

       使用socket连接手机IP+

       编写并执行cmd命令,源码读取返回值

       具体操作包括:

       手机USB连接电脑,微擎医疗源码执行命令adb tcpip

       生成密钥代码,使用adbcli库中的Adbcrypto类

       获取手机IP地址

       使用socket连接并执行cmd命令

       为确保操作成功,需要添加权限。广州防伪溯源码

       首先,设置tcpip端口;然后生成密钥;获取手机IP;通过socket连接手机IP+端口,并执行命令。

       通过ADBLib,我们能实现与手机的稳定连接,执行adb命令,获取设备信息,提升开发效率。

AndroidFramework 之启动 ServiceManager

        本文源码基于 Android ,涉及相关源码如下。

        ServiceManagaer 是 Binder 的守护进程,在 Binder 机制中起着重要的作用。本文将从源码的角度对其进行分析,整体流程如下:

        时序图如下。

        先来看看 ServiceManager 是如何启动的:

        在 Zygote 一文中说过, init 进程启动的第二阶段会解析 init.rc 文件。

        在这之后会触发 trigger init 。

        结合 init.rc 看看 action init 做了什么。

        当触发 trigger init 后,会启动 servicemanager 服务,其声明如下。

        对应的执行文件为 /system/bin/servicemanager ,在编译前位于 frameworks/native/cmds/servicemanager 下,来看看 Android.bp 。

        其对应的源码为 service_manager.c 和 binder.c ,入口函数 main() 位于 servicemanager.c 。

        启动完 ServiceManager 后会打开 Binder 驱动。

        在 main() 中首先调用 binder_open() 。

        binder_open() 主要做了如下事情:

        给结构体 binder_state 分配内存。

        系统调用 open() 打开 /dev/binder ,如果打开驱动失败,则执行 fail_open 释放内存。

        简单的解释一下什么是系统调用?

        由于需要限制不同的程序之间的访问能力,防止程序获取别的程序的内存数据, CPU 划分出两个权限等级,用户态和 内核态。

        所有的用户程序都是运行在用户态,但有时需要做一些内核态的事情,而唯一可以做这些事情的就是操作系统,所以程序需要向操作系统发起请求,以程序的名字来执行这些操作。这时就需要一个从用户态切换到内核态但不能控制内核态中执行的机制,这种机制就是 系统调用。

        系统调用 ioctl() 传入 BINDER_VERSION 命令获取 Binder 驱动版本,对比版本是否一致,不一致则执行 fail_open 释放内存。

        系统调用 mmap() 映射 kb 的内存空间,即把 Binder 驱动文件的 kb 映射到内存空间供 ServiceManager 使用,内存映射失败则执行 fail_map ,关闭 fd 并释放内存。

        ServiceManager 进程 mmap 的内存大小可以通过 adb shell 命令查看。

        可以看到内存映射地址为 0xff ~ 0xf ,差为 0x 即十进制的 kb 。

        打开 Binder 驱动后会将 ServiceManager 设置为上下文管理者。

        调用 binder_become_context_manager() 。

        android 新增 BINDER_SET_CONTEXT_MGR_EXT 命令来设置安全的上下文管理者,如果设置失败,则使用原有的 BINDER_SET_CONTEXT_MGR 命令来设置上下文管理者,两者区别在于是否携带参数。

        最后会进入循环,从 Binder 驱动读取和解析数据。

        调用 binder_loop() 进入循环,不断地通过系统调用 ioctl() 从 Binder 驱动读取数据,并通过 binder_parse() 进行数据解析。

        注意这里调用 binder_loop() 传入的 svcmgr_handler() ,后面会使用到。

        binder_write() 会封装 struct binder_write_read ,并通过系统调用 ioctl() 将对应的命令传递给 Binder 驱动。

        binder_parse() 用来解析从 Binder 驱动读取到的数据,然后根据不同的命令执行对应的操作。

        因为 cmd 命令可能有多个,所以通过 while 循环每次处理一个 cmd 命令,多 cmd 的结构大致如下图所示。

        这里重点看下 BR_TRANSACTION 命令。

        BR_TRANSACTION 是 Binder 驱动向 Server 端发送请求数据。

        binder_transaction_data 的结构如下,其表明了 transcation 传输的具体语义,语义码记录在 code 中,不同语义码携带的数据是不同的,这些数据由 data 指定。

        在解析完 binder_transaction_data 的具体语义后,会调用前面传给 binder_loop() 的 svcmgr_handler() ,其实就是 switch case 语义码做不同的事情。

        ServiceManager 的功能其实很简单:

        至此 ServiceManager 就分析完了。

更多内容请点击【综合】专栏

精彩资讯