In the previous android--4.2 Vold Mount Management _volumemanager (iii) in the analysis of Volumemanager is how to extract volume instances and directvolume and volume relationship between the android-- 4.2 Vold Mount Management _netlinkmanager (iv) from the beginning of the kernel call to handleblockevent, here to resolve the Vold mount the real operation, that is, volume operation!
Writing is not easy, reproduced please specify the source: http://blog.csdn.net/jscese/article/details/38736481
I. Directvolume abstraction
SOURCE location:/system/vold/directvolume.cpp, this class is an abstract operation class as a real volume, first look at the construction:
Directvolume::D irectvolume (Volumemanager *vm, const char *label, const char *mount_point, int partidx): Volume (VM, label, Mount_point) {//constructs the parent class instance Mpartidx = partidx;//Record partition index mpaths = new Pathcollection ();//path container for (int i = 0; i < max_partit IONS; i++)//google The default maximum number of partitions is 4 mpartminors[i] = 1; Mpendingpartmap = 0; Mdiskmajor =-1; Mdiskminor =-1; mdisknumparts = 0; SetState (Volume::state_nomedia);//initial set State}
The previous article has resolved to Directvolume handleblockevent:
int directvolume::handleblockevent (netlinkevent *evt) {const char *DP = Evt->findparam ("DEVPATH");//Get Event device path P Athcollection::iterator it; This directvolume path container, which is initialized at build time, adds path for (it = Mpaths->begin () in Volumemanager based on vold.fstab; it! = mpaths-> End (); ++it) {if (!STRNCMP (DP, *it, strlen (*it))) {//Filters the path that matches this event, exits the processing of this directvolume instance if there is no match, and leaves the next dir in Volumemanager Ectvolume to process, and so on/* We can handle this disk */int action = Evt->getaction (); const char *devtype = Evt->findparam ("Devtype"); There are several types of if (action = = Netlinkevent::nlactionadd) {//event type, where single add is added to parse int major = Atoi (Evt->findparam ("MAJ or ")); 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)) {//Create node Sloge ("Error Making Device node '%s ' (%s)", Nodepath, Strerror (errno)); } if (!strcmp (Devtype, "Disk")) {handlediskadded (DP, EVT);//Handle the event of model disk when inserting a mobile device, regardless of How many partitions, first the first event type is disk, collect information about the device, such as the total number of partitions mdisknumparts} else {handlepartitionadded (DP, E VT); Processing partition event information for a device}/* Send notification IFF disk is ready (ie all partitions found) */ if (getState () = = Volume::state_idle) {//through the handle above, the representative is ready Char msg[255]; snprintf (msg, sizeof (msg), "Volume%s%s disk inserted (%d:%d)", Getlabel (), Getmountpoint (), Mdiskmajor, Mdiskminor); Mvm->getbroadcaster ()->sendbroadcast (responsecode::volumediskinserted,//Send broadcast, Called SocketListener's sendbroadcast. MSG, FALSE); } } ... } }}
Node information for the collection partition in handlepartitionadded mpartminors[part_num-1] = minor; and set the state of the Volume to Volume::state_idle , and finally call the Volumemanager instance to send the broadcast
The actual call is SocketListener's sendbroadcast, in android--4.2 vold Mount Management _commandlistener (ii) in the analysis!
void Socketlistener::sendbroadcast (int code, const char *MSG, bool Adderrno) { Pthread_mutex_lock (& Mclientslock); Locking socketclientcollection::iterator i; for (i = Mclients->begin (); I! = Mclients->end (); ++i) {//traverse the client created at SocketListener to send broadcast //broadcasts is Unsolicited and should not include a CMD number if ((*i)->sendmsg (Code, MSG, Adderrno, False)) { SLOGW ("Error s Ending broadcast (%s) ", Strerror (errno)); } } Pthread_mutex_unlock (&mclientslock);}
The sending process source code is located in:/system/core/libsysutils/src/socketclient.cpp Final call to:
int socketclient::senddatalocked (const void *data, int len) { int rc = 0; while (Brtw > 0) { rc = Send (Msocket, p, BRTW, msg_nosignal);
Here the Msocket is the "vold" The socket of the descriptor!
Two. Volume Processing:
In the above Directvolume sent out the broadcast, will go to the upper Mountservice.java, and then through the "vold" socket to Vold, in the SocketListener will be received, in turn, will be called to FrameworkListener.cpp in ondataavailable,dispatchcommand
Then to the runCommandin CommandListener.cpp ,VolumeManager.cpp in the MountVolume android--4.2 Vold Mount Management _commandlistener (ii) in the analysis!
int Volumemanager::mountvolume (const char *label) { Volume *v = lookupvolume (label); if (!v) { errno = ENOENT; return-1; } return V->mountvol (); Call to Volume's Mountvol}
Look at the Volume.cpp:
int Volume::mountvol () {dev_t devicenodes[4]; int n, i, rc = 0; Char errmsg[255]; Const char* externalstorage = getenv ("External_storage"); BOOL Primarystorage = Externalstorage &&!strcmp (Getmountpoint (), externalstorage); Char Decrypt_state[property_value_max]; Char Crypto_state[property_value_max]; Char Encrypt_progress[property_value_max]; int flags; Property_get ("Vold.decrypt", Decrypt_state, ""); Property_get ("Vold.encrypt_progress", Encrypt_progress, ""); /* Don ' t try to mount the volumes if we had not yet entered the disk password * or is in the process of encrypting. */if ((getState () = = Volume::state_nomedia) | | ((!STRCMP (Decrypt_state, "1") | | encrypt_progress[0]) && primarystorage)) {//volume is not in the wrong state or is an encrypted snprintf (errmsg, sizeof (errmsg), "Volume%s%s Mount Failed-no Media", Getlabel (), Getmountpoint ()); Mvm->getbroadcaster ()->sendbroadcast ( Responsecode::volumemountfailednomedia, ErrMsg, F Alse); errno = Enodev; return-1; } else if (GetState ()! = Volume::state_idle) {//normal logic is here, the state of the Volume should be state_idle errno = ebusy; if (getState () = = volume::state_pending) {Mretrymount = true; } return-1; } ... for (i = 0; i < n; i++) {char devicepath[255]; sprintf (DevicePath, "/dev/block/vold/%d:%d", MAJOR (Devicenodes[i]), MINOR (Devicenodes[i])); Slogi ("%s being considered for volume%s\n", DevicePath, Getlabel ()); errno = 0; SetState (volume::state_checking); if (Fat::check (DevicePath)) {//Call fat Check to check if the file system for fat is (errno = = Enodata) {SLOGW ("%s does Not contain a FAT filesystem\n ", DevicePath); Continue } ... if (primarystorage) {//is the specified external storage with a differentGID mount//special case the primary SD card. For this we grant write access to the SDCARD_RW group. GID = AID_SDCARD_RW; } else {//for secondary external storage We keep things locked up. GID = AID_MEDIA_RW; if (Fat::d omount (DevicePath, "/mnt/secure/staging", False, False, FALSE,//This is the real Mount AID for the entire vold. _system, GID, 0702, True) {Sloge ("%s failed to mount via VFAT (%s) \ n", DevicePath, Strerror (errno)); Continue } ... setState (volume::state_mounted); ... }}
State is critical in the entire mount process, and the mount process is managed by state:
Defined in Volume.h:
static const int State_init =-1; static const int State_nomedia = 0; static const int State_idle = 1; static const int state_pending = 2; static const int State_checking = 3; static const int state_mounted = 4; static const int state_unmounting = 5; static const int state_formatting = 6; static const int state_shared = 7; static const int STATE_SHAREDMNT = 8;
At the same time, each state's settings are sent to the upper layer:
void volume::setstate (int state) { char msg[255]; int oldstate = mstate; if (oldstate = = state) { SLOGW ("Duplicate State (%d) \ n", state); return; } if ((oldstate = = volume::state_pending) && (state = Volume::state_idle)) { Mretrymount = false; } Mstate = State; SLOGD ("Volume%s" state changing%d (%s),%d (%s) ", Mlabel, oldstate, Statetostr (oldstate), Mstate, Statetostr (MS Tate)); snprintf (msg, sizeof (msg), "Volume%s%s" state changed from%d (%s) to%d (%s) ", Getlabel (), getmountpoint (), OL Dstate, Statetostr (oldstate), Mstate, statetostr (mstate)); Mvm->getbroadcaster ()->sendbroadcast (Responsecode::volumestatechange, msg, false);}
A simple drawing of a functional flowchart:
This is how Directvolume/volume works, and subsequent analysis interacts with the upper layer of the framework.
android--4.2 Vold Mount Management _directvolume/volume (Fri)