基于 MsgSender和 Binder 并发可信解耦透传框架设计篇

基于 MsgSender和 Binder 同步并发可信解耦透传框架设计篇

MsgSender是基于蓝牙Socket封装的一套API,但是手表链路有时候不稳定会造成丢包,需要上层业务自己去保证,这样上层业务需要做很多不必要操作,而且MsgSender 是异步回调接口,对于习惯Android Binder 同步RPC 颇为不习惯,而且MsgSender 有强烈的耦合关系,这里曾经在做公交卡中深有体会,为了扩展一个接口就要改四个APK,对于DMA 这种还需要系统签名,DM的微信和QQ支付需要使用正式签名!由于第三方提供的APK有严格的签名验证,所以在手表端就不能使用DMA 直接bind 第三方apk获取服务! share uid 问题 确定不了包名,所以就存在代理端,调试颇为不方便,耦合性太高.简直是痛不欲生!为了达到iOS和安卓的通用性,用JCE来打包数据,对于习惯了AIDL的我颇为不习惯.针对MsgSender问题,本文基于MsgSender封装一套API 供业务使用.像安卓使用别的进程的Service一样,也是基于AIDL的,针对iOS和安卓都需要的业务,可以在参数中直接传byte数组这样也可以达到公用的效果,不过这样牺牲了AIDL的部分数据打包和解包功能.尤其是注册远程CallBack的功能.

- 同步: 是这套API是同步接口,想android中使用Service一样,如果Service里面有耗时操作,客户端线程休眠等待.所以要关注ANR情况.
- 并发: 这套接口是支持多客户端多线程并发访问,基于Binder多线程的特性,理论上支持16线程并发访问.由于蓝牙是小水管!消息排队出去,这里只是提供了多客户端调用的能力!
- 可信: 这是一套超时机制接口,基于蓝牙不稳定的情况,上层业务其实是不care蓝牙的状态,也有可能中途蓝牙偶然断开丢包的情况,该接口如果调用成功返回没有异常,则本次通讯一定可靠,如果蓝牙一直断开根据实际情况,可以返回超时异常或者蓝牙断开异常,客户端在异常处理分支catch 异常就ok
- 安全: 由于是基于binder 可以根据uid pid 校验访问者权限或者签名而达到安全的作用.
- 解耦: 业务不需要在耦合在DMA或者DM,也就是以后不用改DM或者DMA来增加业务,DM和DMA的只是起到搬运的作用

[TOC]

这里我总共实现了三套通用RPC框架,前两套原理基本类似,但是觉得可能引起DM和DMA的 binder线程池过度忙碌,造成DM的所有binder调用的阻塞等待,所以实现第三套方案,占用客户端工作线程的异步回调机制.

  • 基于AIDL进行数据的序列化和反序列化,基于命令字分发业务,基于Biner实现的跨进程分发RPC框架(由于基于AIDL进行打包解包,对iOS可能不太友好)
  • 基于JCE进行数据的序列化和反序列化,基于命令字分发业务,基于Biner实现的跨进程分发RPC框架(基于JCE所以iOS也能使用,但是和上一种方案,可能存在部分缺陷,)
  • 基于JCE进行数据的序列化和反序列化,基于命令字分发业务,基于Biner实现的跨进程分发RPC框架(这种主要依靠CallBack进行分发,只会占用一个binder线程,而且还能很快的返回回收)

一二两种方案和第三种最大的区别是,一二种方案挂起代理服务端的binder线程池,造成代理端binder线程全部忙碌,第三种设计请求和回调的时候只会占用一个binder线程,而且很快的返回,而且是基于异步回调机制,对接iOS现有命令字分发框架更好对接,第三种方案是借鉴映理和jiulingli思路进行实现扩展.

Binder 设计篇分析

Android Binder

Binder 是安卓进程间通讯(IPC)方式之一,同时也是一种RPC调用方式之一, 其实Linxu 实现有socket,信号量等进程间通讯方式
Binder和传统的进程间通讯,有无可以比拟的优势.Binder提供以下几个功能

  • 进程间通讯
  • 共享内存(主要靠传递文件描述符实现)
  • 多线程支持(线程池)
  • 进程间同步异步调用
  • 对象引用计数,死亡通知
  • 用户校验(pid uid)

其中最常用的就是Binder同步调用,跟人感觉就是像 在一个进程里面调用感觉一样,其实最主要的实现思想就是利用Binder驱动实现两个线程的同步协作(只不过这两个线程在不同的进程),调用方请求服务端时候通过系统调用进入内核态,然后挂起当前线程,然后唤醒目标进程,目标进程读取通讯数据,然后调用相关接口,之后再通过系统调用进入内核态,然后挂起当前线程,唤醒调用进程,这是最常用功能,当然也有异步调用,也就是onway的调用,客户端不care 服务端返回的结果.

[TOC]

Android Binder设计篇

Binder是典型的C/S架构 ,服务端等待客服端调用,如果服务端没有客服端调用,服务端进程通过系统调用进入内核态,之后让出CPU使用权,进入休眠状态,此时调度器不会调度当前线程.客户端调用的时候就会挂起客户端线程,唤醒目标线程,这里就涉及一个问题就是,如何找到目标线程,以及目标线程处理之后怎么找到调用者线程的问题,这方面就要借助Binder 驱动了,和ServiceManger,其中对于系统级别的服务,都注册到ServiceManger中,其中注册到ServiceManger又是一个IPC过成,Linux内核空间是共享的,用户进程空间是独立的,对于4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间,IPC实现主要借助内核空间,只不过这个内核空间和用户空间被映射到同一个物理页上,驱动找到目标进程的时候,会在目标进程分配传输数据的空间,直接把客户端数据copy到内核地址空间,只不过这个内核地址空间,在目标进程中也可以访问,目标进程用户空间分配接收数据的空间,和内核空间的起始地址错一个固定的偏移量,通过偏移量就可以算出数据在用户空间的地址.这些数据就是就是序列化的的数据(Parcel),这样就实现客户端的数据通过一次Copy就到了目标进程,不用通过先copy的内核空间,之后再从内核空间copy到目标进程空间,这也是一次copy的根源,当然在IPC过程中也有少量通讯协议数据由客户端copy到内核态,再通过内核态copy到用户空间,但是这些数据相对于通讯的数据是小之又少的.

1 总架构

这里需要介绍binder架构的中几个相关名词.(这里直接拿着相关数据结构来说明更加直接)

  • binder_node和BBbinder
  • binder_ref BPBinder
  • ServiceManger
  • BinderProc
  • Binder线程池
  • binder_buffer( 接受数据内存映射)
  • ProcessState(进程相关数据结构)
  • IPCThreadState

Libaroma_GUI

摘要:
Libaroma是一个用纯C写的控件库,支持Linux、X86、QNX等不同平台。针对不同平台API做了一层封装,可以很快的移植到不同平台,参照Android的材料设计风格实现控件库,已经写好了Fragment、ViewPager、Button、ProgressBar、ListView、Dialog等控件,开发者可以实现自己的控件。目前Libaroma框架只绝对布局,控件的开发基本和Android类似,也有Window,WindowManagr、EventHub等概念,支持Window转场动画。

[TOC]

深蓝合作开发规划

深蓝合作开发规划


背景
技术背景
  1. 反射架构的完成。一键适配成功率达到百分之九十五以上,颠覆传统的patchrom方案,适配效率提高.由于反射架构的是以后的更新和维护可以达到批量更新的水平,而无法投入太多的人力更新维护.
  2. 无线刷机方案的日益完善,用户刷机难度降低,利于推广,而且无线刷机后台编译服务器可以提供给民间开发者使用,可以帮助开发者后台更新与升级.
  3. 双卡sdk的完善,给开发者提供了更广的选择.兼容高通4.4方案,和高通5.1方案.

各种刷写Recovery的方法

首先写这篇文章的情景,今天武汉测试反馈说大神F2无法刷写recovery和无法无法进入recovery.让我帮忙解决下,doraning建议我写篇文章,我就只好献丑了.看武汉测试是用fastboot命令在fastboot模式刷写recovery,这个肯定是错误的,大神F2是非常特别的机型不仅在recovery刷写方面还有root权限方面.下面介绍这个两个特别之处,再写几种方法刷写recovery.

刷写recovery问题


在适配大神F2初期并没有适配我们自己的recovery,所以找一个第三方用着,有一次偷懒用刷机精灵刷,当时进入的是刷机精灵的recovery,但是刷机成功,我重启到recovery发现,还是我自己当时用的recovery,而且ROM并没有内置recovery,当时觉得很奇怪,后来问了刷机精灵官方人员才知道他们用了什么方法,在下面的刷写recovery教程中再介绍

用新架构适配MI3中遇到的各种坑

用新架构适配MI3中遇到的各种坑

首先不得不说hendy架构的强大之处, mi3也直接开机但是遇到各种坑,不能怪架构不够强大,只有说miui定制化太高.
下面详细说一下mi3适配中的各种坑.有些坑会附带点log信息.

PhonewindowManger 通过intent启动 qshutdown.apk

首先贴出异常log
PhonewindowManager

TPS 解决冲突

TPS 解决冲突

首先感谢hendy为我们带来这么强悍的框架,减少机型适配中百分之八十的重复劳动,之前开机都是一个大关,但是用TPS和新的架构开机不再是一件难事,减少我们之前的解决reject阶段,直接进入fix bug 阶段. 也许大家习惯之前的patchrom方案. 之所以叫patchrom 在我个人理解来看来是因为patchrom工具核心使用diff 和patch 命令来进行代码的插入.当然patch不可能百分百正确,才需要人力去解决冲突修复bug.小米patch我也做过,真是深恶痛绝好多重复劳动,做起来让人抓狂,让我最新欢的coron项目的patchrom ,它核心是围绕diff3命令进行的,用makefile进行流程控制,用起来真是爱不释手,工具好用只是前提,更重要的是百度云rom开发人员对代码进行重构,使reject减少,即便是冲突不用对比也能直接插入的.


Smali 语法

QROM逆向工程之 - Smali文档结构介绍

在逆向工程适配过程中,直接打交道的就是smali文件,所以明确smali文档结构,对以后的适配过程有很大的帮助。在适配的过程可以根据smali文件的格式反应对应的java源文件,其实samli文件在读起来和java其实差不多,只是java源文件很容易看清代码执行的逻辑,而smali只能进行局部的判断。在机型适配的过程中根据可以相关指令判获取类的继承信息,实现的接口信息,字段的权限和类型,方法的权限参数类型和返回值。

Smali格式结构

文件结构

无论是普通类、抽象类、接口类或者内部类,反编译出来的代码中,都是以单独的Smali文件存放的,每个文件的的前三行描述改类的信息,包括权限信息、继承信息和源文件信息。#号之后为注释内容格式,格式如下。


1
2
3
.class public Lcom/android/server/SystemServer; #.class <访问权限> [修饰关键字] <类名>
.super Ljava/lang/Object; #<父类名>
.source "SystemServer.java" #<源文件名>