NativeDaemonConnector工作线程

NativeDaemonConnector的作用

    NativeDaemonConnector是与Vold进程通讯的工作线程,它主要完成两个任务:
    1.通过socket监听来自Vold的事件信息,如设备挂载、设备移除等。(称之为被动接收)
    2.为上层提供控制接口,用来执行设备挂载,设备移除、设备扫描的指令。(称之为主动执行)

NativeDaemonConnector初始化

NativeDaemonConnector

NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks,
                      String socket, int responseQueueSize, String logTag) {
    mCallbacks = callbacks;
    mSocket = socket;
    mResponseQueue = new LinkedBlockingQueue<String>(responseQueueSize);
}

INativeDaemonConnectorCallbacks

interface INativeDaemonConnectorCallbacks {
    void onDaemonConnected();
    boolean onEvent(int code, String raw, String[] cooked);
}

被动接收的实现

run

public void run() {
    while (true) {
        try {
            listenToSocket();
        } catch (Exception e) {
            SystemClock.sleep(5000);
        }
    }
}

listenToSocket

private void listenToSocket() throws IOException {
    ......
    try {
        // 初始化LocalSocket
        socket = new LocalSocket();
        LocalSocketAddress address = new LocalSocketAddress(mSocket,
                LocalSocketAddress.Namespace.RESERVED);
        socket.connect(address);
        
        // 调用回调的onDaemonConnected方法
        mCallbacks.onDaemonConnected();

        InputStream inputStream = socket.getInputStream();
        mOutputStream = socket.getOutputStream();
        ......
        while (true) {
            int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
            if (count < 0) break;
            ......
            for (int i = 0; i < count; i++) {
                if (buffer[i] == 0) {
                    ......
                    try {
                        ......
                        // if code >= 600
                        if (code >= ResponseCode.UnsolicitedInformational) {
                            try {
                                // 调用回调的onEvent方法
                                if (!mCallbacks.onEvent(code, event, tokens)) {
                                }
                            } catch (Exception ex) {
                            }
                        } else {
                            try {
                                // 将结果加入应答队列
                                mResponseQueue.put(event);
                            } catch (InterruptedException ex) {
                            }
                        }
                    } catch (NumberFormatException nfe) {
                    }
                }
            }
            ......
        }
    } catch (IOException ex) {
        ......
    } finally {
        ......
    }
}

MountService.VoldResponseCode

class VoldResponseCode {
    /*
     * 100 series - Requestion action was initiated; expect another reply
     *              before proceeding with a new command.
     */
    public static final int VolumeListResult               = 110;
    public static final int AsecListResult                 = 111;
    public static final int StorageUsersListResult         = 112;

    /*
     * 200 series - Requestion action has been successfully completed.
     */
    public static final int ShareStatusResult              = 210;
    public static final int AsecPathResult                 = 211;
    public static final int ShareEnabledResult             = 212;

    /*
     * 400 series - Command was accepted, but the requested action
     *              did not take place.
     */
    public static final int OpFailedNoMedia                = 401;
    public static final int OpFailedMediaBlank             = 402;
    public static final int OpFailedMediaCorrupt           = 403;
    public static final int OpFailedVolNotMounted          = 404;
    public static final int OpFailedStorageBusy            = 405;
    public static final int OpFailedStorageNotFound        = 406;

    /*
     * 600 series - Unsolicited broadcasts.
     */
    public static final int VolumeStateChange              = 605;
    public static final int ShareAvailabilityChange        = 620;
    public static final int VolumeDiskInserted             = 630;
    public static final int VolumeDiskRemoved              = 631;
    public static final int VolumeBadRemoval               = 632;
    // this value indicates it's ok to mount disk
    public static final int VolumeOKtoMount                = 633;
}

主动执行的实现

doCommand

public synchronized ArrayList<String> doCommand(String cmd)
        throws NativeDaemonConnectorException  {
    mResponseQueue.clear();
    // 调用sendCommand发送命令
    sendCommand(cmd);
    ArrayList<String> response = new ArrayList<String>();
    
    while (!complete) {
        try {
            // mResponseQueue是BlockingQueue类型,会阻塞短暂时间,
            // 在这段时间内接收线程会接收到Vold的反馈,如果返回码
            // 小于600,会被加入到这个队列中,此时会从队列中取出。
            String line = mResponseQueue.take();
            String[] tokens = line.split(" ");
            try {
                code = Integer.parseInt(tokens[0]);
            } catch (NumberFormatException nfe) {
            }

            if ((code >= 200) && (code < 600)) {
                complete = true;
            }
            // 将解析的返回码加入列表
            response.add(line);
        } catch (InterruptedException ex) {
        }
    }

    ...... 
    // 返回应答结果
    return response;
}

sendCommand

private void sendCommand(String command, String argument)
        throws NativeDaemonConnectorException  {

    synchronized (this) {
        if (mOutputStream == null) {
            throw new NativeDaemonConnectorException("No output stream!");
        } else {
            StringBuilder builder = new StringBuilder(command);
            if (argument != null) {
                builder.append(argument);
            }
            builder.append('\0');

            try {
                // 通过socket发送消息
                mOutputStream.write(builder.toString().getBytes());
            } catch (IOException ex) {
            }
        }
    }
}