Android5.0 vold-注册过程(上)

转载请标明出处:http://www.jianshu.com/users/183339cdc7ae/latest_articles

概述

前面几篇介绍了vold的框架和内部结构以及启动顺序,可以知道的是vold接受到消息后是如果工作的。这一片文章主要讲的是,vold中的接受上层消息的socket是如何注册的。

相关文章

Android5.0 vold-整体架构
Android5.0 vold-启动过程
Android5.0 vold-注册过程(下)

MountService

创建

vold整体框架可以知道,vold能接受上层(MountService)发过来的信息,我们就从mountservice看起走,是在哪里注册的,先来看看构造方法.
这个NativeDaemonConnector类可以看出是继承自Runnable接口应用层(如:Setting)发送的命令会传给MountService,MountService中有一个线程来接受这个命令需要注意的是NativeDaemonConnector的第二个参数"vold",这里先记住这个参数的名字

 public MountService(Context context) {
     ...
     mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
                null);
     Thread thread = new Thread(mConnector, VOLD_TAG);
     thread.start();
     ...
 }

可以看出的是这个socket的名字就为vold.

NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
            int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
            Looper looper) {
        ...
        mSocket = socket;
        ...
}

因为之前执行了thread.start();所以我们再来看看NativeDaemonConnector的run方法
可以看到实例化了一个LocalSocket,这个LocalSocket是对unix socket操作的一个封装,可以理解为一个工具类,这里仅仅只是做了一个实例化的动作,还并没有创建socket
LocalSocketAddress对象也只是一个地址封装类,里面会封装socket的一个地址,查看代码可以知道的是这个地址名字就叫做“vold”,为前面mSocket的值,并且这个socket文件路径为: /dev/socket/vold
接下来是connect动作,这里面就会创建正真的socket并且指定地址为/dev/socket/vold在这个线程里面会监听由vold发过来的消息,然后再做后续的一些处理 [注:这里是vold发上来的信息]

 public void run() {
        ...
        while (true) {
           ...
           listenToSocket();
           ...      
        }
 }

 private void listenToSocket() throws IOException {
       LocalSocket socket = null;
       ...
       socket = new LocalSocket();
       LocalSocketAddress address = determineSocketAddress();
       socket.connect(address);
       ...
       int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
       ...
       if (mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
              event.getCode(), event.getRawEvent()))) {
       ...
       }     
 }

写入

上面说了socket的创建和读取信息,接下来看是如何往socket里面写的
mountService中会有一些方法供app层调用,这里以加密手机文件为例(命令:cryptfs),最终会封装一些参数到NativeDaemonConnector的execute方法
这个mOutputStream对象也就是之前创建的socket中获取的OutputStream
execute方法最终会往socket中写入数据

 public int encryptStorage(int type, String password) {
        ...
        mConnector.execute("cryptfs", "enablecrypto", "inplace", CRYPTO_TYPES[type],
                           new SensitiveArg(toHex(password)));
        ...
    }

    public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
            throws NativeDaemonConnectorException {
        ...
        mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
        ...
    }

Vold

创建

我们回顾一下init.rc里面启动vold的代码重点是socket这一行.
根据init的语法可以知道的是,这一行会生产一个名叫vold的socket文件在/dev/socket/目录下

service vold /system/bin/vold
    class core
    socket vold stream 0660 root mount
    ioprio be 2

寻找

再回顾一下CommandListener的构造方法,这里传入的是vold一个字符串
这个vold会传入到SocketListener中,并赋值给mSocketName变量

CommandListener::CommandListener() :FrameworkListener("vold", true) 
FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :SocketListener(socketName, true, withSeq) {

根据前文我们可以知道,启动监听的时候会调用到startListener方法然后android_get_control_socket方法会根据mSocketName返回一个fd文件

int SocketListener::startListener(int backlog) {
    ...
        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
            SLOGE("Obtaining file descriptor socket '%s' failed: %s",
                 mSocketName, strerror(errno));
            return -1;
        }
        SLOGV("got mSock = %d for %s", mSock, mSocketName);
   ...
}

android_get_control_socket的定义是在system/core/include/cutils/sockets.h中具体的实现就不仔细看了,看注释可以知道的是,这里返回的fd文件会是init.rc里面创建的文件也就是/dev/socket/vold文件

/*
 * android_get_control_socket - simple helper function to get the file
 * descriptor of our init-managed Unix domain socket. `name' is the name of the
 * socket, as given in init.rc. Returns -1 on error.
 *
 * This is inline and not in libcutils proper because we want to use this in
 * third-party daemons with minimal modification.
 */
static inline int android_get_control_socket(const char *name)
{..}

总结

根据上文可以知道是

  1. init.rc在启动vold的时候,会先创建一个/dev/socket/vold的socket文件
  2. 然后native vold启动完成时,会监听这个/dev/socket/vold socket
  3. 再然后是我们的MountService的启动,启动的时候会先得到/dev/socket/vold的地址,然后connect这个地址

这样可以往这个socket里面写入值了
如果对socket不是很熟悉的童鞋可以看看 关于socket的基本操作

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容