上一篇讲到通过NetlinkManager发送uevent 命令到NetlinkHandler 的onEvent,代码如下:

void NetlinkHandler::onEvent(NetlinkEvent *evt) {
     VolumeManager *vm = VolumeManager::Instance();
     const  char *subsys = evt->getSubsystem();

     if (!subsys) {
        SLOGW( " No subsystem found in netlink event ");
         return;
    }
    SLOGD( " NetlinkHandler:OnEvent subsys values is %s ",subsys);
     if (!strcmp(subsys,  " block ")) {
        SLOGD( " NetlinkHandler:onEvent ");
         vm->handleBlockEvent(evt);
    }
复制代码

 在NetlinkHandler 里面得一个VolumeManager,当收到的命令为block时调用VolumnManager的handleBlockEvent,如上加红加粗的代码。

handleBlockEvent实则是通过一个循环将事先将main事先读取的配置文件:etc/vold.fstab存进VolumeCollection,得到VolumeCollection的对象,然后调用Volume 的handleBlockEvent,如代码:

void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
     const  char *devpath = evt->findParam( " DEVPATH ");

     /*  Lookup a volume to handle this device  */
    VolumeCollection::iterator it;
     bool hit =  false;
     for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
         if (! (*it)->handleBlockEvent(evt)) {
#ifdef NETLINK_DEBUG
            SLOGD( " Device '%s' event handled by volume %s\n ", devpath, (*it)->getLabel());
#endif
            hit =  true;
             break;
        }
    }

     if (!hit) {
#ifdef NETLINK_DEBUG
        SLOGW( " No volumes handled block event for '%s' ", devpath);
#endif
    } 复制代码

看一下Volume 的handleblockEvent代码:

int Volume::handleBlockEvent(NetlinkEvent *evt) {
    errno = ENOSYS;
     return - 1; 复制代码

 看起来好像没做什么事,其实真的实现在于Volume 的子类,DirectVolume,DirectVolme 中重写了handleBlockEvent,看代码:

int DirectVolume::handleBlockEvent(NetlinkEvent *evt) {
     const  char *dp = evt->findParam( " DEVPATH ");

    PathCollection::iterator  it;
     for (it = mPaths->begin(); it != mPaths->end(); ++it) {
         if (!strncmp(dp, *it, strlen(*it))) {
             /*  We can handle this disk  */
             int action = evt->getAction();
             const  char *devtype = evt->findParam( " DEVTYPE ");

             if (action == NetlinkEvent::NlActionAdd) {
                 int major = atoi(evt->findParam( " MAJOR "));
                 int minor = atoi(evt->findParam( " MINOR "));
                 char nodepath[ 255];

                snprintf(nodepath,
                          sizeof(nodepath),  " /dev/block/vold/%d:%d ",
                         major, minor);
                 if (createDeviceNode(nodepath, major, minor)) {
                    SLOGE( " Error making device node '%s' (%s) ", nodepath,
                                                               strerror(errno));
                }
                 if (!strcmp(devtype,  " disk ")) {
                    handleDiskAdded(dp, evt);
                }  else {
                    handlePartitionAdded(dp, evt);
                }
            }  else  if (action == NetlinkEvent::NlActionRemove) {
                 if (!strcmp(devtype,  " disk ")) {
                     handleDiskRemoved(dp, evt);
                }  else {
                    SLOGD( " DirectVolume:handleBlockEvent--->handlePartitionRemoved ");
                     handlePartitionRemoved(dp, evt);
                }
            }  else  if (action == NetlinkEvent::NlActionChange) {
                 if (!strcmp(devtype,  " disk ")) {
                    handleDiskChanged(dp, evt);
                }  else {
                    handlePartitionChanged(dp, evt);
                }
            }  else {
                    SLOGW( " Ignoring non add/remove/change event ");
            }

             return  0;
        }
    }
    errno = ENODEV;
     return - 1;
复制代码

 

因为我的板子还未完善,所以这里它认为我的sdcard是一个分区,但无关紧要,原理一样,就根据分区的代码跟踪。:handlePartitionRemoved,由于代码过多,只贴出核心代码:

void DirectVolume::handlePartitionRemoved( const  char *devpath, NetlinkEvent *evt) {

  if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) {
         /*
         * Yikes, our mounted partition is going away!
         
*/

        snprintf(msg,  sizeof(msg),  " Volume %s %s bad removal (%d:%d) ",
                 getLabel(), getMountpoint(), major, minor);
        SLOGD( " DirectVolume:(dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev:%d,msg is :%s. ",mCurrentlyMountedKdev,msg);
         mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval,
                                             msg, false);


     if (mVm->cleanupAsec( thistrue)) {
            SLOGE( " Failed to cleanup ASEC - unmount will probably fail! ");
        }

         if ( Volume::unmountVol(truefalse)) {
            SLOGE( " Failed to unmount volume on bad removal (%s) "
                 strerror(errno));
             //  XXX: At this point we're screwed for now
        }  else {
            SLOGD( " Crisis averted ");
        }
    }
复制代码

 

 到此,直接调用父类的unmountVol方法,unmountVol会通过setState通知框架状态改变。代码太多,只推荐核心代码:

int Volume::unmountVol( bool force,  bool revert) {
 setState(Volume::State_Unmounting);
复制代码

 

 而setState会通过socket将msg消息传给框架

mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
                                         msg,  false);  复制代码

接下去的步骤是关于socket的操作,就不深入了。

小结

   到了这一步,Vold 向上层反馈的动作基本己经完成,下一篇文章将会讲解Framework 如何取得Vold 反馈过来的数据。 

 

更多相关文章

  1. Android(安卓)利用canvas画各种图形(点、直线、弧、圆、椭圆、文
  2. Android安装卸载程序具体操作方法解析
  3. Android为菜单添加事件
  4. Android(安卓)SlidingTabLayout+不可手动横向滑动的ViewPager
  5. Android在开机时自动启动一个应用程序
  6. Android(安卓)editText
  7. [android]初始化代码仓库时出现“OSError: [Errno 2] No such fi
  8. android实现截屏功能
  9. Android(安卓)DrawerLayout实现抽屉效果实例代码

随机推荐

  1. android edittext 键盘弹出屏幕自适应
  2. Android(安卓)监听程序的安装、卸载、替
  3. android ComponentName 示例
  4. android 模拟浏览器访问网络
  5. android透明状态栏
  6. Android(安卓)文件工具FileUtil
  7. 登录界面(Android(安卓)studio)
  8. Android(安卓)闹钟以及通知
  9. How Android(安卓)Draws Views
  10. Android_在线视频播放器