整个Vold机制应该算system层,与framwork层的交互在Android—— 4.2 Vold挂载管理_CommandListener (二)中有提到过,是通过一个"vold"的socket进行通信的,这里分析一下framework中负责与Vold通信的:MountService


                                                       撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/38978387



一.MountService启动:

在/frameworks/base/services/java/com/android/server/SystemServer.java中有:

            if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {                try {                    /*                     * NotificationManagerService is dependant on MountService,                     * (for media / usb notifications) so we must start MountService first.                     */                    Slog.i(TAG, "Mount Service");                    mountService = new MountService(context);                    ServiceManager.addService("mount", mountService);                } catch (Throwable e) {                    reportWtf("starting Mount Service", e);                }            }

开机启动的系统服务之一,关于系统初始启动详情可参考: Android——启动过程详析 


public MountService(Context context) {        mContext = context;        synchronized (mVolumesLock) {            readStorageListLocked(); // 解析/frameworks/base/core/res/res/xml/storage_list.xml保存volume到 MountService的list :mVolumes中        }        // XXX: This will go away soon in favor of IMountServiceObserver        mPms = (PackageManagerService) ServiceManager.getService("package");        mHandlerThread = new HandlerThread("MountService");        mHandlerThread.start();        mHandler = new MountServiceHandler(mHandlerThread.getLooper());//新建消息处理handler        // Watch for user changes        final IntentFilter userFilter = new IntentFilter();        userFilter.addAction(Intent.ACTION_USER_ADDED);        userFilter.addAction(Intent.ACTION_USER_REMOVED);        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);//注册广播接收        // Watch for USB changes on primary volume        final StorageVolume primary = getPrimaryPhysicalVolume();        if (primary != null && primary.allowMassStorage()) {            mContext.registerReceiver(                    mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE), null, mHandler);        }        // Add OBB Action Handler to MountService thread.        mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper());        /*         * Create the connection to vold with a maximum queue of twice the         * amount of containers we'd ever expect to have. This keeps an         * "asec list" from blocking a thread repeatedly.         */        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25);//创建 vold 的监听接收,用于接收system中Vold的socket消息        Thread thread = new Thread(mConnector, VOLD_TAG);        thread.start();//启动线程,NativeDaemonConnector实现了Runnable接口,实现在 run中        // Add ourself to the Watchdog monitors if enabled.        if (WATCHDOG_ENABLE) {            Watchdog.getInstance().addMonitor(this);        }    }


二.MountService接收Socket:

上面有看到构造了NativeDaemonConnector用来接收来自下层的socket消息,先看构造:

    NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,            int responseQueueSize, String logTag, int maxLogSize) {        mCallbacks = callbacks; //回调        mSocket = socket; // socket名称        mResponseQueue = new ResponseQueue(responseQueueSize);//构建一个响应队列        mSequenceNumber = new AtomicInteger(0);        TAG = logTag != null ? logTag : "NativeDaemonConnector";        mLocalLog = new LocalLog(maxLogSize);    }

在上面开启监测线程的run方法:

    public void run() {        HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); //TAG 为 VoldConnector,这里新建一个名为VoldConnector.CallbackHandler的消息处理线程,用于下面接收到vold 的socket之后的处理        thread.start();        mCallbackHandler = new Handler(thread.getLooper(), this); //创建handler 用于分发消息        while (true) {            try {                listenToSocket();// while 循环 监听socket            } catch (Exception e) {                loge("Error in NativeDaemonConnector: " + e);                SystemClock.sleep(5000);            }        }    }

往里看 listenToSocket


    private void listenToSocket() throws IOException {        LocalSocket socket = null;        try {            socket = new LocalSocket();  //创建本地socket            LocalSocketAddress address = new LocalSocketAddress(mSocket,                    LocalSocketAddress.Namespace.RESERVED);//获得服务端vold socket的地址            socket.connect(address);//连接            InputStream inputStream = socket.getInputStream();            synchronized (mDaemonLock) {                mOutputStream = socket.getOutputStream();            }//获取输入输出流            mCallbacks.onDaemonConnected();//回调,在MountService中执行,初始化一些Volume状态信息            byte[] buffer = new byte[BUFFER_SIZE];            int start = 0;            while (true) {                int count = inputStream.read(buffer, start, BUFFER_SIZE - start);//读取数据到buffer                if (count < 0) {//连接断开,跳出当前while ,外部while循环 重新调用该函数连接                    loge("got " + count + " reading with start = " + start);                    break;                }                // Add our starting point to the count and reset the start.                count += start;                start = 0;                for (int i = 0; i < count; i++) {                    if (buffer[i] == 0) {                        final String rawEvent = new String(                                buffer, start, i - start, Charsets.UTF_8);                        log("RCV <- {" + rawEvent + "}");                        try {                            final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(                                    rawEvent);   //解析成event 保存                            if (event.isClassUnsolicited()) {    //判断event的code范围 code >= 600 && code < 700                                // TODO: migrate to sending NativeDaemonEvent instances                                mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage( //发送消息,把event交给handle来分发处理                                        event.getCode(), event.getRawEvent()));                            } else {                                mResponseQueue.add(event.getCmdNumber(), event);//加入到响应队列                            }                        } catch (IllegalArgumentException e) {                            log("Problem parsing message: " + rawEvent + " - " + e);                        }                        start = i + 1;                    }                }        ...           }     }}

在NativeDaemonConnector中的handle处理为:


    @Override    public boolean handleMessage(Message msg) {        String event = (String) msg.obj;        try {            if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) { //回调到MountService 的onEent函数                log(String.format("Unhandled event '%s'", event));            }        } catch (Exception e) {            loge("Error handling '" + event + "': " + e);        }        return true;    }

到MountService中onEvent

    public boolean onEvent(int code, String raw, String[] cooked) {        if (DEBUG_EVENTS) {            StringBuilder builder = new StringBuilder();            builder.append("onEvent::");            builder.append(" raw= " + raw);            if (cooked != null) {                builder.append(" cooked = " );                for (String str : cooked) {                    builder.append(" " + str);                }            }            Slog.i(TAG, builder.toString());        }        if (code == VoldResponseCode.VolumeStateChange) { //根据 Vold的Code 执行            /*             * One of the volumes we're managing has changed state.             * Format: "NNN Volume 


可以看到根据code值执行相对应的操作,在Android—— 4.2 Vold挂载管理_DirectVolume/Volume (五)中的DirectVolume中 DirectVolume::handleBlockEvent中就发送了ResponseCode::VolumeDiskInserted

MountService中对Vold的socket接收大体就是这样!


三.MountService下发Command:

就从上面doMountVolume来解析,MountService中对Volume的各种操作都是需要转换成符合Vold中socket command,这样Vold中才能正确的解析识别调用!

    private int doMountVolume(String path) {        int rc = StorageResultCode.OperationSucceeded;        final StorageVolume volume;        synchronized (mVolumesLock) {            volume = mVolumesByPath.get(path);        }        if (DEBUG_EVENTS) Slog.i(TAG, "doMountVolume: Mouting " + path);        try {            mConnector.execute("volume", "mount", path);// 调用到NativeDaemonConnector中的execute        }     ...}

NativeDaemonConnector中:

    public NativeDaemonEvent execute(String cmd, Object... args)            throws NativeDaemonConnectorException {        final NativeDaemonEvent[] events = executeForList(cmd, args);//由executeForList发送,返回NativeDaemonEent事件        if (events.length != 1) {            throw new NativeDaemonConnectorException(                    "Expected exactly one response, but received " + events.length);        }        return events[0];    }

最终调用到:
    public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)            throws NativeDaemonConnectorException {        final ArrayList events = Lists.newArrayList();        final int sequenceNumber = mSequenceNumber.incrementAndGet();        final StringBuilder cmdBuilder =                new StringBuilder(Integer.toString(sequenceNumber)).append(' ');        final long startTime = SystemClock.elapsedRealtime();        makeCommand(cmdBuilder, cmd, args); //转换制作成标准的Command        final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */        log("SND -> {" + logCmd + "}");        cmdBuilder.append('\0');        final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */        synchronized (mDaemonLock) {            if (mOutputStream == null) {                throw new NativeDaemonConnectorException("missing output stream");            } else {                try {                    mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8)); //通过在listenToSocket中获取的输出流,写入转换好的sentCmd                } catch (IOException e) {                    throw new NativeDaemonConnectorException("problem sending command", e);                }            }        }     ...}

MountService 中往下发command的流程大体就是这样!

简单流程图:

            

至此,framework与Vold的分析就到这里!





更多相关文章

  1. Android(安卓)之ActivityThead、ActivityManagerService 与activ
  2. [置顶] Android(安卓)启动 白屏问题 解决
  3. Android的Message Pool是个什么鬼——源码角度分析
  4. android中wifi原理及流程分析(很经典)
  5. Android利用NotificationListenerService实现消息盒子功能
  6. Android(安卓)Kernel Porting 的简单总结文档
  7. Android客户端接收来自Faye的消息推送
  8. Android的Launcher成为系统中第一个启动的,也是唯一的Launcher
  9. 【 Android(安卓)10 系统启动 】系列 -- ShutdownThread(关机流程

随机推荐

  1. revoke_permission 实现过程
  2. Android线性LinearLayout布局xml属性介绍
  3. 关于 Android 进程保活,你所需要知道的一
  4. Andriod是什么?
  5. Android动态获取json解析后显示到Recycle
  6. Android内存泄漏查找
  7. 学习TimePicker和DataPicker
  8. Android Wear手表蓝牙连接Android Studio
  9. Android(安卓)Scroll
  10. Android(安卓)-- SurfaceFlinger 合成主