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. FregServer进程,封装进程间通信数据
  2. 按键消息传播流程(WindowManagerService.java)
  3. Android service通信
  4. Android消息机制Message消息池
  5. Android studio 串口通信(动态获取串口)
  6. 进程博客纳入

随机推荐

  1. android wifi
  2. android编程中的琐碎知识点汇总(2)
  3. 【Android(安卓)应用开发】 Android(安卓
  4. Android(安卓)开发问题总结 四
  5. [Android] AsyncTask使用实例---加载网络
  6. 在Android中查看和管理sqlite数据库
  7. Android中launcherMode="singleTask"详解
  8. android 高德地图API 之 java.lang.Unsat
  9. android反编译工具(ApkDec-Release-0.1)-正
  10. Android多媒体框架OpenCore(PacketVideo)介