张墨轩的技术宅

不忘初心,方得始终

WIFI-Display浅析

前段时间弄的车机手机互联产品,当把Android手机插入车机上的时候需要通过ADB推送一个后台程序到手机上,由这个后台程序负责获取屏幕镜像然后编码通过网络传送给车机端,再由车机端将手机屏幕显示出来,那么如果不推送任何后台程序给Android手机的情况下能否实现类似的功能呢?答案当然是可以的,比如现在市面上有一种叫做同屏器的产品就可以实现这种功能,它实际利用了Miracast技术。Miracast实际上是WiFi联盟(WiFi Alliance)对支持WiFi Display功能的设备的认证名称(该认证项目已经在2012年9月正式启动)。而通过Miracast认证的设备,便可提供简化发现和设置,实现设备间高速传输视频。而WiFi Display功能又是基于WiFi Direct(WIFI P2P)之上的,所以要搞明白Miracast最好先看看两文档:Wi-Fi_Display_Specification_v1.1和WiFi_P2P_Technical_Specification_v1.2。而对于安卓系统来说,自从Android4.2版本以后就开始支持,Android4.2的源码中就已经包含了这部分的代码。

AirPlay协议浅析

iPhone手机可以把屏幕镜像和音频等投射到AppleTV上,中间走的是AirPlay协议,这个是苹果的私有协议并没有对外公开,所以如果要实现类似AppleTV的功能的话基本只能通过逆向分析和抓包分析,之前为了实现将iPhone手机屏幕投射到车机屏幕上逆向了市面上一些同类产品,同时抓包研究分析,整个过程还是挺困难的。实际上AirPlay并不仅仅包含屏幕镜像和音频,同时还包括图片和视频推送等功能,而且自IOS4.2以来到现在整个协议也经历了多次升级和变化,网上虽然也可以找到一些资料,但是这些资料通常都比较古老,和最新的协议差别已经比较大了,参考价值有限。我这里因为手头机器有限,所以只针对于IOS9.3.2到IOS10.2.1之间的版本做了适配,这个范围以外的版本没做研究,而且只实现了屏幕镜像和音频的功能,视频推送部分没做研究,图片推送因为现在已经和屏幕镜像统一成一个流程,所以也是支持的。这里简单做个总结也算是对之前工作的一个记录。

Mirrorlink类型车机手机互联产品-2016总结

时间飞快,年又过完了,之前实在是太忙了,根本没时间写点东西,今天是大年初八,正好写点东西,回顾2016年,经过半年多努力,同时通过逆向工程的手段分析学习别人产品的长处,终于完成了自己的mirrorlink类型的车机手机互联产品的第一个版本,自己的努力总算是没有白费,在逆向别人产品的过程中,发现别人以状态机模型作为基础同时配合消息机制的合理利用共同构建出整个系统的基础架构的方法实在是让人受益匪浅,同时对android的surface系统,touch系统,音视频的编解码,软解,硬解等机制,IOS的airplay架构,开放的DLNA等都有了更深层次的了解,可以说是受益良多。这里展示一些产品的图片和视频,也算是对2016年工作的总结:

坑爹的NDK

今天又被NDK坑了一把,用NDK编译android-4.2.2_r1源代码中一个MediaCodec解码的示例程序,修改好程序后编译,报如下错误:

undefined reference to `android::AMessage::setString(char const*, char const*, int)'

collect2.exe: error: ld returned 1 exit status

顿觉奇怪,这个函数明明有啊,怎么会链接不上,打开源码翻看原型:

Mirrorlink项目注册功能简单描叙

注册相关的功能主要分为三大部分:


1. 车机端(一般无法上网)

2. 手机端(一般可以上网)

3. 外网注册后台


因为车机端一般无法上网,所以我们要利用手机端作为跳板帮助车机端进行注册,因为手机端会和车机端进行连接,所以手机端和车机端之间是可以通讯的,我们需要开发一个(注册助手APP)安装到手机上,此APP通过网络获取车机端的序列号等信息(当然更酷一点的方式是可以通过扫描二维码的方式,在车机屏幕生成一个二维码,然后利用手机去扫码),传送给外网的注册服务器上,然后从外网注册服务器获取注册结果,传回给车机端,然后车机端就知道是否注册成功了。

ffmpeg(neon优化)性能的一些总结

近段时间做的车联网项目一直在nexus5手机上做测试,对于手机屏幕投射到车机大屏幕这项技术而言,其实本质上可以看做是一个精简版的直播技术的实现,和当下热门的直播技术本质上是相似的,只是这里直播的是手机屏幕的内容而已。这块的流程简单来说就是在手机端通过android系统内部的接口获取手机屏幕一帧一帧的原始RGBA图像数据,然后通过sws_scale进行缩放并且转换为YUV420格式,然后利用ffmpeg-x264将其编码为h264包后再通过网络传送给车机端,车机端通过网络获取h264包后,利用ffmpeg-x264将其解码成YUV420后利用SDL显示出来。流程如下:

Win7-32位平台下用Cygwin+NDK编译android版FFmpeg+x264全过程

这里我将详细记录我在Win7-32位平台下用Cygwin+NDK编译出跑在android系统上的FFmpeg+x264全过程。FFmpeg默认情况下只支持h264的解码,并不支持h264的编码,为了让FFmpeg支持对h264的编码功能,需要编译的时候加入x264这个扩展库的支持。本文的目的就是最终编译出一个能在android下运行,同时支持h264编码和解码的的FFmpeg。

Mirrorlink类型车联网项目阶段性成果(二)

前段时间弄的是CE平台的车机。但是因为android发展迅猛,现在android车机已经相当普遍,所以最近一直在弄android系统的车机平台,这次主要的目标是实现android车机平台与iPhone手机之间的连接。对于苹果在车联网领域,已经有了它自己的方案CarPlay,但是正如苹果一贯的封闭,对我来说完全没有帮助。我只得采用airplay协议进行屏幕的投射。至于说反控,就是通过车机屏幕去控制iPhone手机的屏幕,这个因为iPhone手机严格的权限控制,是不可能实现的。不过人总是聪明的,这里有一种很取巧的办法,虽然我们没有权限控制整个iPhone手机,但是我们却可以实现应用内的控制,简单来说我们可以开发一个自己的苹果APP,然后可以通过车机端控制我们自己APP在运行时所展现出来的那个屏幕内容。这也不失是一种折中的好办法。 整的来说难度还是挺大的,而且对于airplay协议来说也是封闭的,没有太多公开的资料,很多时候需要自己抓包去分析,另外也不知道什么时候苹果一升级,协议又变了。

Mirrorlink类型车联网项目阶段性成果

最近做的一个类似mirrorlink的车联网项目取得阶段性的成果,车机和手机之间已经连通并且已经可以实现远程控制,目前实现的车机平台是CE系统,手机是android类手机。其实这样的项目从原理上来讲并不复杂,主要是包括2大功能:


第一:实现一个类似手机助手功能,可以简单把车机理解成一台PC主机,当有android手机通过USB插入到车机上的时候,车机发现手机,并且推送类似VNC的远控程序到手机端,并且通过ADB的端口转发功能在USB链路上实现socket连通,这样车机控制端程序就可以和手机上的被控端程序进行socket网络通讯了。难点主要是需要在CE平台上实现一个ADB驱动程序, 并且将ADB移植到CE平台上来。

ADB与普通APP权限简单对比

最近在做一个车联网的项目,其中一个基本需求是将一台android手机通过USB线缆接入到车机上后,手机屏幕远程映射到车机的屏幕上,我们可以通过操作车机的屏幕来远程控制手机。这个技术本质上就是通过类似VNC的方式在车机上远程控制手机。业内有名的车联网方案如apple的carplay还有google的androidauto本质上其实也都是远程映射,另外一个著名的规范MirrorLink就直接定义了利用VNC技术进行映射。
android平台上有很多VNC相关的程序和库,如开源的libvncserver,如有名的droidVncServer项目,它内部其实就是使用了libvncserver库。还有如Remoteroid等等。这些程序作为远程控制中的《被控端》运行到android上都必须要求root权限,原因也很简单就是需要权限。作为VNC技术中的《被控端》有两个基本工作要做:
第一就是读取本机的屏幕buffer传送给《控制端》,这样《控制端》就可以看到《被控端》的屏幕内容了。
第二就是《被控端》要接受来自《控制端》的操作请求,比如点击了屏幕上某个位置,进而控制android做出相应的反应。
这里获取屏幕buffer暂且不聊,主要说说输入控制相关的部分,android是基于linux的,所以输入控制的部分主要是操作/dev/input下面的设备文件。我们来看看android系统/dev/input下面的设备文件的权限。如图:
可见root用户有读写权限,input组下面的用户也有读写权限。而作为android下面的普通的APP是不具备这样的权限的。
下面我们来看看一个普通的APP的权限,如图:
可见这个普通的APP所属用户为u0_a57,所在组也不包括input组。所以对/dev/input下面的设备文件无权操作,那么输入控制功能将无法实现。所以必须要求root权限才行。
但是别家的车联网项目确实不要求android手机已经root,在没有root的android手机上也能实现类似VNC的远程操作。那么这又是为什么呢。答案就在adb上。adb在设备端所对应的的守护进程叫做adbd,在android启动过程中它会被init进程所加载,程序刚运行的时候是root权限,然后它会给自己降权,最终以shell用户权限运行。而shell属于input组,是可以读写/dev/input下面的设备文件的。如图:
所以当用户把android手机通过USB接入到车机上时(为了方便理解这里可以把车机就想象成一台PC电脑),车机通过adb命令通知android手机上的adbd运行起《被控端》程序,这个时候《被控端》运行在shell用户权限,可以正常读写/dev/input。
因为adb本身就是作为android调试桥的作用存在的。所以它实际上也是具备一定权限的,虽然没有root权限那么大,但是比一般普通的APP的权限还是要大一些。像/system/bin/下面提供的一些工具,比如getevent/sendevent,input,screencap,screenrecord等都只有用adb去调用才能正常工作,普通APP去调用是无法正常工作的,因为缺乏权限。 而像screenshot这样的工具通过adb去调用也无法正常工作,因为这个工具内部是直接操作/dev/graphics/fb0设备的,而这个设备连shell权限也无权操作。如图:
 
只有system用户和graphics组才有权操作。那为什么adb调用screencap又可以呢,通过读取源代码可以知道,它的源代码在frameworks/base/cmds/screencap/ ,它内部实际上是调用SurfaceFlinger提供的接口ScreenshotClient,本质上是通过binder机制与SurfaceFlinger进程间通讯罢了。android自带的调试工具DDMS有一个截图功能,其实也是通过adbd调用screencap完成截图的。


«12»

Powered By

Copyright phonegap.me Rights Reserved.