Android—— 4.2 Vold掛載管理_mmcblk內建-雙sdcard (八)

來源:互聯網
上載者:User

標籤:sdcard   mount   mmcblock   fatext4   uuid   

      Vold的學習過了一段時間了,才想著把mmcblock內建成sdcard的方法記錄一下。

當初就是因為要做這個功能才去學習Vold機制,貼出之前的部落格:

Android—— 4.2 Vold掛載管理_主體構建main (一)

Android—— 4.2 Vold掛載管理_CommandListener (二)

Android—— 4.2 Vold掛載管理_VolumeManager (三)

Android—— 4.2 Vold掛載管理_NetlinkManager (四)

Android—— 4.2 Vold掛載管理_DirectVolume/Volume (五)

Android—— 4.2 Vold掛載管理_MountService (六) 

Android—— 4.2 Vold掛載管理_Kernel_USB_Uevent (七) 

個人認為把上面的脈絡理清了,Vold應該算是基本掌握了,其中的細節部分就需要另行研究了。



                                                 撰寫不易,轉載請註明出處:http://blog.csdn.net/jscese/article/details/39692953


一.準備:

   不同平台的mmc資料分割配置和燒寫emmc方式不一樣,總之劃分一塊地區用來當sdcard掛載,並且記住block序號,android的分區類型在linux下製作一般都是ext4格式。

可在BoardCondif.mk中添加宏控制:

BOARD_MMCBLK_AS_SDCARD := 13#jscese open mmcblk0p13 as sdcard to mount 140724#

並且在/system/vold/Android.mk 中添加編譯選項:

ifneq ($(BOARD_MMCBLK_AS_SDCARD),)  common_cflags := -DMMCBLK_AS_SDCARD=$(BOARD_MMCBLK_AS_SDCARD)endifLOCAL_CFLAGS := $(common_cflags)


二.Vold掛載:

在/system/vold/VolumeManager.cpp 中的 handleBlockEvent 中添加特殊處理。

核心添加如下:


    const char *devtype = evt->findParam("DEVTYPE");    const char *dn = evt->findParam("DEVNAME");    int major = -1;    int minor = -1;    bool isRawDisk = false;    bool isPartition = false;    int partIdx = -1;    bool isSDCard = false;    major = atoi(evt->findParam("MAJOR"));    minor = atoi(evt->findParam("MINOR")); if (major == 179) {        if (strncmp(dn,"mmcblk0",7) == 0) {//判斷是否為mmc的block#ifndef MMCBLK_AS_SDCARD            return;#endif        }       if (strcmp(dn,"mmcblk0p13") == 0)        SLOGD("jscese display in vm - handle-isSDCard = true\n");        isSDCard = true;    }    snprintf(device,255,"/dev/block/vold/%d:%d",major,minor);  if (strcmp(devtype,"disk") == 0) { //根據裝置類型就行判斷        const char *nparts = evt->findParam("NPARTS");        if (nparts) {            int diskNumParts = atoi(nparts);            isRawDisk = (diskNumParts == 0);        } else {            return ;        }    } else {        const char *tmp = evt->findParam("PARTN");        if (tmp == NULL) {            return;        }        partIdx = atoi(tmp);//        if (strcmp(dn,"mmcblk0p14") == 0)        SLOGD("jscese display in vm - handle- isPartition = true\n");        isPartition = true;    }

以上是對從kernel發過來的event資訊進行一些篩選,下面就需要對device以及Volume進行特殊處理:

  if (isRawDisk || isPartition) {        //first find uuid from cache        UUIDCache::Entry *entry = uuidCache.searchEntry(device); /dev uuid緩衝        if (evt->getAction() == NetlinkEvent::NlActionAdd) {            mode_t mode = 0660 | S_IFBLK;            dev_t dev = (major << 8) | minor;            //if device has been now added, not add again            if (entry != NULL && entry->uuid != NULL) {                return;            }            if (mknod(device, mode, dev) < 0) {//沒有即建立節點                if (errno != EEXIST) {                    return ;                }            }            if (!getVolumeUUID(device, uuid, 255)) {//擷取uuid        #ifdef NETLINK_DEBUG                SLOGD("can not get the uuid of %s when device add",device);        #endif          return;             }      }//Volume容器中添加處理,針對上面的uuid        for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {            if (strcmp(uuid, (*it)->getLabel()) == 0) {         (*it)->handleBlockEvent(evt);          hit = true;       if (evt->getAction() == NetlinkEvent::NlActionAdd) {                    //if device was added at before, so cache its uuid and device path again                    uuidCache.addEntry(device,uuid);                    (*it)->setDevicePath(device);                     }         ...       }   } } if (!hit) {        static char index = 'a'-1;        char * mountPoint = NULL;        const char *dp = NULL;        DirectVolume * volume = NULL;    #ifdef NETLINK_DEBUG        SLOGW("No volumes handled block event for '%s'", devpath);    #endif        if (evt->getAction() != NetlinkEvent::NlActionAdd)        {          return;         }        dp = evt->findParam("DEVPATH");        if (dp == NULL) {            return;        }           SLOGD("jscese display in vm  for 1 mVolumes and isSDCard ==%d, isPartition+=%d \n",isSDCard,isPartition);        /* Determine its mount point */        if (isSDCard) {   //根據上面來的篩選            if (isRawDisk) {                asprintf(&mountPoint,"/mnt/sdcard_external");            } else if (isPartition) {#ifdef MMCBLK_AS_SDCARD                if (partIdx == MMCBLK_AS_SDCARD) { //根據boardconfig中定義的block來設定掛載點                    asprintf(&mountPoint,"/mnt/sdcard");                    SLOGD("jscese display set mountpoint fuck mmcblock %d as sdcard\n",partIdx);                }#else                if (partIdx == 1) { //外部的SD卡掛載點 改為 /mnt/sdcard_external                    asprintf(&mountPoint,"/mnt/sdcard_external");                } else {                    asprintf(&mountPoint,"/mnt/usb/%s",dn);                }#endif            }        }      volume = new DirectVolume(this,uuid,mountPoint,partIdx);        //cache the device path of device        volume->setDevicePath(device);        free(mountPoint);        mVolumesLock.lock();        addVolume(volume);        mVolumesLock.unlock();        //cache the uuid of device        uuidCache.addEntry(device, uuid);        if ( volume->handleBlockEvent(evt) !=0 ) {            SLOGD("New add volume fail to handle the event of %s",devpath);        }     }


UUID的cache介面如下:

static bool getVolumeUUID(const char* path, char* buf, int size) {    blkid_cache cache = NULL;    blkid_dev dev = NULL;    blkid_tag_iterate iter = NULL;    const char *type = NULL, *value = NULL;    bool ret = false;    if (path == NULL || buf == NULL || size < 0) {        return false;    }    if (blkid_get_cache(&cache, NULL) < 0) {        return false;    }    dev = blkid_get_dev(cache, path, BLKID_DEV_NORMAL);    if (dev == NULL) {        return false;    }    iter = blkid_tag_iterate_begin(dev);    while (blkid_tag_next(iter, &type, &value) == 0) {        if (strcmp(type,"UUID") == 0) {            int n = strlen(value);            if (n > size) {                n = size;            }            ret = true;            strncpy(buf,value,n);            buf[n] = '\0';        }    }    blkid_tag_iterate_end(iter);    blkid_put_cache(cache);    return ret;}class UUIDCache {public:    struct Entry {        char *device;        char *uuid;    };    UUIDCache() {        uuidCache = new EntryCollection();    }    ~UUIDCache() {        delete uuidCache;    }    void addEntry(const char *device, const char *uuid) {        Entry *entry = NULL;        if (device == NULL || uuid == NULL) {            return;        }        entry = searchEntry(device);        if (entry == NULL) {            entry = new Entry();            entry->device = strdup(device);            uuidCache->push_back(entry);        } else {            if (entry->uuid != NULL) {                free(entry->uuid);            }        }        entry->uuid = strdup(uuid);    }    Entry *searchEntry(const char *device) {        EntryCollection::iterator it;        for (it = uuidCache->begin(); it != uuidCache->end(); ++it) {            if ((*it)->device != NULL && strcmp((*it)->device, device) == 0) {                return(*it);            }        }        return NULL;    }private:    typedef android::List<Entry *> EntryCollection;    EntryCollection *uuidCache;};static UUIDCache uuidCache;

調入到DirectVolume中,不再做分析,前文有解析。

最後執行到掛載的Volume.cpp中的 mountVol 中。修改添加如下:

  if (primaryStorage) {            // 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;        }        SLOGE("jscese display in Volume-mountVol devicepath==%s , gid ==%d \n",devicePath,gid);        bool isFatFs = true;        bool isNtfsFS = true;        bool isExtFs = true;        if(isFatFs) {             SLOGE("jscese Fat::doMount \n");        if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,                    AID_SYSTEM, gid, 0002, true)) {            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));                isFatFs = false;            } else {                isNtfsFS = false;                isExtFs = false;            }        }/*===jscese add for format mmcblock ext4_type to vfat_type as sdcard 140805=====*/#ifdef MMCBLK_AS_SDCARD        if(!isFatFs)        {            char checkmmcblokPath[255];//            sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]), MINOR(deviceNodes[i]));            sprintf(checkmmcblokPath, "/dev/block/vold/%d:%d", SD_MAJOR,MMCBLK_AS_SDCARD);            SLOGE("jscese Volume::mountvol format checkmmcblockpath= %s,  devicepath==%s , mountpoint==%s\n",checkmmcblokPath,devicePath,getMountpoint());            if(!strcmp("/mnt/sdcard",getMountpoint()))            {                if(!strcmp(checkmmcblokPath,devicePath))                {                    setState(Volume::State_Idle);                    SLOGE("jscese Volume::mountvol format 1 label== %s\n",getLabel());                    if(formatVol()==0)                    {                        setState(Volume::State_Checking);                        SLOGE("jscese Volume::mountvol format over \n");                        if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,                                        AID_SYSTEM, gid, 0002, true))                        {                            SLOGE("%s failed to mount via VFAT 2 (%s)\n", devicePath, strerror(errno));                            isFatFs = false;                        }                        else                        {                            isFatFs=true;                            isNtfsFS = false;                            isExtFs = false;                        }                    }                }            }        }#endif/*===============end================*/

首先進行FAT形式掛載,在系統第一次運行時,因為sdcard的block為ext4格式,肯定是會false返回,這個時候在代碼中將其 formatVol 格式化,再進行FAT形式掛載!

因為我發現,如果以ext4形式掛載的/mnt/sdcard  這時分區中檔案的建立許可權只有建立者 才能有可讀寫權限,並不是根據/mnt/sdcard來規定許可權。

此時各個應用進程在/mnt/sdcard建立的檔案夾,其它使用者就無權訪問了,失去了sdcard應有的價值!

所以這裡要先格式化成FAT,之後的分區中的建立許可權全又掛載點也就是/mnt/sdcard來規定!


上層架構不用改動,這樣就可以實現mmc的一個block內建成sdcard供應用程式使用,同時外部插入的sdcard將被掛載到/mnt/sdcard_external下。





Android—— 4.2 Vold掛載管理_mmcblk內建-雙sdcard (八)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.