The previous http://www.bkjia.com/kf/201203/124631.html talked about sending the uevent command to the onEvent of NetlinkHandler through NetlinkManager. The Code is as follows:
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 );
}
}
In NetlinkHandler, A VolumeManager is obtained. When the command received is block, the handleBlockEvent of VolumnManager is called. The above code is highlighted in red and bold.
HandleBlockEvent stores the configuration file "etc/vold. fstab" read in advance by using a loop to obtain the VolumeCollection object, and then calls the handleBlockEvent of Volume, such as the Code:
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
}
Let's take a look at the Volume handleblockEvent code:
Int Volume: handleBlockEvent (NetlinkEvent * evt ){
Errno = ENOSYS;
Return-1;
It seems that nothing is done. In fact, the actual implementation lies in the sub-class of Volume. DirectVolume and DirectVolme re-wrote handleBlockEvent and read the code:
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;
}
Because my board is not complete yet, it thinks that my sdcard is a partition, but it doesn't matter. In the same principle, it tracks the code of the partition. : HandlePartitionRemoved: because there are too many codes, only the core code is pasted:
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 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 re screwed for now
} Else {
SLOGD ("Crisis averted ");
}
}
}
At this point, the unmountVol method of the parent class is called directly, and unmountVol notifies the framework of state change through setState. Too many codes. Only core code is recommended:
Int Volume: unmountVol (bool force, bool revert ){
SetState (Volume: State_Unmounting );
}
SetState transmits the msg message to the framework through socket.
MVm-> getBroadcaster ()-> sendBroadcast (ResponseCode: VolumeStateChange,
Msg, false );
The next step is about socket operations.
Summary
At this point, the action of Vold feedback to the upstream layer has basically been completed. The next article will explain how the Framework obtains the data from Vold feedback.
From Terry _ Dragon