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,如代碼:socket
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代碼:ide
int Volume::handleBlockEvent(NetlinkEvent *evt) {
errno = ENOSYS;
return -
1;
看起來好像沒作什麼事,其實真的實如今於Volume 的子類,DirectVolume,DirectVolme 中重寫了handleBlockEvent,看代碼:post
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,因爲代碼過多,只貼出核心代碼:this
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(
this,
true)) {
SLOGE(
"
Failed to cleanup ASEC - unmount will probably fail!
");
}
if (
Volume::unmountVol(true, false)) {
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通知框架狀態改變。代碼太多,只推薦核心代碼:spa
int Volume::unmountVol(
bool force,
bool revert) {
setState(Volume::State_Unmounting);
}
而setState會經過socket將msg消息傳給框架code
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
msg,
false);
接下去的步驟是關於socket的操做,就不深刻了。orm
小結
到了這一步,Vold 向上層反饋的動做基本己經完成,下一篇文章將會講解Framework 如何取得Vold 反饋過來的數據。 對象