android 5.0挂载子系统

  1. logcat -s Vold MountService DirectVolume  
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/

  1. public MountService(Context context) {  
  2.   mConnector = new NativeDaemonConnector(this"vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,  
  3.                 null);  //vold的socket,与CommandListener通信  
  4. }  
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

  1. int main() {  
  2.   VolumeManager *vm;  //管理挂载  
  3.   CommandListener *cl;  //与Android的MountService通信  
  4.   NetlinkManager *nm;    //与Linux的Kernel通信  
  5.   cl = new CommandListener();  
  6.   vm->setBroadcaster((SocketListener *) cl); //VolumeManager可以与MountService通信  
  7.   nm->setBroadcaster((SocketListener *) cl); //NetlinkManager可以与MountService通信  
  8. }  
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

  1. void SocketListener::runListener() {  
  2.   if (!onDataAvailable(c)) {  
  3.     release(c, false);  
  4.   }  
  5. }  
  6. /* 
  7. system/core/include/sysutils/NetlinkListener.h 
  8. class NetlinkListener : public SocketListener { 
  9.    
  10. } 
  11. */  
void SocketListener::runListener() {
  if (!onDataAvailable(c)) {
    release(c, false);
  }
}
/*
system/core/include/sysutils/NetlinkListener.h
class NetlinkListener : public SocketListener {
  
}
*/

system/core/libsysutils/src/NetlinkListener.cpp

  1. bool NetlinkListener::onDataAvailable(SocketClient *cli)  
  2. {  
  3.   int socket = cli->getSocket();  
  4.   NetlinkEvent *evt = new NetlinkEvent();  
  5.   if (evt->decode(mBuffer, count, mFormat)) {  
  6.     onEvent(evt);  
  7.   } else if (mFormat != NETLINK_FORMAT_BINARY) {  
  8.       // Don't complain if parseBinaryNetlinkMessage returns false. That can  
  9.       // just mean that the buffer contained no messages we're interested in.  
  10.       SLOGE("Error decoding NetlinkEvent");  
  11.   }  
  12. }  
  13. /* 
  14. system/vold/NetlinkHandler.h 
  15. class NetlinkHandler: public NetlinkListener { 
  16.  
  17.  
  18. } 
  19. */  
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.h
class NetlinkHandler: public NetlinkListener {


}
*/

system/vold/NetlinkHandler.cpp

  1. void NetlinkHandler::onEvent(NetlinkEvent *evt) {  
  2.     VolumeManager *vm = VolumeManager::Instance();  
  3.     const char *subsys = evt->getSubsystem();  
  4.   
  5.   
  6.     if (!subsys) {  
  7.         SLOGW("No subsystem found in netlink event");  
  8.         return;  
  9.     }  
  10.   
  11.   
  12.     if (!strcmp(subsys, "block")) {  
  13.         vm->handleBlockEvent(evt);  
  14.     }else if(!strcmp(subsys, "usb")) {  
  15.         vm->handleHidEvent(evt);  
  16.     }  
  17. }  
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

  1. void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {  
  2.   for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {  
  3.     (*it)->handleBlockEvent(evt);  
  4.   }  
  5.   volume = new DirectVolume(this, &rec, flags);  
  6.   addVolume(volume);  
  7.   if ( volume->handleBlockEvent(evt) !=0 ) {  
  8.     SLOGD("New add volume fail to handle the event of %s",devpath);  
  9.   }  
  10. }  
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

  1. int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {  
  2.   handleDiskAdded(dp, evt);  
  3. }  
  4. void DirectVolume::handleDiskAdded(const char * /*devpath*/,  
  5.                                    NetlinkEvent *evt) {  
  6.   mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,  
  7.                                              msg, false);  
  8. }  
  9. /* 
  10. system/vold/DirectVolume.h 
  11. class DirectVolume : public Volume { 
  12.  VolumeManager *mVm; 
  13. } 
  14. */  
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.h
class DirectVolume : public Volume {
 VolumeManager *mVm;
}
*/

system/vold/VolumeManager.h

  1. class VolumeManager {  
  2.   void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }  
  3.   /* 
  4.   system/vold/main.cpp 
  5.   int main() { 
  6.     VolumeManager *vm; 
  7.     CommandListener *cl; 
  8.     NetlinkManager *nm; 
  9.     cl = new CommandListener(); 
  10.     vm->setBroadcaster((SocketListener *) cl); 
  11.     nm->setBroadcaster((SocketListener *) cl); 
  12.   } 
  13.   */  
  14.   SocketListener *getBroadcaster() { return mBroadcaster; }  
  15. }  
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

  1. class CommandListener : public FrameworkListener {  
  2.     
  3. }  
  4. /* 
  5. system/core/include/sysutils/FrameworkListener.h 
  6. class FrameworkListener : public SocketListener { 
  7.  
  8.  
  9. } 
  10. */  
class CommandListener : public FrameworkListener {
  
}
/*
system/core/include/sysutils/FrameworkListener.h
class FrameworkListener : public SocketListener {


}
*/

system/core/libsysutils/src/SocketListener.cpp

  1. void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {  
  2.   if (c->sendMsg(code, msg, addErrno, false)) {  
  3.     SLOGW("Error sending broadcast (%s)", strerror(errno));  
  4.   }  
  5. }  
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

  1. public boolean onEvent(int code, String raw, String[] cooked) {  
  2.   if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {  
  3.     Slog.w(TAG, String.format("Insertion mount failed (%d)", rc));  
  4.   }  
  5. }  
  6. private int doMountVolume(String path) {  
  7.   mConnector.execute("volume""mount", path);  
  8.   /* 
  9.   mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25, 
  10.                 null); 
  11.   */  
  12. }  
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

  1. public NativeDaemonEvent execute(String cmd, Object... args)  
  2.             throws NativeDaemonConnectorException {  
  3.   final NativeDaemonEvent[] events = executeForList(cmd, args);  
  4. }  
  5. public NativeDaemonEvent[] executeForList(String cmd, Object... args)  
  6.             throws NativeDaemonConnectorException {  
  7.   return execute(DEFAULT_TIMEOUT, cmd, args);  
  8. }  
  9. public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)  
  10.            throws NativeDaemonConnectorException {  
  11.   NativeDaemonEvent event = null;  
  12.   events.add(event);  
  13. }  
  14. public void add(int cmdNum, NativeDaemonEvent response) {  
  15.   found = new PendingCmd(cmdNum, null);  
  16.   mPendingCmds.add(found);  
  17. }  
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

  1. void SocketListener::runListener() {  
  2.   if (!onDataAvailable(c)) {  
  3.     release(c, false);  
  4.   }  
  5. }  
void SocketListener::runListener() {
  if (!onDataAvailable(c)) {
    release(c, false);
  }
}

system/core/libsysutils/src/FrameworkListener.cpp

  1. bool FrameworkListener::onDataAvailable(SocketClient *c) {  
  2.   dispatchCommand(c, buffer + offset);  
  3. }  
  4. void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {  
  5.   for (i = mCommands->begin(); i != mCommands->end(); ++i) {  
  6.     FrameworkCommand *c = *i;  
  7.     /* 
  8.     void FrameworkListener::registerCmd(FrameworkCommand *cmd) { 
  9.       mCommands->push_back(cmd); 
  10.     } 
  11.     system/core/include/sysutils/FrameworkListener.h 
  12.     class FrameworkListener : public SocketListener { 
  13.  
  14.  
  15.     } 
  16.     system/vold/CommandListener.h 
  17.     class CommandListener : public FrameworkListener { 
  18.    
  19.     } 
  20.     system/vold/CommandListener.cpp 
  21.     CommandListener::CommandListener() : 
  22.                  FrameworkListener("vold", true) { 
  23.       registerCmd(new DumpCmd()); 
  24.       registerCmd(new VolumeCmd());  //volume的mount命令 
  25.       registerCmd(new AsecCmd()); 
  26.       registerCmd(new ObbCmd()); 
  27.     } 
  28.     */  
  29.     if (c->runCommand(cli, argc, argv)) {  
  30.       SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));  
  31.     }  
  32.   }  
  33. }  
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

  1. int CommandListener::VolumeCmd::runCommand(SocketClient *cli,  
  2.                                            int argc, char **argv) {  
  3.   VolumeManager *vm = VolumeManager::Instance();  
  4.   else if (!strcmp(argv[1], "mount")) {  
  5.     rc = vm->mountVolume(argv[2]);  
  6.   }  
  7. }  
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

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

/system/vold/Volume.cpp

  1. int Volume::mountVol() {  
  2.   if (isNtfsFS) {  
  3.     if (Ntfs::doMount(devicePath, getMountpoint(), falsefalse, AID_MEDIA_RW, AID_MEDIA_RW, permMask)) { //实际调用Linux系统调用挂载  
  4.       SLOGE("%s failed to mount via NTFS (%s)\n", devicePath, strerror(errno));  
  5.       isNtfsFS = false;  
  6.     } else {  
  7.       isFatFs = false;  
  8.       isExtFs = false;  
  9.       isExfatFs = false;  
  10.     }  
  11.   }  
  12.   setState(Volume::State_Mounted);  
  13. }  
  14. void Volume::setState(int state) {  
  15.   mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,  
  16.                                          msg, false); //同之前消息发送,不做分析;MountServer会收到VolumeStateChange消息  
  17. }  
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

  1. public boolean onEvent(int code, String raw, String[] cooked) {  
  2.   if (code == VoldResponseCode.VolumeStateChange) {  
  3.     notifyVolumeStateChange(  
  4.                     cooked[2], cooked[3], Integer.parseInt(cooked[7]),  
  5.                             Integer.parseInt(cooked[10]));  
  6.   }  
  7. }  
  8. private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {  
  9.   else if (newState == VolumeState.Mounted) {  
  10.     if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state mounted");  
  11.     updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED); //广播通知应用挂载完毕  
  12.     action = Intent.ACTION_MEDIA_MOUNTED;  
  13.   }  
  14.   if (action != null) {  
  15.     sendStorageIntent(action, volume, UserHandle.ALL);  
  16.   }  
  17. }  
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为只读问题




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值