NativeDaemonConnector工作线程
NativeDaemonConnector的作用
    NativeDaemonConnector是与Vold进程通讯的工作线程,它主要完成两个任务:
    1.通过socket监听来自Vold的事件信息,如设备挂载、设备移除等。(称之为被动接收)
    2.为上层提供控制接口,用来执行设备挂载,设备移除、设备扫描的指令。(称之为主动执行)
NativeDaemonConnector初始化
- 
NativeDaemonConnector继承自Runnable类,MountService通过其初始化一个Thread,之后还需要通过该类的doCommand方法与Vold通讯。
- 
构造方法主要有以下几点相关操作:
- 
设置callback,该回调的实现者是MountService,由此可知当事件被通报后,会由MountService做具体处理。
- 
设置socket名称,Java的socket实现是透过JNI调用完成,该名称将会向下传递。
- 
创建一个String类型的队列,每当上层发送控制指令给Vold进程后,会将接收自Vold的特定信息加入到该队列中,返回给上层的应答会从该队列中取。
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方法中实现,它调用listenToSocket方法监听Vold的状态。
run
public void run() {
    while (true) {
        try {
            listenToSocket();
        } catch (Exception e) {
            SystemClock.sleep(5000);
        }
    }
}
- 
listenToSocket首先会初始化一个LocalSocket,当与Vold进程连接后,会调用回调的onDaemonConnected方法,该回调再通过NativeDaemonConnector对象获取设备状态。
- 
接下来会循环接收来自Vold的socket数据,如果没有数据到来会阻塞在read方法。可以把该方法作为流数据处理的范例来学习。
- 
如果接收到底层传来的有效数据,会根据结果做出不同的动作:
- 
如果返回码大于ResponseCode.UnsolicitedInformational则调用回调的onEvent方法。(ResponseCode.UnsolicitedInformational值为600)
- 
如果返回码小于ResponseCode.UnsolicitedInformational则将该事件加入到应答队列。
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 {
        ......
    }
}
- 
VoldResponseCode类描述了来自Vold的消息代码,大于600的代码表示了设备状态变化,因此上述代码中大于等于600时onEvent才会被调用。
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;
}
主动执行的实现
- 
主动执行是指上层模块通过特定接口向Vold发送指令,执行设备相关的操作,如mount、unmount。
- 
NativeDaemonConnector主要提供了两个方法doCommand和doListCommand。
- 
doCommand和doListCommand最终会调用sendCommand方法,通过socket向Vold发送指令。有时上层会发送一些查询指令到Vold,因此doCommand会返回一个字符串列表作为应答结果。
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) {
            }
        }
    }
}