01 September 2015

小米09月工作记录


2015.09.01

ServiceManager

  1. 它是整个Binder机制的守护进程,涉及到Binder进程间通信。

  2. 它在init进程启动之后启动。

  3. 管理系统中service,包括 add_service、check_service、get_service(获取服务)。

Binder进程间通信_

  1. 不同于一般的进程间通信方式(共享内存,信号,信号量,socket,管道等)

  2. 其实就是提供RPC功能(Remote Process Call)

  3. Binder机制主要由4部分系统组件组成,Client、Server、Service Manager(这三运行在用户空间)、Binder驱动程序(运行在内核空间)。其中Service Manager和Binder驱动程序已经在Android中实现好了,用户只要按照规范实现自己的Client和Server组件就可以通信了。

  4. Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信。

Binder机制4部分组件关系图

BnMediaPlayerService是一个Binder本地对象,它在内核中有一个对应的Binder实体对象,当另外一个进程要使用MediaPlayerService的时候,Binder驱动程序就会在内核创建一个Binder引用对象,同时在那个进程创建一个Binder代理对象,即一个BpMediaPlayerService对象。这四个对象是有一一对应关系的,因此,当一个进程调用BpMediaPlayerService对象的transact函数时,通过Binder驱动程序就可以找到对应的BnMediaPlayerService对象,并且调用它的OnTransact函数。

接下去的while循环是通过sm->getService接口来不断尝试获得名称为“media.player”的Service,即MediaPlayerService。为什么要通过这无穷循环来得MediaPlayerService呢?因为这时候MediaPlayerService可能还没有启动起来,所以这里如果发现取回来的binder接口为NULL,就睡眠0.5秒,然后再尝试获取,这是获取Service接口的标准做法。 (MiLinkService也是这么干的)


2015.09.06

android事件分发机制

  1. 只要你触摸了任何控件,肯定是先调用该控件的view.dispatchTouchEvent方法。

     //{java}
     public boolean dispatchTouchEvent(MotionEvent event) {  
         if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
                 mOnTouchListener.onTouch(this, event)) {  
             return true;  
         }  
         return onTouchEvent(event);  
     } 
    
  2. 由上源码可以看出 onTouchonTouchEvent 的关系, mOnTouchListener是注册的回调。

  3. 执行的log。case:都不拦截和消费。

     //{bash}
     09-06 14:01:23.639 V/TouchEventActivity( 1750): dispatchTouchEvent begin action:0
         09-06 14:01:23.639 V/TouchEventViewGroup( 1750): dispatchTouchEvent begin
         09-06 14:01:23.639 V/TouchEventViewGroup( 1750): onInterceptTouchEvent begin
         09-06 14:01:23.639 V/TouchEventViewGroup( 1750): onInterceptTouchEvent result = false
             09-06 14:01:23.639 V/TouchEventView( 1750): dispatchTouchEvent begin
             09-06 14:01:23.639 V/TouchEventView( 1750): onTouchEvent begin
             09-06 14:01:23.639 V/TouchEventView( 1750): onTouchEvent result = false
             09-06 14:01:23.639 V/TouchEventView( 1750): dispatchTouchEvent result = false
         09-06 14:01:23.639 V/TouchEventViewGroup( 1750): onTouchEvent begin
         09-06 14:01:23.639 V/TouchEventViewGroup( 1750): onTouchEvent result = false
         09-06 14:01:23.639 V/TouchEventViewGroup( 1750): dispatchTouchEvent result = false
     09-06 14:01:23.639 V/TouchEventActivity( 1750): onTouchEvent begin
     09-06 14:01:23.649 V/TouchEventActivity( 1750): onTouchEvent result = false
     09-06 14:01:23.649 V/TouchEventActivity( 1750): dispatchTouchEvent result = false
    
     // 这里为什么move事件不往下传了呢。因为down事件没有被消费,如果down事件在viewgroup层被消费,则move事件就只会传到viewgroup层。
     09-06 14:01:23.659 V/TouchEventActivity( 1750): dispatchTouchEvent begin action:2
     09-06 14:01:23.659 V/TouchEventActivity( 1750): onTouchEvent begin
     09-06 14:01:23.659 V/TouchEventActivity( 1750): onTouchEvent result = false
     09-06 14:01:23.659 V/TouchEventActivity( 1750): dispatchTouchEvent result = false
     09-06 14:01:23.689 V/TouchEventActivity( 1750): dispatchTouchEvent begin action:2
     09-06 14:01:23.689 V/TouchEventActivity( 1750): onTouchEvent begin
     09-06 14:01:23.689 V/TouchEventActivity( 1750): onTouchEvent result = false
     09-06 14:01:23.689 V/TouchEventActivity( 1750): dispatchTouchEvent result = false
    

    就是touch事件的层级传递。我们都知道如果给一个控件注册了touch事件,每次点击它的时候都会触发一系列的ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件。这里需要注意,如果你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action

    说到这里,很多的朋友肯定要有巨大的疑问了。这不是在自相矛盾吗?前面的例子中,明明在onTouch事件里面返回了false,ACTION_DOWN和ACTION_UP不是都得到执行了吗?其实你只是被假象所迷惑了,让我们仔细分析一下,在前面的例子当中,我们到底返回的是什么。
    参考着我们前面分析的源码,首先在onTouch事件里返回了false,就一定会进入到onTouchEvent方法中,然后我们来看一下onTouchEvent方法的细节。由于我们点击了按钮(Clickable),就会进入到第14行这个if判断的内部,然后你会发现,不管当前的action是什么,最终都一定会走到第89行,返回一个true。
    是不是有一种被欺骗的感觉?明明在onTouch事件里返回了false,系统还是在onTouchEvent方法中帮你返回了true。就因为这个原因,才使得前面的例子中ACTION_UP可以得到执行。

  4. Activity接受所有事件。

android_Touch事件分发机制

adb shell monkey -p com.zifei.on -v 500 自动化测试,一阵狂跑。


2015.09.07

Process.kill(myPid)适合杀死属于自己包名的进程。

Binder机制中Client如何获得Server远程接口 好文章要多看。

BpMediaPlayerService类图

我们要获得MediaPlayerService的远程接口,实际上就是要获得一个称为BpMediaPlayerService对象的IMediaPlayerService接口。

::getMediaPlayerService过程分析

  1. 通过defaultServiceManager函数来获得Service Manager的远程接口,实际上就是获得BpServiceManager的IServiceManager接口

2015.09.08

发版前客户端调用milink差点改出一个大bug,幸好是虚惊一场。

Miui 7 getNetworkInfo 有可能不正确,明明联网,state确是 DISCONNECTED/BLOCKED 。解决办法,使用别的参数来确定网络是否可用,如 isAvailable,可能跟神隐模式有关。

吹了几个专利 idea 。


2015.09.14

对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。

监听屏幕点亮


2015.09.16

RSA的公钥非常长,但能加密的数据又比较少,可以分段加密。

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes

所以上行包不带这玩意。


2015.09.17

codota

比如你想用使用某个函数,但不知道这个函数该在怎样的上下文种使用,可以用codota搜这个函数的用法。


2015.09.18

今天彻底换了chrome,有点舍不得firefox。


2015.09.21

Android 内存优化之OOM

ProGuard能够通过移除不需要的代码,重命名类,域与方法等等对代码进行压缩,优化与混淆。使用ProGuard可以使得你的代码更加紧凑,这样能够减少mapping代码所需要的内存空间


2015.09.21

接入MiPush唤醒app。 Done;



blog comments powered by Disqus