源码分析之存储系统启动流程MountService模块

上篇我们介绍了Android的存储系统中native层的Vold的启动流程,Vold在init进程中通过init脚本进行启动,而MountService则是在Java的服务总站SystemServer中配置启动的,下面我们就来看一下Java层的MountService是如何启动的。

MountService启动流程

Java层的MountService服务是在SystemServer中配置的,我们来分析一下其启动流程。

SystemServer启动配置

private static final String MOUNT_SERVICE_CLASS = "com.android.server.MountService$Lifecycle";

private void startOtherServices() {

    ...
    if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        if (!disableStorage &&
            !"0".equals(SystemProperties.get("system_init.startmountservice"))) {
            try {
                /*
                 * NotificationManagerService is dependant on MountService,
                 * (for media / usb notifications) so we must start MountService first.
                 */
                //启动MountService服务
                mSystemServiceManager.startService(MOUNT_SERVICE_CLASS);
                //等价new IMountService.Stub.Proxy(),即获取MountService的proxy对象
                mountService = IMountService.Stub.asInterface(
                        ServiceManager.getService("mount"));
            } catch (Throwable e) {
                reportWtf("starting Mount Service", e);
            }
        }
    }
    ...

}

这里可以看出,启动MountService并非直接启动,而是通过其静态内部类Lifecycle实现启动,下面我们看一下其内部静态类的实现。

静态内部类Lifecycle

// Lifecycle继承SystemService,受制于父类的生命周期方法回调,其为MountService的内部静态类,控制MountService的实例化操作
public static class Lifecycle extends SystemService {
    private MountService mMountService;

    public Lifecycle(Context context) {
        super(context);
    }

    @Override
    public void onStart() {
        //创建MountService对象【见小节2.3】
        mMountService = new MountService(getContext());
        //登记Binder服务
        publishBinderService("mount", mMountService);
    }

    // 由SystenServer启动到指定阶段进行回调,其内部由mServices持有
    @Override
    public void onBootPhase(int phase) {
        // 由于MountService的内部Lifecycle已添加SystemServiceManager的mServices服务列表;
        // 系统启动到PHASE_ACTIVITY_MANAGER_READY时会回调mServices中的onBootPhase方法
        if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
            mMountService.systemReady();
        }
    }

    ...

}

静态内部类Lifecycle中实现MountService的初始化操作,然后通过publishBinderService将新建的MountService添加到服务列表中。

MountService初始化

MountService在其静态内部类LifeCycle中进行初始化,具体如下:

public MountService(Context context) {
    sSelf = this;

    mContext = context;
    //FgThread线程名为“"android.fg",创建IMountServiceListener回调方法(1线程)
    mCallbacks = new Callbacks(FgThread.get().getLooper());

    // XXX: This will go away soon in favor of IMountServiceObserver
    //获取PKMS的Client端对象
    mPms = (PackageManagerService) ServiceManager.getService("package");

    //创建“MountService”线程(2线程)
    HandlerThread hthread = new HandlerThread(TAG);
    hthread.start();
    mHandler = new MountServiceHandler(hthread.getLooper());

    // Add OBB Action Handler to MountService thread.
    //IoThread线程名为"android.io",创建OBB操作的handler(3线程)
    mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());

    // Initialize the last-fstrim tracking if necessary
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
    //判断/data/system/last-fstrim文件,不存在则创建,存在则更新最后修改时间
    if (!mLastMaintenanceFile.exists()) {
        // Not setting mLastMaintenance here means that we will force an
        // fstrim during reboot following the OTA that installs this code.
        try {
            (new FileOutputStream(mLastMaintenanceFile)).close();
        } catch (IOException e) {
            Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
        }
    } else {
        mLastMaintenance = mLastMaintenanceFile.lastModified();
    }

    mSettingsFile = new AtomicFile(
            new File(Environment.getSystemSecureDirectory(), "storage.xml"));

    synchronized (mLock) {
        readSettingsLocked();
    }

    //将MountServiceInternalImpl登记到sLocalServiceObjects,区别Binder的RemoteService
    LocalServices.addService(MountServiceInternal.class, mMountServiceInternal);

    /*
     * 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.
     */

    //创建用于VoldConnector的NDC(native守护进程连接器)对象
    mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
            null);
    mConnector.setDebug(true);

    //创建线程名为"VoldConnector"的线程,用于跟vold通信,启动(4线程)
    Thread thread = new Thread(mConnector, VOLD_TAG);
    thread.start();

    // Reuse parameters from first connector since they are tested and safe
    //创建用于CryptdConnector工作的NDC对象,同上面的一样
    mCryptConnector = new NativeDaemonConnector(this, "cryptd",
            MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
    mCryptConnector.setDebug(true);

    //创建线程名为"CryptdConnector"的线程,用于加密(5线程)
    Thread crypt_thread = new Thread(mCryptConnector, CRYPTD_TAG);
    crypt_thread.start();

    //注册监听用户添加、删除的广播
    final IntentFilter userFilter = new IntentFilter();
    userFilter.addAction(Intent.ACTION_USER_ADDED);
    userFilter.addAction(Intent.ACTION_USER_REMOVED);
    mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);

    //内部私有volume的路径为/data,该volume通过dumpsys mount是不会显示的
    addInternalVolume();

    // Add ourself to the Watchdog monitors if enabled.
    if (WATCHDOG_ENABLE) {
        Watchdog.getInstance().addMonitor(this);
    }
}

代码内容比较多,我们梳理一下其主要工作:

  • 创建线程 Callbacks,线程名android.fg
  • 创建线程 HandlerThread,线程名MountService,并开启
  • 创建线程 ObbActionHandler,线程名android.io
  • 创建 NativeDaemonConnector对象,线程 thread并开启,线程名VoldConnector
  • 创建 NativeDaemonConnector对象,线程 crypt_thread并开启,线程名CryptdConnector
  • 注册广播和其他操作

这里设计线程数量比较多,新建了三个线程:MountService,VoldConnector,CryptdConnector;还有两个额外的系统进程中的线程android.fg和android.io

Callbacke

private static class Callbacks extends Handler {
    private static final int MSG_STORAGE_STATE_CHANGED = 1;
    private static final int MSG_VOLUME_STATE_CHANGED = 2;
    private static final int MSG_VOLUME_RECORD_CHANGED = 3;
    private static final int MSG_VOLUME_FORGOTTEN = 4;
    private static final int MSG_DISK_SCANNED = 5;
    private static final int MSG_DISK_DESTROYED = 6;

    //通过 register() 方法添加 IMountServiceListener 对象信息到 mCallbacks 成员变量。
    // RemoteCallbackList 的内部类 Callback 继承于 IBinder.DeathRecipient,这是死亡通知
    //当 binder 服务端进程死亡后,回调 binderDied 方法通知 binder 客户端进行相应地处理
    private final RemoteCallbackList<IMountServiceListener>
            mCallbacks = new RemoteCallbackList<>();

    public Callbacks(Looper looper) {
        super(looper);
    }

    public void register(IMountServiceListener callback) {
        mCallbacks.register(callback);
    }

    public void unregister(IMountServiceListener callback) {
        mCallbacks.unregister(callback);
    }

    @Override
    public void handleMessage(Message msg) {
        final SomeArgs args = (SomeArgs) msg.obj;
        final int n = mCallbacks.beginBroadcast();
        for (int i = 0; i < n; i++) {
            final IMountServiceListener callback = mCallbacks.getBroadcastItem(i);
            try {
                invokeCallback(callback, msg.what, args);
            } catch (RemoteException ignored) {
            }
        }
        mCallbacks.finishBroadcast();
        args.recycle();
    }

    private void invokeCallback(IMountServiceListener callback, int what, SomeArgs args)
            throws RemoteException {
        switch (what) {
            case MSG_STORAGE_STATE_CHANGED: {
                callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
                        (String) args.arg3);
                break;
            }

            ...

        }
    }

    private void notifyStorageStateChanged(String path, String oldState, String newState) {
        final SomeArgs args = SomeArgs.obtain();
        args.arg1 = path;
        args.arg2 = oldState;
        args.arg3 = newState;
        obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
    }

    ...

}

Callback继承自handler,其中Looper采用的是系统进程线程android.fg,其内部还有一个成员变量mCallbacks,通过register()方法添加IMountServiceListener对象信息到mCallbacks成员变量。RemoteCallbackList的内部类Callback继承于IBinder.DeathRecipient,很显然这是死亡通知,当binder服务端进程死亡后,回调binderDied方法通知binder客户端进行相应地处理。

MountServiceHandler

class MountServiceHandler extends Handler {
    public MountServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case H_SYSTEM_READY: {
                // 处理system_server主线程发送 H_SYSTEM_READY 消息
                handleSystemReady();
                break;
            }
            case H_DAEMON_CONNECTED: {
                // Daemon-Socket 已经建立连接
                handleDaemonConnected();
                break;
            }

            ...

            case H_VOLUME_MOUNT: {
                final VolumeInfo vol = (VolumeInfo) msg.obj;
                if (isMountDisallowed(vol)) {
                    Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
                    break;
                }
                try {
                    mConnector.execute("volume", "mount", vol.id, vol.mountFlags,
                            vol.mountUserId);
                } catch (NativeDaemonConnectorException ignored) {
                }
                break;
            }

            ...

        }
    }
}

Handler主线程,负责处理所有的UI事件。

NativeDaemonConnector初始化

NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
        int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
    this(callbacks, socket, responseQueueSize, logTag, maxLogSize, wl,
            FgThread.get().getLooper());
}

// mLooper 为 FgThread.get().getLooper(),即运行在 ”android.fg” 线程
NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
        int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
        Looper looper) {
    mCallbacks = callbacks;
    //socket名为"vold"
    mSocket = socket;
    // mResponseQueue 对象中成员变量 mPendingCmds 数据类型为 LinkedList
    //记录着 vold 进程上报的响应事件,事件个数上限为500
    mResponseQueue = new ResponseQueue(responseQueueSize);
    mWakeLock = wl;
    if (mWakeLock != null) {
        mWakeLock.setReferenceCounted(true);
    }
    mLooper = looper;
    mSequenceNumber = new AtomicInteger(0);

    // TAG 为"VoldConnector"
    TAG = logTag != null ? logTag : "NativeDaemonConnector";
    mLocalLog = new LocalLog(maxLogSize);
}

NativeDaemonConnector使用的线程为android.fg,其主要负责和Native层Vold进程通过Socket进行痛惜,其中mResponseQueue对象中成员变量mPendingCmds数据类型为LinkedList,记录着vold进程上报的响应事件,事件个数上限为500。

在线程VoldConnector中建立了名为vold的socket的客户端,通过循环方式不断监听Vold服务端发送过来的消息。 另外,同理还有一个线程CryptdConnector也采用类似的方式,建立了cryptd的socket客户端,监听Vold中另个线程发送过来的消息。

NDC->run

接下来就是NDC的start进入run方法,如下;

@Override
public void run() {
    mCallbackHandler = new Handler(mLooper, this);

    while (true) {
        try {
            //监听vold的socket
            listenToSocket();
        } catch (Exception e) {
            loge("Error in NativeDaemonConnector: " + e);
            SystemClock.sleep(5000);
        }
    }
}

listenToSocket

// 监听 socket 内数据
private void listenToSocket() throws IOException {
    LocalSocket socket = null;

    try {
        socket = new LocalSocket();
        LocalSocketAddress address = determineSocketAddress();

        // 建立与"/dev/socket/vold"的socket连接
        socket.connect(address);

        InputStream inputStream = socket.getInputStream();
        synchronized (mDaemonLock) {
            mOutputStream = socket.getOutputStream();
        }

        // 建立连接后,回调 MS.onDaemonConnected
        mCallbacks.onDaemonConnected();

        byte[] buffer = new byte[BUFFER_SIZE];
        int start = 0;

        while (true) {
            int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
            if (count < 0) {
                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) {
                    // Note - do not log this raw message since it may contain
                    // sensitive data
                    final String rawEvent = new String(
                            buffer, start, i - start, StandardCharsets.UTF_8);

                    boolean releaseWl = false;
                    try {
                        //解析 socket 服务端发送的 event
                        final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(
                                rawEvent);

                        log("RCV <- {" + event + "}");

                        //当事件的响应码区间为[600,700),则发送消息交由 mCallbackHandler 处理
                        if (event.isClassUnsolicited()) {
                            // TODO: migrate to sending NativeDaemonEvent instances
                            if (mCallbacks.onCheckHoldWakeLock(event.getCode())
                                    && mWakeLock != null) {
                                mWakeLock.acquire();
                                releaseWl = true;
                            }
                            if (mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
                                    event.getCode(), event.getRawEvent()))) {
                                releaseWl = false;
                            }
                        } else {
                            // 对于其他的响应码则添加到 mResponseQueue 队列
                            // 该方法便能触发 ResponseQueue.poll 阻塞操作继续往下执行
                            mResponseQueue.add(event.getCmdNumber(), event);
                        }
                    } catch (IllegalArgumentException e) {
                        log("Problem parsing message " + e);
                    } finally {
                        if (releaseWl) {
                            mWakeLock.acquire();
                        }
                    }
                    start = i + 1;
                }
            }

            if (start == 0) {
                log("RCV incomplete");
            }

            // We should end at the amount we read. If not, compact then
            // buffer and read again.
            if (start != count) {
                final int remaining = BUFFER_SIZE - start;
                System.arraycopy(buffer, start, buffer, 0, remaining);
                start = remaining;
            } else {
                start = 0;
            }
        }
    } catch (IOException ex) {
        loge("Communications error: " + ex);
        throw ex;
    } finally {
        //收尾清理类工作,关闭mOutputStream, socket
        synchronized (mDaemonLock) {
            if (mOutputStream != null) {
                try {
                    loge("closing stream for " + mSocket);
                    mOutputStream.close();
                } catch (IOException e) {
                    loge("Failed closing output stream: " + e);
                }
                mOutputStream = null;
            }
        }

        try {
            if (socket != null) {
                socket.close();
            }
        } catch (IOException ex) {
            loge("Failed closing socket: " + ex);
        }
    }
}

内容比较多,这里也是比较重要的部分,建立连接后,便会进行onDaemonConnected回调。之后进入死循环不断监听,调用NativeDaemonEvent.parseRawEvent解析Socket内的元数据,根据事件类型进行分类处理。当事件的响应码区间为[600,700),则发送消息交由 mCallbackHandler 处理,其他的则添加到 mResponseQueue 队列,触发 ResponseQueue.poll 阻塞操作继续往下执行。最终在finally释放锁和清理工作。

onDaemonConnected

// 主线程发送消息 H_DAEMON_CONNECTED 给线程 MountService
// 该线程收到消息后调用 MountServiceHandler 的 handleMessage()
@Override
public void onDaemonConnected() {
    mDaemonConnected = true;
    mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
}

其通过handler,最终调用到handleDaemonConnected,如下:

MountService.handleDaemonConnected

private void handleDaemonConnected() {
    synchronized (mLock) {
        // 重置清理工作
        resetIfReadyAndConnectedLocked();
    }

    /*
     * Now that we've done our initialization, release
     * the hounds!
     */

    // 类型为 CountDownLatch,用于多线程同步,阻塞await()直到计数器为零
    mConnectedSignal.countDown();
    if (mConnectedSignal.getCount() != 0) {
        // More daemons need to connect
        return;
    }

    // On an encrypted device we can't see system properties yet, so pull
    // the system locale out of the mount service.
    if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
        copyLocaleFromMountService();
    }

    // Let package manager load internal ASECs.
    //调用PMS来加载ASECs
    mPms.scanAvailableAsecs();

    // Notify people waiting for ASECs to be scanned that it's done.
    //用于通知ASEC扫描已完成
    mAsecsScanned.countDown();
}

mResponseQueue.add

public void add(int cmdNum, NativeDaemonEvent response) {
        PendingCmd found = null;
        synchronized (mPendingCmds) {
            for (PendingCmd pendingCmd : mPendingCmds) {
                if (pendingCmd.cmdNum == cmdNum) {
                    found = pendingCmd;
                    break;
                }
            }

            //没有找到则创建相应的PendingCmd
            if (found == null) {
                // 没有找到,在添加之前,确保队列容量不溢出
                while (mPendingCmds.size() >= mMaxCount) {
                    Slog.e("NativeDaemonConnector.ResponseQueue",
                            "more buffered than allowed: " + mPendingCmds.size() +
                            " >= " + mMaxCount);
                    // let any waiter timeout waiting for this
                    PendingCmd pendingCmd = mPendingCmds.remove();
                    Slog.e("NativeDaemonConnector.ResponseQueue",
                            "Removing request: " + pendingCmd.logCmd + " (" +
                            pendingCmd.cmdNum + ")");
                }
                found = new PendingCmd(cmdNum, null);
                mPendingCmds.add(found);
            }
            found.availableResponseCount++;
            // if a matching remove call has already retrieved this we can remove this
            // instance from our list
            if (found.availableResponseCount == 0) mPendingCmds.remove(found);
        }
        try {
            found.responses.put(response);
        } catch (InterruptedException e) { }
    }

mResponseQueue.add(),通过该方法便能触发ResponseQueue.poll阻塞操作继续往下执行。

到此,MountService与NativeDaemonConnector都已经启动,之前我们看到MountService内部静态类LifeCycle继承自SystemService,那么接下来到系统启动到达阶段PHASE_ACTIVITY_MANAGER_READY,则调用到其onBootPhase方法。

Lifecycle->onBootPhase

// 由SystenServer启动到指定阶段进行回调,其内部由mServices持有
    @Override
    public void onBootPhase(int phase) {
        // 由于MountService的内部Lifecycle已添加SystemServiceManager的mServices服务列表;
        // 系统启动到PHASE_ACTIVITY_MANAGER_READY时会回调mServices中的onBootPhase方法
        if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
            mMountService.systemReady();
        }
    }

由SystemService统一管理其声明流程,之后调用systemReady方法,如下:

systemReady

private void systemReady() {
    mSystemReady = true;
    // 此处 mHandler = new MountServiceHandler(hthread.getLooper())
    // 采用的是线程 ”MountService” 中的 Looper
    // system_server 主线程通过 handler 向线程 ”MountService” 发送 H_SYSTEM_READY 消息
    mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}

MountService的systemReady通过Handler发送消息到MountServiceHandler中进行处理,其收到消息处理后进入handleSystemReady方法

handleSystemReady

private void handleSystemReady() {
    synchronized (mLock) {
        // 重置...
        resetIfReadyAndConnectedLocked();
    }

    // Start scheduling nominally-daily fstrim operations
    // 计划执行日常的 fstrim 操作【】
    MountServiceIdler.scheduleIdlePass(mContext);
}

主要做了两件事情,一件事重置操作,一件事执行fstrim操作。

resetIfReadyAndConnectedLocked

private void resetIfReadyAndConnectedLocked() {
    Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
            + ", mDaemonConnected=" + mDaemonConnected);
    if (mSystemReady && mDaemonConnected) {
        killMediaProvider();

        // Mstar Android Patch Begin
        new Thread() {
            public void run() {
                try {

                    mConnector.execute("volume", "reset");

                    // Tell vold about all existing and started users
                    //告知所有已经存在和启动的 users
                    final UserManager um = mContext.getSystemService(UserManager.class);
                    final List<UserInfo> users = um.getUsers();
                    for (UserInfo user : users) {
                        mConnector.execute("volume", "user_added", user.id, user.serialNumber);
                    }
                    for (int userId : mStartedUsers) {
                        mConnector.execute("volume", "user_started", userId);
                    }
                } catch (NativeDaemonConnectorException e) {
                    Slog.w(TAG, "Failed to reset vold", e);
                }
            }
        }.start();
        // Mstar Android Patch End
    }
}

首先检测系统是否启动完毕,是否和Vold建立连接,之后开启线程通过mConnector执行execute(“volume”, “reset”),并再次通过mConnector告知所有的用户user_added和user_started。

NDC->execute

NativeDaemonConnector执行execute经过层层调用,最终走到executeForList,此时命令执行超时时长为1分钟,具体如下:

public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
        throws NativeDaemonConnectorException {
    final long startTime = SystemClock.elapsedRealtime();

    final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();

    final StringBuilder rawBuilder = new StringBuilder();
    final StringBuilder logBuilder = new StringBuilder();

    // mSequenceNumber初始化值为0,每执行一次该方法则进行加1操作
    final int sequenceNumber = mSequenceNumber.incrementAndGet();

    makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);

    //例如:“7 volume mount”
    final String rawCmd = rawBuilder.toString();
    final String logCmd = logBuilder.toString();

    log("SND -> {" + logCmd + "}");

    synchronized (mDaemonLock) {
        if (mOutputStream == null) {
            throw new NativeDaemonConnectorException("missing output stream");
        } else {
            try {
                //将 cmd 写入到 socket 的输出流
                mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                throw new NativeDaemonConnectorException("problem sending command", e);
            }
        }
    }

    NativeDaemonEvent event = null;
    do {
        event = mResponseQueue.remove(sequenceNumber, timeoutMs, logCmd);
        if (event == null) {
            loge("timed-out waiting for response to " + logCmd);
            throw new NativeDaemonTimeoutException(logCmd, event);
        }
        if (VDBG) log("RMV <- {" + event + "}");
        events.add(event);
        // 当收到的事件响应码属于[100,200)区间,则继续等待后续事件上报
    } while (event.isClassContinue());

    final long endTime = SystemClock.elapsedRealtime();

    //对于执行时间超过500ms则会记录到log
    if (endTime - startTime > WARN_EXECUTE_DELAY_MS) {
        loge("NDC Command {" + logCmd + "} took too long (" + (endTime - startTime) + "ms)");
    }

    if (event.isClassClientError()) {
        throw new NativeDaemonArgumentException(logCmd, event);
    }
    if (event.isClassServerError()) {
        throw new NativeDaemonFailureException(logCmd, event);
    }

    return events.toArray(new NativeDaemonEvent[events.size()]);
}

其流程也是比较重要的,主要是和Socket进行打交道。首先,将带执行的命令mSequenceNumber执行加1操作,再将cmd(例如7 volume mount)写入到socket的输出流,通知Vold进行处理。然后通过循环与poll机制等待执行底层响应该操作结果,否则直到1分钟超时才结束该方法。即便收到底层的响应码,如果响应码属于[100,200)区间,则继续阻塞等待后续事件上报。

mResponseQueue.remove

和上面的add操作相反,这里是将阻塞队列ResponseQueue移除操作,多有操作都是由ReentrantLock同步锁来控制,实现多线程下并发操作。

public NativeDaemonEvent remove(int cmdNum, long timeoutMs, String logCmd) {
    PendingCmd found = null;
    synchronized (mPendingCmds) {
        // 从mPendingCmds查询cmdNum
        for (PendingCmd pendingCmd : mPendingCmds) {
            if (pendingCmd.cmdNum == cmdNum) {
                found = pendingCmd;
                break;
            }
        }

        // 如果已有的mPendingCmds中查询不到,则创建一个新的PendingCmd
        if (found == null) {
            found = new PendingCmd(cmdNum, logCmd);
            mPendingCmds.add(found);
        }
        found.availableResponseCount--;
        // if a matching add call has already retrieved this we can remove this
        // instance from our list
        if (found.availableResponseCount == 0) mPendingCmds.remove(found);
    }
    NativeDaemonEvent result = null;
    try {
        //采用poll轮询方式等待底层上报该事件,直到1分钟超时
        //这里用到poll,先来看看responses
        result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {}
    if (result == null) {
        Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
    }
    return result;
}
  • 关于ArrayBlockingQueue可以参考如下链接:

ArrayBlockingQueue

MountService总结

MountService启动方式和其他的Service有点不同,主要是由其静态内部类LifeCycle控制其实例化过程,然后LifeCycle又继承SystemService,从而其受到SystemService的控制,系统启动到Ready阶段便会回调LifeCycle对应的方法,然后由发送消息到MountService进行处理。

MountService启动时候,自行建立了三个子线程:MountService、VoldConnector、CryptdConnector,其中VoldConnector,CryptdConnector分别对应监听Vold进程中的两个线程,接受他它们传递过来的消息。

其中重要的NativeDaemonConnector负责和Vold传递来的Socket进行通信,其运行在VoldConnector线程中。同理还有一个NDC运行在CryptdConnecto线程中。

部分内容参考如下:

GitYuan

AttayBlockingQueue

坚持原创技术分享,您的支持将鼓励我继续创作!