android fw systemserver之MountService分析

文章目录

  • 前言
  • 分析
  • 总结
  • 参考

前言

MountService是Android系统中众多systemserver中一员,其工作主要是与native service Vold共同管理Android系统中的磁盘模块。
MountService:Android Binder服务端,运行在system_server进程,用于跟Vold进行消息通信,比如MountService向Vold发送挂载SD卡的命令,或者接收到来自Vold的外设热插拔事件。MountService作为Binder服务端,那么相应的Binder客户端便是StorageManager,通过binder IPC与MountService交互。

分析

和众多service一样,mountservice(后简称MS)在systemserver:startOtherServices中启动

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

try {
	 /*
	 * NotificationManagerService is dependant on MountService,
	* (for media / usb notifications) so we must start MountService first.
	 */
	mSystemServiceManager.startService(MOUNT_SERVICE_CLASS);
	mountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
}

MS由SystemServiceManager(后简称SSM)通过startService启动,那么可知会调用MS中Lifecycle类的onStart方法,先看看这个。

    public static class Lifecycle extends SystemService {
        private MountService mMountService;

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

        @Override
        public void onStart() {
            mMountService = new MountService(getContext());
            publishBinderService("mount", mMountService); //通知注册Binder服务
            mMountService.start();
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mMountService.systemReady();
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                mMountService.bootCompleted();
            }
        }

        @Override
        public void onSwitchUser(int userHandle) {
            mMountService.mCurrentUserId = userHandle;
        }

        @Override
        public void onUnlockUser(int userHandle) {
            mMountService.onUnlockUser(userHandle);
        }

        @Override
        public void onCleanupUser(int userHandle) {
            mMountService.onCleanupUser(userHandle);
        }
    }

Lifecycle 是MS中的内部类,并且继承了SystemService (之前讲过),需要实现一些SystemService 必须要实现的方法。这里我们重点看onStart方法。方法中构建了MS对象,并且发布binder(需要理解binder相关机制)。然后调用了MS的start方法。
看看MS中的start();

    private void start() {
        mConnectorThread.start();
        mCryptConnectorThread.start();
    }

mConnectorThread和mCryptConnectorThread 都是Thread对象,根据名字,可以看到在SystemServer中startService在MS中启动了两个线程,分别是连接线程和Crypt连接线程。
这里的两个线程对象都已经实例过了,应该是在刚刚onStart中的构造里做的。

frameworks/base/services/core/java/com/android/server/MountService.java
    public MountService(Context context) {
        sSelf = this;

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

        //获取PackageManagerService的Client端对象,管理服务
        mPms = (PackageManagerService) ServiceManager.getService("package");

         //创建“MountService”线程,处理消息
        HandlerThread hthread = new HandlerThread(TAG);
        hthread.start();

        //MountService中的消息处理运行在hthread线程中
        mHandler = new MountServiceHandler(hthread.getLooper());

        //IoThread线程名为"android.io",创建OBB操作的handler
        mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
        //判断/data/system/last-fstrim文件,不存在则创建,存在则更新最后修改时间
        File dataDir = Environment.getDataDirectory();        
        File systemDir = new File(dataDir, "system");       
        mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
        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.getDataSystemDirectory(), "storage.xml"));

        synchronized (mLock) {
            readSettingsLocked();
        }
        //将MountServiceInternalImpl登记到sLocalServiceObjects
        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的NativeDaemonConnector对象
        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25, null);
        mConnector.setDebug(true);

        //创建线程名为"VoldConnector"的线程,用于跟vold通信
        mConnector.setWarnIfHeld(mLock);
        mConnectorThread = new Thread(mConnector, VOLD_TAG);

        //创建用于CryptdConnector的NativeDaemonConnector对象
        // Reuse parameters from first connector since they are tested and safe
        mCryptConnector = new NativeDaemonConnector(this, "cryptd",
                MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
        mCryptConnector.setDebug(true);
        //创建线程名为"CryptdConnector"的线程,用于加密
        mCryptConnectorThread = new Thread(mCryptConnector, CRYPTD_TAG);

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

        synchronized (mLock) {
            addInternalVolumeLocked();
        }
        // Add ourself to the Watchdog monitors if enabled.
        //默认为false
        if (WATCHDOG_ENABLE) {
            Watchdog.getInstance().addMonitor(this);
        }

        initMTKFeature();
    }

其中MountService完成的主要任务如下:
1、创建ICallbacks回调方法,FgThread线程名为”android.fg”;
3、创建并启动线程名为”MountService”的handlerThread用来处理消息;
4、创建OBB操作的handler,IoThread线程名为”android.io“;
5、创建NativeDaemonConnector对象;
6、创建并启动线程名为”VoldConnector”的线程;
7、创建并启动线程名为”CryptdConnector”的线程;
8、注册监听用户添加、删除的广播;

到这里,MS的创建和启动已经分析完成,接下来看看它的简要工作模式:

MS在创建启动后是,依靠着system_server主线程和其余三个子线程((VoldConnector, MountService, CryptdConnector)一直勤勤恳恳的工作
这里拿mount流程作个简要分析。
需要mount的信息是由vold native层发来的,那么肯定在MS中需要有一个地方在时刻监听,也就是之前说的socket通讯,这个工作由NativeDaemonConnector完成。
在MS构造中通过NativeDaemonConnector创建了一个连接对象,这个就是用来和Vold通信的,
再看看构造NativeDaemonConnector的详细过程

        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
                null);
        mConnector.setDebug(true);
        mConnector.setWarnIfHeld(mLock);
        mConnectorThread = new Thread(mConnector, VOLD_TAG);

        // Reuse parameters from first connector since they are tested and safe
        mCryptConnector = new NativeDaemonConnector(this, "cryptd",
                MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
        mCryptConnector.setDebug(true);
        mCryptConnectorThread = new Thread(mCryptConnector, CRYPTD_TAG);

注意,这里给NativeDaemonConnector传参的是this,这个this是指什么,我们先看看MS的类声明

class MountService extends IMountService.Stub
        implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {

MS继承了 IMountService.Stub,实现了INativeDaemonConnectorCallbacks等接口。
那么这个this无疑就是它自己了,但它实现了这些接口等信息都包含在里面了,因此在NativeDaemonConnector构造中,可以看看,这个this就是INativeDaemonConnectorCallbacks 类型。

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

    NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
            int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
            Looper looper) {
        mCallbacks = callbacks;
        mSocket = socket;
        mResponseQueue = new ResponseQueue(responseQueueSize);
        mWakeLock = wl;
        if (mWakeLock != null) {
            mWakeLock.setReferenceCounted(true);
        }
        mLooper = looper;
        mSequenceNumber = new AtomicInteger(0);
        TAG = logTag != null ? logTag : "NativeDaemonConnector";
        mLocalLog = new LocalLog(maxLogSize);
    }

接下来看,这个NativeDaemonConnector在MS构造中创建的对象被作为参数传给了mConnectorThread线程做参数,这个mConnectorThread还熟悉吗?刚刚之前提过的,在MS start方法中启动。那这里实际上就是NativeDaemonConnector线程类,应该可以这么叫吧。
启动后,NativeDaemonConnector的run方法也应该跑起来了。

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

        while (true) {
            try {
                listenToSocket();
            } catch (Exception e) {
                loge("Error in NativeDaemonConnector: " + e);
                SystemClock.sleep(5000);
            }
        }
    }

这个run方法中,mCallbackHandler创建了一个Handler对象,可知,这个应该就是处理vold传递来的信息的。而在创建对象后,开启了线程做的事,一个死循环。实现由listenToSocket担当。

//./frameworks/base/services/core/java/com/android/server/NativeDaemonConnector.java
    private void listenToSocket() throws IOException {
        LocalSocket socket = null;

        try {
            //创建Vold socket  
            socket = new LocalSocket();
            LocalSocketAddress address = determineSocketAddress();

            //向服务端发起连接请求
            socket.connect(address);
            //获取连接的socket中得到输入输出流  
            InputStream inputStream = socket.getInputStream();
            synchronized (mDaemonLock) {
                mOutputStream = socket.getOutputStream();
            }

            //对本次连接请求做一些回调处理  
            mCallbacks.onDaemonConnected();
            FileDescriptor[] fdList = null;
            byte[] buffer = new byte[BUFFER_SIZE];
            int start = 0;

            while (true) {
                //从socket输出流中读取数据
                int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
                if (count < 0) {
                    loge("got " + count + " reading with start = " + start);
                    break;
                }
                fdList = socket.getAncillaryFileDescriptors();

                // Add our starting point to the count and reset the start.
                count += start;
                start = 0;
                //解析读取到的数据,得到NativeDaemonEvent  
                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 {
                            final NativeDaemonEvent event =
                                  NativeDaemonEvent.parseRawEvent(rawEvent, fdList);

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

                            //如果命令码code >= 600 && code < 700     
                            if (event.isClassUnsolicited()) {
                                //将读取到的事件发送到VoldConnector.CallbackHandler线程中处理
                                if (mCallbacks.onCheckHoldWakeLock(event.getCode())
                                        && mWakeLock != null) {
                                    mWakeLock.acquire();
                                    releaseWl = true;
                                }                       
                                    Message msg = mCallbackHandler.obtainMessage(
                                        event.getCode(), uptimeMillisInt(), 0, event.getRawEvent());
                                if (mCallbackHandler.sendMessage(msg)) {
                                    releaseWl = false;
                                }
                            } else {     
                                //对于其他响应码则添加到mResponseQueue队列
                                mResponseQueue.add(event.getCmdNumber(), event);
                            }
                        } catch (IllegalArgumentException e) {
                            log("Problem parsing message " + e);
                        } finally {     
                            if (releaseWl) {
                                mWakeLock.release();
                            }
                        }

                        start = i + 1;
                    }
                }
                if (start == 0) {
                    log("RCV incomplete");
                }
          ......
      }                                                              

以上代码中主要完成了两项工作:
(1)当vold返回的响应吗不在区间[600,700),则将该事件添加到mResponseQueue,并且触发响应事件所对应的请求事件不再阻塞到ResponseQueue.poll,那么线程继续往下执行;
(2)当返回的响应码区间为[600,700):则发送消息交由mCallbackHandler处理,向线程android.fg发送Handler消息,该线程收到后回调NativeDaemonConnector的handleMessage来处理。
这里接收消息处理后然后又发送消息给mCallbackHandler处理,那接下来看看mCallbackHandler是如何处理对应的消息。

    @Override
    public boolean handleMessage(Message msg) {
			......
            if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) {
                log(String.format("Unhandled event '%s'", event));
            }
			......
    }

这里省去了大量代码,留下了这句mCallbacks.onEvent,这个mCallbacks是什么,可还记得NativeDaemonConnector构造中曾经从MS中传递进来一个INativeDaemonConnectorCallbacks类型的对象,没错,它在就是NativeDaemonConnector中就是mCallbacks。也就是说这里调用了INativeDaemonConnectorCallbacks对象的onEvent。那么也就是在MS中调用。这样一来,又回到了MS

    //./frameworks/base/services/core/java/com/android/server/MountService.java
    public boolean onEvent(int code, String raw, String[] cooked) {
        synchronized (mLock) {
            return onEventLocked(code, raw, cooked);
        }
    }

    private boolean onEventLocked(int code, String raw, String[] cooked) {
    //处理各种设备挂载等的命令
    ......
        switch (code) {
            case VoldResponseCode.VOLUME_CREATED: {
                final String id = cooked[1];
                final int type = Integer.parseInt(cooked[2]);
                final String diskId = TextUtils.nullIfEmpty(cooked[3]);
                final String partGuid = TextUtils.nullIfEmpty(cooked[4]);

                final DiskInfo disk = mDisks.get(diskId);
                final VolumeInfo vol = new VolumeInfo(id, type, disk, partGuid);
                mVolumes.put(id, vol);
                onVolumeCreatedLocked(vol);
                break;
            }
    ......
    }

这里仅仅留下了VoldResponseCode.VOLUME_CREATED命令的处理。
VoldResponseCode类声明在MS中。说到相关指令的时候,这里提下MS收到vold指令分为两种情况:
(1)当MountService向Vold发送命令后,将接收到Vold的响应消息;
(2)当外部存储设备发生热插拔时,kernel将通过netlink方式通知Vold,Vold进程经过一系列处理后最终还是要将uevent事件消息发送给MountService,Vold发送uevent的过程。

    /*
     * Internal vold response code constants
     */
    class VoldResponseCode {
        /*
         * 100 series - Requestion action was initiated; expect another reply
         *              before proceeding with a new command.
         * 100系列-请求行动已启动; 在继续执行新命令之前,需要其他答复。
         */
        public static final int VolumeListResult               = 110;
        public static final int AsecListResult                 = 111;
        public static final int StorageUsersListResult         = 112;
        public static final int CryptfsGetfieldResult          = 113;

        /*
         * 200 series - Requestion action has been successfully completed.
         * 200系列-请求操作已成功完成。
         */
        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.
         * 400系列-接受命令,但未执行所请求的操作。
         */
        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.
         * 600系列-不请自来的广播。差不多就是kernel通过vold 主动上报的,由NativeDaemonConnector->listenToSocket循环监听的
         */
        public static final int DISK_CREATED = 640;
        public static final int DISK_SIZE_CHANGED = 641;
        public static final int DISK_LABEL_CHANGED = 642;
        public static final int DISK_SCANNED = 643;
        public static final int DISK_SYS_PATH_CHANGED = 644;
        public static final int DISK_DESTROYED = 649;

        public static final int VOLUME_CREATED = 650;
        public static final int VOLUME_STATE_CHANGED = 651;
        public static final int VOLUME_FS_TYPE_CHANGED = 652;
        public static final int VOLUME_FS_UUID_CHANGED = 653;
        public static final int VOLUME_FS_LABEL_CHANGED = 654;
        public static final int VOLUME_PATH_CHANGED = 655;
        public static final int VOLUME_INTERNAL_PATH_CHANGED = 656;
        public static final int VOLUME_DESTROYED = 659;

        public static final int MOVE_STATUS = 660;
        public static final int BENCHMARK_RESULT = 661;
        public static final int TRIM_RESULT = 662;
    }

回到MS->onEventLocked:VOLUME_CREATED 中
最终调用了,onVolumeCreatedLocked方法,执行实际操作。

 private void onVolumeCreatedLocked(VolumeInfo vol) {
		.......
        if (vol.type == VolumeInfo.TYPE_EMULATED) {
			......
            if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
                    && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
				.......
                mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
            } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
          		.......
                mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
            }

        } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
			......
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
        } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
        } else {
            Slog.d(TAG, "Skipping automatic mounting of " + vol);
        }
    }

看起来onVolumeCreatedLocked做了如下的事情:
1.判断是主存储(私有内部)还是公有的存储。
2.不管是哪种,都通过mHandler分发H_VOLUME_MOUNT的消息,这个mHandler是什么?
还记得MS构造中

mHandler = new MountServiceHandler(hthread.getLooper());

此处的mHandler即是MountServiceHandler对象。

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

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
				.......
                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;
                }
  				......
            }
        }
    }

可以看到,MS对H_VOLUME_MOUNT消息的处理,最终是调用了mConnector.execute。mConnector这个应该清楚了吧,它就是NativeDaemonConnector对象,在MS构造中创建的。
这样又回到了NativeDaemonConnector里,真是来来回回,百转千回呀。

frameworks\base\services\core\java\com\android\server\NativeDaemonConnector.java

    public NativeDaemonEvent execute(String cmd, Object... args)
            throws NativeDaemonConnectorException {
        //设置超时时间:DEFAULT_TIMEOUT = 1 * 60 * 1000
        return execute(DEFAULT_TIMEOUT, cmd, args);
    }

    public NativeDaemonEvent execute(long timeoutMs, String cmd, Object... args)
            throws NativeDaemonConnectorException {
        //调用executeForList发送命令
        final NativeDaemonEvent[] events = executeForList(timeoutMs, cmd, args);
        if (events.length != 1) {
            throw new NativeDaemonConnectorException(
                    "Expected exactly one response, but received " + events.length);
        }
        return events[0];
    }

在executeForList中首先判断命令的合法性,并对命令进行处理后写入到socket输出流mOutputStream中。

    public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
            throws NativeDaemonConnectorException {
        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
            loge("Calling thread " + Thread.currentThread().getName() + " is holding 0x"
                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)));
        }
        //获取数据传输的开始时间
        final long startTime = SystemClock.elapsedRealtime();

        final ArrayList 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);

        final String rawCmd = rawBuilder.toString();
        final String logCmd = logBuilder.toString();

        //eg:VoldConnector: SND -> {13 volume unmount public:179,129}
        log("SND -> {" + logCmd + "}");
        synchronized (mDaemonLock) {
            if (mOutputStream == null) {
                throw new NativeDaemonConnectorException("missing output stream");
            } else {
                try {
                    //将命令写入到socket输出流
                    mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
                } catch (IOException e) {
                    throw new NativeDaemonConnectorException("problem sending command", e);
                }
            }
        }

        NativeDaemonEvent event = null;
        do {
            //设置指令接收时间60S,超过60S跳出循环
            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());

        //获取数据传输的结束时间,并判断是否超过WARN_EXECUTE_DELAY_MS=0.5S
        final long endTime = SystemClock.elapsedRealtime();
        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()]);
    }

以上executeForList是MountService指令传输中的重要函数,其重主要完成的任务总结如下:
(1) 带执行的命令mSequenceNumber执行加1操作;
(2) 将cmd写入到socket的输出流;
(3) 通过循环与poll机制阻塞等待底层响应该操作完成的结果;
   有两个情况会跳出循环:
    a、当超过1分钟未收到vold相应事件的响应码,则跳出阻塞等待;
    b、当收到底层的响应码,且响应码不属于[100,200)区间,则跳出循环。
(4)对于执行时间超过500ms的时间,则额外输出以NDC Command开头的log信息。
  MountService向vold发送消息后,便阻塞在MountService线程的NDC.execute()方法,当MonutService接收到vold返回的消息,且消息响应吗不属于区间[600,700)则添加事件到ResponseQueue,从而唤醒阻塞的MountService继续执行。

总结

上面分析过程中,涉及比较多,因为单单断章取义是不太容易把事情讲清理顺的。这里画图做下总结,算是理下思路。
android fw systemserver之MountService分析_第1张图片

参考

Android vold进程三 MountService介绍

你可能感兴趣的:(android)