Android Binder 全解析(3) -- AIDL原理剖析

摘要 本文是 Android 系统学习系列文章中的第二章节,在前面一些细节概念的铺垫下,大体上知道 Binder Framework 是怎么运作的,在这边文章中,将详细说明下 Binder Framework 的具体实现,这一套机制如何盘活整个 Android 系统。对此系列感兴趣的同学,可以收藏这个链接 Android 系统学习,也可以点击 RSS订阅 进行订阅。

IBinder 与 Binder

一个在同进程的对象的抽象是 Object,但这个对象是不能被跨进程使用的,要想跨进程使用,在 Android 中就必须依附于 Binder Framework。基于抽象设计的原理,Android系统将一个可远程操作的应用定义为 IBinder,在这个接口中定义了一个可远程调用对象应该具有的属性和方法,在代码中实际使用的Binder 也都是继承自 IBinder 对象。我们接下来分析 IBinder 中定义了那些接口,是怎么抽象出可远程调用相关的方法的。

public interface IBinder {
    ... ...

    // 查看 binder 对应的进程是否存活
    public boolean pingBinder();
    // 查看 binder 是否存活,需要注意的是,可能在返回的过程中,binder 不可用
    public  boolean isBinderAlive();

    /**
     * 执行一个对象的方法,
     *
     * @param 需要执行的命令
     * @param 传输的命令数据,这里一定不能为空
     * @param 目标 Binder 返回的结果,可能为空
     * @param 操作方式,0 等待 RPC 返回结果,1 单向的命令,最常见的就是 Intent.
     */
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;

    // 注册对Binder死亡通知的观察者,在其死亡后,会收到相应的通知
    // 这里先跳过,后续
    public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException;

    ... ...

}

如注释中所述,最重要的方法是 transact 方法,要理解这个方法是干嘛的,得看 ipcthreadstate.cpp 源代码里的说明。

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    status_t err = data.errorCheck();
    flags |= TF_ACCEPT_FDS;

    ... ...

    if (err == NO_ERROR) {
        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    }

    if (err != NO_ERROR) {
        if (reply) reply->setError(err);
        return (mLastError = err);
    }

    if ((flags & TF_ONE_WAY) == 0) {
        ... ...
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        ... ...
    } else {
        err = waitForResponse(NULL, NULL);
    }

    return err;
}

这是截取过后的源码,刨除了一些支线逻辑,从这个代码里面可以看到的主要逻辑就是:根据Uid 和 Pid (用户id和进程id)进行相应的校验,校验通过后,将相应的数据写入 writeTransactionData ,其后在 waitForResponse 里面读取前面写入的值,并执行相应的方法,最后返回结果。

总结地来说,就是 IBinder 抽象了远程调用的接口,任何一个可远程调用的对象都应该实现这个接口。由于 IBinder 对象是一个高度抽象的结构,直接使用这个接口对于应用层的开发者而言学习成本太高,需要涉及到不少本地实现,因而 Android 实现了 Binder 作为 IBinder 的抽象类,提供了一些默认的本地实现,当开发者需要自定义实现的时候,只需要重写 Binder 中的protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) 方法即可。


自动售货机的故事

先偏一个题,夏天一到,天气也变得炎热,地铁旁边的自动售货机开始有更多的人关顾了。那么售货机是怎么工作的了?通过对这个分析,可以对Binder Proxy/Stub 模式更好地理解。

和我们打交道得是售货机,而不是背后的零售商,道理很简单,零售商的位置是固定的,也就意味着有很大的交通成本,而和售货机打交道就轻松很多,毕竟售货机就在身边。因而从客户端的角度上看,只需要知道售货机即可。

再从零售商的角度来看,要和为数众多的售货机打交道也是不容易的事情,需要大量的维护和更新成本,如果将起交由另一个中介公司,就能够省心不少。零售商只关心这个中介公司,按时发货,检查营收,这就是所有它应该完成的工作。

binder proxy / stub 结构

如上图所示,在 Binder Framework 中也采用了类似的结构,Proxy 就相当于前面提及的售货机,Stub 相当于这里的中介公司,在这样的设计下,客户端只需要和 Proxy 打交道,服务端只需要和 Stub 打交道,调理清晰很多。这种模式又被称为 Proxy / Stub 模式,这种模式也值得我们在日后的开发中借鉴。另外需要注意的是,为了开发的需要,通常 Proxy 和 Stub 实现了相同的接口。

在这里 Stub 是具体的远程方法实现,也被称为存根,Proxy 继承了相应的接口,但只是在这里面调用远程方法,并返回相应的结果。

AIDL 是什么?它是如何运作的?

虽然上述的模式帮助我们将远程方法调用与服务具体实现解耦开来,但是这里面还是又不少代码需要实现,而且远程方法调用这一块应该是重复代码,那么有什么方法来帮我们简化这个步骤吗?

Android 的设计者在一开始也意识到这个问题,推出了 AIDL,如下图所示

AIDL

现在我们来分析下,Android Framework 是如何把 AIDL 运行起来的,首先来看看一个大数相乘的例子,想把这个耗时的操作,放到另一个进程上来调用,于是定义了下面的 IMultiply.aidl 文件。

// IMultiply.aidl
package com.wandoujia.baymax.aidl;

interface IMultiply {
    long multiply(long left, long right);
}

在 Android Studio 中点击 Clean / Rebuild Project 之后,可以在 build / genreated / Source 的目录里面找到 IMultiply.java 文件,具体的代码如下:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /Users/QisenTang/Program/Wandoulabs/baymax/packages/baymax/src/main/aidl/com/wandoujia/baymax/aidl/IMultiply.aidl
 */
package com.wandoujia.baymax.aidl;
// Declare any non-default types here with import statements

public interface IMultiply extends android.os.IInterface {
  /**
   * Local-side IPC implementation stub class.
   */
  public static abstract class Stub extends android.os.Binder implements com.wandoujia.baymax.aidl.IMultiply {
    private static final java.lang.String DESCRIPTOR = "com.wandoujia.baymax.aidl.IMultiply";

    /**
     * Construct the stub at attach it to the interface.
     */
    public Stub() {
      this.attachInterface(this, DESCRIPTOR);
    }

    /**
     * Cast an IBinder object into an com.wandoujia.baymax.aidl.IMultiply interface,
     * generating a proxy if needed.
     */
    public static com.wandoujia.baymax.aidl.IMultiply asInterface(android.os.IBinder obj) {
      if ((obj == null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin != null) && (iin instanceof com.wandoujia.baymax.aidl.IMultiply))) {
        return ((com.wandoujia.baymax.aidl.IMultiply) iin);
      }
      return new com.wandoujia.baymax.aidl.IMultiply.Stub.Proxy(obj);
    }

    @Override
    public android.os.IBinder asBinder() {
      return this;
    }

    @Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
      switch (code) {
        case INTERFACE_TRANSACTION: {
          reply.writeString(DESCRIPTOR);
          return true;
        }
        case TRANSACTION_multiply: {
          data.enforceInterface(DESCRIPTOR);
          long _arg0;
          _arg0 = data.readLong();
          long _arg1;
          _arg1 = data.readLong();
          long _result = this.multiply(_arg0, _arg1);
          reply.writeNoException();
          reply.writeLong(_result);
          return true;
        }
      }
      return super.onTransact(code, data, reply, flags);
    }

    private static class Proxy implements com.wandoujia.baymax.aidl.IMultiply {
      private android.os.IBinder mRemote;

      Proxy(android.os.IBinder remote) {
        mRemote = remote;
      }

      @Override
      public android.os.IBinder asBinder() {
        return mRemote;
      }

      public java.lang.String getInterfaceDescriptor() {
        return DESCRIPTOR;
      }

      @Override
      public long multiply(long left, long right) throws android.os.RemoteException {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        long _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeLong(left);
          _data.writeLong(right);
          mRemote.transact(Stub.TRANSACTION_multiply, _data, _reply, 0);
          _reply.readException();
          _result = _reply.readLong();
        } finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
    }
    static final int TRANSACTION_multiply = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  }

  public long multiply(long left, long right) throws android.os.RemoteException;
}

这段自动的生成的代码,可读性上不是很好,但不影响我们进行分析。这段自动生成的代码中,最重要的是三个部分,ProxyStubasInterface

首先看看Proxy的实现,首先是将远程的Binder作为参数传入进来,再来看看 multiply 这个方法里面的下面几个步骤。首先是将left 和 right的参数写入到_data中去,同时在 远程binder 调用结束后,得到返回的 _reply ,在没有异常的情况下,返回_reply.readLong()的结果。根据 Android Binder 完全解析(一)概述 提到的内容,这里可以粗略地将 Binder 看做远程服务抛出的句柄,通过这个句柄就可以执行相应的方法了。这里需要额外说明的是,写入和传输的数据,都是 Parcelable,Android Framework 中提供的

_data.writeInterfaceToken(DESCRIPTOR);
_data.writeLong(left);
_data.writeLong(right);
mRemote.transact(Stub.TRANSACTION_multiply, _data, _reply, 0);
_reply.readException();
_result = _reply.readLong();

再来看看Stub里面的实现,Stub本身继承了Binder抽象类,本身将作为一个句柄,实现在服务端,但传递给客户端使用。同样也看看 onTransact里面的方法,首先是通过 long _arg0; _arg0 = data.readLong(); 读取 left 和 right 参数,在this.multiply(_arg0, _arg1)计算过后,将结果写入到reply中。

细心的读者,可以从上面的描述中,发现一些有意思的东西。Proxy 是写入参数,读取值;Stub 是读取参数,写入值。正好是一对,那因此我们是不是可以做出这样的论断呢?Proxy 和 Stub 操作的是一份数据?恭喜你,答对了。

在前文提及的内容里,用户空间和内核空间是互相隔离的,客户端和服务端在同一用户空间,而 Binder Driver 在内核空间中,常见的方式是通过 copy_from_user 和 copy_to_user 两个系统调用来完成,但 Android Framework 考虑到这种方式涉及到两次内存拷贝,在嵌入式系统中不是很合适,于是 Binder Framework 通过 ioctl 系统调用,直接在内核态进行了相关的操作,节省了宝贵的空间。

可能大家也注意点 Proxy 这里是private权限的,外部是无法访问的,但这里是 Android 有意为之,抛出了 asInterface 方法,这样避免了对 Proxy可能的修改。

系统使用AIDL的场景

AIDL 被Android 系统广泛使用,在许多地方都能看到相应的场景,这里以 电话服务 作为例子,来简单说明下如何在系统没有提供挂断电话的API的情况下强行挂电话。

通过的 ITelephony.aidl 的查看,可以在里面找到相应的接口,不过这个类是 internal 包里面的,应用层无法访问。那怎么来完成这个操作了?

 /**
  * End call if there is a call in progress, otherwise does nothing.
  *
  * @return whether it hung up
  */
 boolean endCall();

首先在相同包名下申明同样的AIDL文件,再通过编译后,就会生成相应的 Stub 文件。其次通过反射拿到 TELEPHONY_SERVICE 的binder。这个 binder 就是可以操作另一个进程来挂断电话的句柄。将这个binder 作为 Proxy 的参数,并通过 asInterface 注入进去,从何获得相应的接口,最后调用 telephony.endCall() 即可完成操作。

Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
IBinder binder = (IBinder) method.invoke(null, new Object[]{TELEPHONY_SERVICE});
ITelephony telephony = ITelephony.Stub.asInterface(binder);
telephony.endCall();

参考文献

  1. https://developer.android.com/guide/components/aidl.html
  2. http://8204129.blog.51cto.com/8194129/1357365

Published:May302016

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android开发艺术探索》是一本Android进阶类书籍,采用理论、源码和实践相结合的方式来阐述高水准的Android应用开发要点。《Android开发艺术探索》从三个方面来组织内容。第一,介绍Android开发者不容易掌握的一些知识点;第二,结合Android源代码和应用层开发过程,融会贯通,介绍一些比较深入的知识点;第三,介绍一些核心技术和Android的性能优化思想。 《Android开发艺术探索》侧重于Android知识的体系化和系统工作机制的分析,通过《Android开发艺术探索》的学习可以极大地提高开发者的Android技术水平,从而更加高效地成为高级开发者。而对于高级开发者来说,仍然可以从《Android开发艺术探索》的知识体系中获益。 书目录 ------------------------------------------------------------------- 第1章 Activity的生命周期和启动模式 / 1   1.1 Activity的生命周期面分析 / 1   1.1.1 典型情况下的生命周期分析 / 2   1.1.2 异常情况下的生命周期分析 / 8   1.2 Activity的启动模式 / 16   1.2.1 Activity的LaunchMode / 16   1.2.2 Activity的Flags / 27   1.3 IntentFilter的匹配规则 / 28   第2章 IPC机制 / 35   2.1 Android IPC简介 / 35   2.2 Android中的多进程模式 / 36   2.2.1 开启多进程模式 / 36   2.2.2 多进程模式的运行机制 / 39   2.3 IPC基础概念介绍 / 42   2.3.1 Serializable接口 / 42   2.3.2 Parcelable接口 / 45   2.3.3 Binder / 47   2.4 Android中的IPC方式 / 61   2.4.1 使用Bundle / 61   2.4.2 使用文件共享 / 62   2.4.3 使用Messenger / 65   2.4.4 使用AIDL / 71   2.4.5 使用ContentProvider / 91   2.4.6 使用Socket / 103   2.5 Binder连接池 / 112   2.6 选用合适的IPC方式 / 121   第3章 View的事件体系 / 122   3.1 View基础知识 / 122   3.1.1 什么是View / 123   3.1.2 View的位置参数 / 123   3.1.3 MotionEvent和TouchSlop / 125   3.1.4 VelocityTracker、GestureDetector和Scroller / 126   3.2 View的滑动 / 129   3.2.1 使用scrollTo/scrollBy / 129   3.2.2 使用动画 / 131   3.2.3 改变布局参数 / 133   3.2.4 各种滑动方式的对比 / 133   3.3 弹性滑动 / 135   3.3.1 使用Scroller / 136   3.3.2 通过动画 / 138   3.3.3 使用延时策略 / 139   3.4 View的事件分发机制 / 140   3.4.1 点击事件的传递规则 / 140   3.4.2 事件分发的源码解析 / 144   3.5 View的滑动冲突 / 154   3.5.1 常见的滑动冲突场景 / 155   3.5.2 滑动冲突的处理规则 / 156   3.5.3 滑动冲突的解决方式 / 157   第4章 View的工作原理 / 174   4.1 初识ViewRoot和DecorView / 174   4.2 理解MeasureSpec / 177   4.2.1 MeasureSpec / 177   4.2.2 MeasureSpec和LayoutParams的对应关系 / 178   4.3 View的工作流程 / 183   4.3.1 measure过程 / 183   4.3.2 layout过程 / 193   4.3.3 draw过程 / 197   4.4 自定义View / 199   4.4.1 自定义View的分类 / 200   4.4.2 自定义View须知 / 201   4.4.3 自定义View示例 / 202   4.4.4 自定义View的思想 / 217   第5章 理解RemoteViews / 218   5.1 RemoteViews的应用 / 218   5.1.1 RemoteViews在通知栏上的应用 / 219   5.1.2 RemoteViews在桌面小部件上的应用 / 221   5.1.3 PendingIntent概述 / 228   5.2 RemoteViews的内部机制 / 230   5.3 RemoteViews的意义 / 239   第6章 Android的Drawable / 243   6.1 Drawable简介 / 243   6.2 Drawable的分类 / 244   6.2.1 BitmapDrawable / 244   6.2.2 ShapeDrawable / 247   6.2.3 LayerDrawable / 251   6.2.4 StateListDrawable / 253   6.2.5 LevelListDrawable / 255   6.2.6 TransitionDrawable / 256   6.2.7 InsetDrawable / 257   6.2.8 ScaleDrawable / 258   6.2.9 ClipDrawable / 260   6.3 自定义Drawable / 262   第7章 Android动画深入分析 / 265   7.1 View动画 / 265   7.1.1 View动画的种类 / 265   7.1.2 自定义View动画 / 270   7.1.3 帧动画 / 272   7.2 View动画的特殊使用场景 / 273   7.2.1 LayoutAnimation / 273   7.2.2 Activity的切换效果 / 275   7.3 属性动画 / 276   7.3.1 使用属性动画 / 276   7.3.2 理解插值器和估值器 / 280   7.3.3 属性动画的监听器 / 282   7.3.4 对任意属性做动画 / 282   7.3.5 属性动画的工作原理 / 288   7.4 使用动画的注意事项 / 292   第8章 理解Window和WindowManager / 294   8.1 Window和WindowManager / 294   8.2 Window的内部机制 / 297   8.2.1 Window的添加过程 / 298   8.2.2 Window的删除过程 / 301   8.2.3 Window的更新过程 / 303   8.3 Window的创建过程 / 304   8.3.1 Activity的Window创建过程 / 304   8.3.2 Dialog的Window创建过程 / 308   8.3.3 Toast的Window创建过程 / 311   第9章 四大组件的工作过程 / 316   9.1 四大组件的运行状态 / 316   9.2 Activity的工作过程 / 318   9.3 Service的工作过程 / 336   9.3.1 Service的启动过程 / 336   9.3.2 Service的绑定过程 / 344   9.4 BroadcastReceiver的工作过程 / 352   9.4.1 广播的注册过程 / 353   9.4.2 广播的发送和接收过程 / 356   9.5 ContentProvider的工作过程 / 362   第10章 Android的消息机制 / 372   10.1 Android的消息机制概述 / 373   10.2 Android的消息机制分析 / 375   10.2.1 ThreadLocal的工作原理 / 375   10.2.2 消息队列的工作原理 / 380   10.2.3 Looper的工作原理 / 383   10.2.4 Handler的工作原理 / 385   10.3 主线程的消息循环 / 389   第11章 Android的线程和线程池 / 391   11.1 主线程和子线程 / 392   11.2 Android中的线程形态 / 392   11.2.1 AsyncTask / 392   11.2.2 AsyncTask的工作原理 / 395   11.2.3 HandlerThread / 402   11.2.4 IntentService / 403   11.3 Android中的线程池 / 406   11.3.1 ThreadPoolExecutor / 407   11.3.2 线程池的分类 / 410   第12章 Bitmap的加载和Cache / 413   12.1 Bitmap的高效加载 / 414   12.2 Android中的缓存策略 / 417   12.2.1 LruCache / 418   12.2.2 DiskLruCache / 419   12.2.3 ImageLoader的实现 / 424   12.3 ImageLoader的使用 / 441   12.3.1 照片墙效果 / 441   12.3.2 优化列表的卡顿现象 / 446   第13章 综合技术 / 448   13.1 使用CrashHandler来获取应用的crash信息 / 449   13.2 使用multidex来解决方法数越界 / 455   13.3 Android的动态加载技术 / 463   13.4 反编译初步 / 469   13.4.1 使用dex2jar和jd-gui反编译apk / 470   13.4.2 使用apktool对apk进行二次打包 / 470   第14章 JNI和NDK编程 / 473   14.1 JNI的开发流程 / 474   14.2 NDK的开发流程 / 478   14.3 JNI的数据类型和类型签名 / 484   14.4 JNI调用Java方法的流程 / 486   第15章 Android性能优化 / 489   15.1 Android的性能优化方法 / 490   15.1.1 布局优化 / 490   15.1.2 绘制优化 / 493   15.1.3 内存泄露优化 / 493   15.1.4 响应速度优化和ANR日志分析 / 496   15.1.5 ListView和Bitmap优化 / 501   15.1.6 线程优化 / 501   15.1.7 一些性能优化建议 / 501   15.2 内存泄露分析之MAT工具 / 502   15.3 提高程序的可维护性 / 506
深入理解Android 卷1 不是扫描版的,是版电子书的,非PDF,可编辑,各种阅览器以打开!包括书签和同步目录! 第1章 阅读前的准备工作 / 1 1.1 系统架构 / 2 1.1.1 Android系统架构 / 2 1.1.2 本书的架构 / 3 1.2 搭建开发环境 / 4 1.2.1 下载源码 / 4 1.2.2 编译源码 / 6 1.3 工具介绍 / 8 1.3.1 Source Insight介绍 / 8 1.3.3 Busybox的使用 / 11 1.4 本章小结 / 12 第2章 深入理解JNI / 13 2.1 JNI概述 / 14 2.2 学习JNI的实例:MediaScanner / 15 2.3 Java层的MediaScanner分析 / 16 2.3.1 加载JNI库 / 16 2.3.2 Java的native函数和总结 / 17 2.4 JNI层MediaScanner的分析 / 17 2.4.1 注册JNI函数 / 18 2.4.2 数据类型转换 / 22 2.4.3 JNIEnv介绍 / 24 2.4.4 通过JNIEnv操作jobject / 25 2.4.5 jstring介绍 / 27 2.4.6 JNI类型签名介绍 / 28 2.4.7 垃圾回收 / 29 2.4.8 JNI中的异常处理 / 32 2.5 本章小结 / 32 第3章 深入理解init / 33 3.1 概述 / 34 3.2 init分析 / 34 3.2.1 解析配置文件 / 38 3.2.2 解析service / 42 3.2.3 init控制service / 48 3.2.4 属性服务 / 52 3.3 本章小结 / 60 第4章 深入理解zygote / 61 4.1 概述 / 62 4.2 zygote分析 / 62 4.2.1 AppRuntime分析 / 63 4.2.2 Welcome to Java World / 68 4.2.3 关于zygote的总结 / 74 4.3 SystemServer分析 / 74 4.3.1 SystemServer的诞生 / 74 4.3.2 SystemServer的重要使命 / 77 4.3.3 关于 SystemServer的总结 / 83 4.4 zygote的分裂 / 84 4.4.1 ActivityManagerService发送请求 / 84 4.4.2 有求必应之响应请求 / 86 4.4.3 关于zygote分裂的总结 / 88 4.5 拓展思考 / 88 4.5.1 虚拟机heapsize的限制 / 88 4.5.2 开机速度优化 / 89 4.5.3 Watchdog分析 / 90 4.6 本章小结 / 93 第5章 深入理解常见类 / 95 5.1 概述 / 96 5.2 以“三板斧”揭秘RefBase、sp和wp / 96 5.2.1 第一板斧——初识影子对象 / 96 5.2.2 第二板斧——由弱生强 / 103 5.2.3 第三板斧——破解生死魔咒 / 106 5.2.4 轻量级的引用计数控制类LightRefBase / 108 5.2.5 题外话-三板斧的来历 / 109 5.3 Thread类及常用同步类分析 / 109 5.3.1 一个变量引发的思考 / 109 5.3.2 常用同步类 / 114 5.4 Looper和Handler类分析 / 121 5.4.1 Looper类分析 / 122 5.4.2 Handler分析 / 124 5.4.3 Looper和Handler的同步关系 / 127 5.4.4 HandlerThread介绍 / 129 5.5 本章小结 / 129 第6章 深入理解Binder / 130 6.1 概述 / 131 6.2 庖丁解MediaServer / 132 6.2.1 MediaServer的入口函数 / 132 6.2.2 独一无二的ProcessState / 133 6.2.3 时空穿越魔术-defaultServiceManager / 134 6.2.4 注册MediaPlayerService / 142 6.2.5 秋风扫落叶-StartThread Pool和join Thread Pool分析 / 149 6.2.6 你彻底明白了吗 / 152 6.3 服务总管ServiceManager / 152 6.3.1 ServiceManager原理 / 152 6.3.2 服务的注册 / 155 6.3.3 ServiceManager存在的意义 / 158 6.4 MediaPlayerService和它的Client / 158 6.4.1 查询ServiceManager / 158 6.4.2 子承父业 / 159 6.5 拓展思考 / 162 6.5.1 Binder和线程的关系 / 162 6.5.2 有人情味的讣告 / 163 6.5.3 匿名Service / 165 6.6 学以致用 / 166 6.6.1 纯Native的Service / 166 6.6.2 扶得起的“阿斗”(aidl) / 169 6.7 本章小结 / 172 第7章 深入理解Audio系统 / 173 7.1 概述 / 174 7.2 AudioTrack的破解 / 174 7.2.1 用例介绍 / 174 7.2.2 AudioTrack(Java空间)分析 / 179 7.2.3 AudioTrack(Native空间)分析 / 188 7.2.4 关于AudioTrack的总结 / 200 7.3 AudioFlinger的破解 / 200 7.3.1 AudioFlinger的诞生 / 200 7.3.2 通过流程分析AudioFlinger / 204 7.3.3 audio_track_cblk_t分析 / 230 7.3.4 关于AudioFlinger的总结 / 234 7.4 AudioPolicyService的破解 / 234 7.4.1 AudioPolicyService的创建 / 235 7.4.2 重回AudioTrack / 245 7.4.3 声音路由切换实例分析 / 251 7.4.4 关于AudioPolicy的总结 / 262 7.5 拓展思考 / 262 7.5.1 DuplicatingThread破解 / 262 7.5.2 题外话 / 270 7.6 本章小结 / 272 第8章 深入理解Surface系统 / 273 8.1 概述 / 275 8.2 一个Activity的显示 / 275 8.2.1 Activity的创建 / 275 8.2.2 Activity的UI绘制 / 294 8.2.3 关于Activity的总结 / 296 8.3 初识Surface / 297 8.3.1 和Surface有关的流程总结 / 297 8.3.2 Surface之乾坤大挪移 / 298 8.3.3 乾坤大挪移的JNI层分析 / 303 8.3.4 Surface和画图 / 307 8.3.5 初识Surface小结 / 309 8.4 深入分析Surface / 310 8.4.1 与Surface相关的基础知识介绍 / 310 8.4.2 SurfaceComposerClient分析 / 315 8.4.3 SurfaceControl分析 / 320 8.4.4 writeToParcel和Surface对象的创建 / 331 8.4.5 lockCanvas和unlockCanvasAndPost分析 / 335 8.4.6 GraphicBuffer介绍 / 344 8.4.7 深入分析Surface的总结 / 353 8.5 SurfaceFlinger分析 / 353 8.5.1 SurfaceFlinger的诞生 / 354 8.5.2 SF工作线程分析 / 359 8.5.3 Transaction分析 / 368 8.5.4 关于SurfaceFlinger的总结 / 376 8.6 拓展思考 / 377 8.6.1 Surface系统的CB对象分析 / 377 8.6.2 ViewRoot的你问我答 / 384 8.6.3 LayerBuffer分析 / 385 8.7 本章小结 / 394 第9章 深入理解Vold和Rild / 395 9.1 概述 / 396 9.2 Vold的原理与机制分析 / 396 9.2.1 Netlink和Uevent介绍 / 397 9.2.2 初识Vold / 399 9.2.3 NetlinkManager模块分析 / 400 9.2.4 VolumeManager模块分析 / 408 9.2.5 CommandListener模块分析 / 414 9.2.6 Vold实例分析 / 417 9.2.7 关于Vold的总结 / 428 9.3 Rild的原理与机制分析 / 428 9.3.1 初识Rild / 430 9.3.2 RIL_startEventLoop分析 / 432 9.3.3 RIL_Init分析 / 437 9.3.4 RIL_register分析 / 444 9.3.5 关于Rild main函数的总结 / 447 9.3.6 Rild实例分析 / 447 9.3.7 关于Rild的总结 / 459 9.4 拓展思考 / 459 9.4.1 嵌入式系统的存储知识介绍 / 459 9.4.2 Rild和Phone的改进探讨 / 462 9.5 本章小结 / 463 第10章 深入理解MediaScanner / 464 10.1 概述 / 465 10.2 android.process.media分析 / 465 10.2.1 MSR模块分析 / 466 10.2.2 MSS模块分析 / 467 10.2.3 android.process.media媒体扫描工作的流程总结 / 471 10.3 MediaScanner分析 / 472 10.3.1 Java层分析 / 472 10.3.2 JNI层分析 / 476 10.3.3 PVMediaScanner分析 / 479 10.3.4 关于MediaScanner的总结 / 485 10.4 拓展思考 / 486 10.4.1 MediaScannerConnection介绍 / 486 10.4.2 我问你答 / 487 10.5 本章小结 / 488

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值