logcat -s Vold MountService DirectVolume

虚拟SD卡相关:

Android虚拟SD卡

一、启动过程分析

1.应用程序API

frameworks/base/core/java/android/os/storage/StorageManager.java

2.MountService

frameworks/base/services/core/java/com/android/server/MountService.java

frameworks/base/services/core/java/com/android/server/storage/

public MountService(Context context) {  mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,                null);  //vold的socket,与CommandListener通信}
3.vold进程

system/vold/main.cpp

int main() {  VolumeManager *vm;  //管理挂载  CommandListener *cl;  //与Android的MountService通信  NetlinkManager *nm;    //与Linux的Kernel通信  cl = new CommandListener();  vm->setBroadcaster((SocketListener *) cl); //VolumeManager可以与MountService通信  nm->setBroadcaster((SocketListener *) cl); //NetlinkManager可以与MountService通信}
二、U盘挂载分析

1.vold进程获取内核U盘接入事件

system/core/libsysutils/src/SocketListener.cpp

void SocketListener::runListener() {  if (!onDataAvailable(c)) {    release(c, false);  }}/*system/core/include/sysutils/NetlinkListener.hclass NetlinkListener : public SocketListener {  }*/

system/core/libsysutils/src/NetlinkListener.cpp

bool NetlinkListener::onDataAvailable(SocketClient *cli){  int socket = cli->getSocket();  NetlinkEvent *evt = new NetlinkEvent();  if (evt->decode(mBuffer, count, mFormat)) {    onEvent(evt);  } else if (mFormat != NETLINK_FORMAT_BINARY) {      // Don't complain if parseBinaryNetlinkMessage returns false. That can      // just mean that the buffer contained no messages we're interested in.      SLOGE("Error decoding NetlinkEvent");  }}/*system/vold/NetlinkHandler.hclass NetlinkHandler: public NetlinkListener {}*/

system/vold/NetlinkHandler.cpp

void NetlinkHandler::onEvent(NetlinkEvent *evt) {    VolumeManager *vm = VolumeManager::Instance();    const char *subsys = evt->getSubsystem();    if (!subsys) {        SLOGW("No subsystem found in netlink event");        return;    }    if (!strcmp(subsys, "block")) {        vm->handleBlockEvent(evt);    }else if(!strcmp(subsys, "usb")) {        vm->handleHidEvent(evt);    }}

system/vold/VolumeManager.cpp

void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {  for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {    (*it)->handleBlockEvent(evt);  }  volume = new DirectVolume(this, &rec, flags);  addVolume(volume);  if ( volume->handleBlockEvent(evt) !=0 ) {    SLOGD("New add volume fail to handle the event of %s",devpath);  }}

2.向Android的MountServer发送U盘接入消息

system/vold/DirectVolume.cpp

int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {  handleDiskAdded(dp, evt);}void DirectVolume::handleDiskAdded(const char * /*devpath*/,                                   NetlinkEvent *evt) {  mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,                                             msg, false);}/*system/vold/DirectVolume.hclass DirectVolume : public Volume { VolumeManager *mVm;}*/

system/vold/VolumeManager.h

class VolumeManager {  void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }  /*  system/vold/main.cpp  int main() {    VolumeManager *vm;    CommandListener *cl;    NetlinkManager *nm;    cl = new CommandListener();    vm->setBroadcaster((SocketListener *) cl);    nm->setBroadcaster((SocketListener *) cl);  }  */  SocketListener *getBroadcaster() { return mBroadcaster; }}

system/vold/CommandListener.h

class CommandListener : public FrameworkListener {  }/*system/core/include/sysutils/FrameworkListener.hclass FrameworkListener : public SocketListener {}*/

system/core/libsysutils/src/SocketListener.cpp

void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {  if (c->sendMsg(code, msg, addErrno, false)) {    SLOGW("Error sending broadcast (%s)", strerror(errno));  }}

3.Android的MountServer接收到VolumeDiskInserted消息后处理

frameworks/base/services/core/java/com/android/server/MountService.java

public boolean onEvent(int code, String raw, String[] cooked) {  if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {    Slog.w(TAG, String.format("Insertion mount failed (%d)", rc));  }}private int doMountVolume(String path) {  mConnector.execute("volume", "mount", path);  /*  mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,                null);  */}

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

public NativeDaemonEvent execute(String cmd, Object... args)            throws NativeDaemonConnectorException {  final NativeDaemonEvent[] events = executeForList(cmd, args);}public NativeDaemonEvent[] executeForList(String cmd, Object... args)            throws NativeDaemonConnectorException {  return execute(DEFAULT_TIMEOUT, cmd, args);}public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)           throws NativeDaemonConnectorException {  NativeDaemonEvent event = null;  events.add(event);}public void add(int cmdNum, NativeDaemonEvent response) {  found = new PendingCmd(cmdNum, null);  mPendingCmds.add(found);}

4.vold进程接收Android的MountServer进程的volume的mount命令

system/core/libsysutils/src/SocketListener.cpp

void SocketListener::runListener() {  if (!onDataAvailable(c)) {    release(c, false);  }}

system/core/libsysutils/src/FrameworkListener.cpp

bool FrameworkListener::onDataAvailable(SocketClient *c) {  dispatchCommand(c, buffer + offset);}void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {  for (i = mCommands->begin(); i != mCommands->end(); ++i) {    FrameworkCommand *c = *i;    /*    void FrameworkListener::registerCmd(FrameworkCommand *cmd) {      mCommands->push_back(cmd);    }    system/core/include/sysutils/FrameworkListener.h    class FrameworkListener : public SocketListener {    }    system/vold/CommandListener.h    class CommandListener : public FrameworkListener {      }    system/vold/CommandListener.cpp    CommandListener::CommandListener() :                 FrameworkListener("vold", true) {      registerCmd(new DumpCmd());      registerCmd(new VolumeCmd());  //volume的mount命令      registerCmd(new AsecCmd());      registerCmd(new ObbCmd());    }    */    if (c->runCommand(cli, argc, argv)) {      SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));    }  }}

system/vold/CommandListener.cpp

int CommandListener::VolumeCmd::runCommand(SocketClient *cli,                                           int argc, char **argv) {  VolumeManager *vm = VolumeManager::Instance();  else if (!strcmp(argv[1], "mount")) {    rc = vm->mountVolume(argv[2]);  }}

system/vold/VolumeManager.cpp

int VolumeManager::mountVolume(const char *label) {  Volume *v = lookupVolume(label);  return v->mountVol();}

/system/vold/Volume.cpp

int Volume::mountVol() {  if (isNtfsFS) {    if (Ntfs::doMount(devicePath, getMountpoint(), false, false, AID_MEDIA_RW, AID_MEDIA_RW, permMask)) { //实际调用Linux系统调用挂载      SLOGE("%s failed to mount via NTFS (%s)\n", devicePath, strerror(errno));      isNtfsFS = false;    } else {      isFatFs = false;      isExtFs = false;      isExfatFs = false;    }  }  setState(Volume::State_Mounted);}void Volume::setState(int state) {  mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,                                         msg, false); //同之前消息发送,不做分析;MountServer会收到VolumeStateChange消息}

5.Android的MountServer收到VolumeStateChange消息通知应用

frameworks/base/services/core/java/com/android/server/MountService.java

public boolean onEvent(int code, String raw, String[] cooked) {  if (code == VoldResponseCode.VolumeStateChange) {    notifyVolumeStateChange(                    cooked[2], cooked[3], Integer.parseInt(cooked[7]),                            Integer.parseInt(cooked[10]));  }}private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {  else if (newState == VolumeState.Mounted) {    if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state mounted");    updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED); //广播通知应用挂载完毕    action = Intent.ACTION_MEDIA_MOUNTED;  }  if (action != null) {    sendStorageIntent(action, volume, UserHandle.ALL);  }}

三、项目问题

Android下开机启动后U盘经常不能自动挂载

Android媒体应用下不能将两个U盘间文件复制

Android5.0挂载NTFS为只读问题




更多相关文章

  1. Android(安卓)trouble shooting 整理
  2. Android开机自启动
  3. 浅析Android中的消息机制
  4. 浅析Android中的消息机制
  5. android 实现类似Iphone底部消息数量提示
  6. QT Creator 构建android apk失败问题
  7. FregServer进程,封装进程间通信数据
  8. 按键消息传播流程(WindowManagerService.java)
  9. Android开机自启动

随机推荐

  1. DB Usage Complete / ADB 用法大全(转自g
  2. Android调用平台功能具体技巧分享
  3. [Android1.6]动态添加View的问题
  4. Android Studio 1.3 正式发布
  5. Android ADK 编程简介
  6. Android(安卓)for OpenCV 调用 CameraAPI
  7. Android多渠道打包以及发布方法
  8. 写android程序碰到的一些记录
  9. Android(安卓)插件化 动态升级
  10. Android 系统中使用GDB调试C程序