/** * Get information on a user interface element for documentation. * * @param[in] path The UI full pathname to parse. * @param[out] label The place to store the UI name. * @param[out] unit The place to store the UI unit. */ void DocCompiler::getUIDocInfos(Tree path, string& label, string& unit) { label = ""; unit = ""; map<string, set<string>> metadata; extractMetadata(tree2str(hd(path)), label, metadata); set<string> myunits = metadata["unit"]; // for (set<string>::iterator i = myunits.begin(); i != myunits.end(); i++) { // cerr << "Documentator : getUIDocInfos : metadata[\"unit\"] = " << *i << endl; // } for(map<string, set<string>>::iterator i = metadata.begin(); i != metadata.end(); i++) { const string& key = i->first; const set<string>& values = i->second; for(set<string>::const_iterator j = values.begin(); j != values.end(); j++) { if(key == "unit") unit += *j; } } }
/** * removes enclosing quotes and transforms '<', '>' and '&' characters */ static string xmlize(const string& fullsrc) { map<string, set<string>> metadata; string dst; string src; extractMetadata(fullsrc, src, metadata); for(size_t i = 0; i < src.size(); i++) { if(src[i] == '"' & (i == 0 | i == src.size() - 1)) { // nothing to do just skip the quotes } else { switch(src[i]) { case '<': dst += "<"; break; case '>': dst += ">"; break; case '&': dst += "&"; break; default: dst += src[i]; } } } return dst; }
string extractName(Tree fulllabel) { string name; map<string, set<string>> metadata; extractMetadata(tree2str(fulllabel), name, metadata); return name; }
/** * Generate buildUserInterface C++ lines of code corresponding * to user interface element t */ void Compiler::generateUserInterfaceTree(Tree t) { Tree label, elements, varname, sig; if (isUiFolder(t, label, elements)) { const int orient = tree2int(left(label)); // Empty labels will be renamed with a 0xABCD (address) kind of name that is ignored and not displayed by UI architectures const char* str = tree2str(right(label)); const char* model; // extract metadata from group label str resulting in a simplifiedLabel // and metadata declarations for fictive zone at address 0 string simplifiedLabel; map<string, set<string> > metadata; extractMetadata(str, simplifiedLabel, metadata); // add metadata if any for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) { const string& key = i->first; const set<string>& values = i->second; for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) { fClass->addUICode(subst("interface->declare($0, \"$1\", \"$2\");", "0", wdel(key) ,wdel(*j))); fJSON.declare(NULL, wdel(key).c_str(), wdel(*j).c_str()); } } //----------------- switch (orient) { case 0 : model = "interface->openVerticalBox(\"$0\");"; fJSON.openVerticalBox(checkNullLabel(t, simplifiedLabel).c_str()); break; case 1 : model = "interface->openHorizontalBox(\"$0\");"; fJSON.openHorizontalBox(checkNullLabel(t, simplifiedLabel).c_str()); break; case 2 : model = "interface->openTabBox(\"$0\");"; fJSON.openTabBox(checkNullLabel(t, simplifiedLabel).c_str()); break; default : fprintf(stderr, "error in user interface generation 1\n"); exit(1); } fClass->addUICode(subst(model, checkNullLabel(t, simplifiedLabel))); generateUserInterfaceElements(elements); fClass->addUICode("interface->closeBox();"); fJSON.closeBox(); } else if (isUiWidget(t, label, varname, sig)) { generateWidgetCode(label, varname, sig); } else { fprintf(stderr, "error in user interface generation 2\n"); exit(1); } }
std::unique_ptr<DecodedImage> decodeWebpFromInputStream( JNIEnv* env, jobject is, PixelFormat pixel_format) { // get image into decoded heap auto encoded_image = readStreamFully(env, is); RETURNVAL_IF_EXCEPTION_PENDING({}); // extract metadata auto metadata = extractMetadata(env, encoded_image); RETURNVAL_IF_EXCEPTION_PENDING({}); // get pixels int image_width = 0; int image_height = 0; uint8_t* raw_pixels = nullptr; switch (pixel_format) { case PixelFormat::RGB: raw_pixels = WebPDecodeRGB( encoded_image.data(), encoded_image.size(), &image_width, &image_height); break; case PixelFormat::RGBA: raw_pixels = WebPDecodeRGBA( encoded_image.data(), encoded_image.size(), &image_width, &image_height); break; default: THROW_AND_RETURNVAL_IF(true, "unrecognized pixel format", {}); } auto pixels = pixels_t{raw_pixels, (void(*)(uint8_t*)) &free}; return std::unique_ptr<DecodedImage>{ new DecodedImage{ std::move(pixels), pixel_format, (unsigned int) image_width, (unsigned int) image_height, std::move(metadata)}}; }
/** * Generate user interface macros corresponding * to a user interface widget */ void Compiler::generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig) { Tree path, c, x, y, z; string label; map<string, set<string> > metadata; extractMetadata(tree2str(fulllabel), label, metadata); //string pathlabel = pathname+unquote(label); string pathlabel = pathname+label; if ( isSigButton(sig, path) ) { fClass->addUIMacro(subst("FAUST_ADDBUTTON(\"$0\", $1);", pathlabel, tree2str(varname))); } else if ( isSigCheckbox(sig, path) ) { fClass->addUIMacro(subst("FAUST_ADDCHECKBOX(\"$0\", $1);", pathlabel, tree2str(varname))); } else if ( isSigVSlider(sig, path,c,x,y,z) ) { fClass->addUIMacro(subst("FAUST_ADDVERTICALSLIDER(\"$0\", $1, $2, $3, $4, $5);", pathlabel, tree2str(varname), T(tree2float(c)), T(tree2float(x)), T(tree2float(y)), T(tree2float(z)))); } else if ( isSigHSlider(sig, path,c,x,y,z) ) { fClass->addUIMacro(subst("FAUST_ADDHORIZONTALSLIDER(\"$0\", $1, $2, $3, $4, $5);", pathlabel, tree2str(varname), T(tree2float(c)), T(tree2float(x)), T(tree2float(y)), T(tree2float(z)))); } else if ( isSigNumEntry(sig, path,c,x,y,z) ) { fClass->addUIMacro(subst("FAUST_ADDNUMENTRY(\"$0\", $1, $2, $3, $4, $5);", pathlabel, tree2str(varname), T(tree2float(c)), T(tree2float(x)), T(tree2float(y)), T(tree2float(z)))); } else if ( isSigVBargraph(sig, path,x,y,z) ) { fClass->addUIMacro(subst("FAUST_ADDVERTICALBARGRAPH(\"$0\", $1, $2, $3);", pathlabel, tree2str(varname), T(tree2float(x)), T(tree2float(y)))); } else if ( isSigHBargraph(sig, path,x,y,z) ) { fClass->addUIMacro(subst("FAUST_ADDHORIZONTALBARGRAPH(\"$0\", $1, $2, $3);", pathlabel, tree2str(varname), T(tree2float(x)), T(tree2float(y)))); } else { fprintf(stderr, "Error in generating widget code\n"); exit(1); } }
/** * Generate buildUserInterface C++ lines of code corresponding * to user interface widget t */ void Compiler::generateWidgetCode(Tree fulllabel, Tree varname, Tree sig) { Tree path, c, x, y, z; string label; map<string, set<string> > metadata; extractMetadata(tree2str(fulllabel), label, metadata); // add metadata if any for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) { const string& key = i->first; const set<string>& values = i->second; for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) { fClass->addUICode(subst("interface->declare(&$0, \"$1\", \"$2\");", tree2str(varname), wdel(key), wdel(*j))); fJSON.declare(NULL, wdel(key).c_str(), wdel(*j).c_str()); } } if ( isSigButton(sig, path) ) { fClass->incUIActiveCount(); fClass->addUICode(subst("interface->addButton(\"$0\", &$1);", checkNullLabel(varname, label), tree2str(varname))); fJSON.addButton(checkNullLabel(varname, label).c_str(), NULL); } else if ( isSigCheckbox(sig, path) ) { fClass->incUIActiveCount(); fClass->addUICode(subst("interface->addCheckButton(\"$0\", &$1);", checkNullLabel(varname, label), tree2str(varname))); fJSON.addCheckButton(checkNullLabel(varname, label).c_str(), NULL); } else if ( isSigVSlider(sig, path,c,x,y,z) ) { fClass->incUIActiveCount(); fClass->addUICode(subst("interface->addVerticalSlider(\"$0\", &$1, $2, $3, $4, $5);", checkNullLabel(varname, label), tree2str(varname), T(tree2float(c)), T(tree2float(x)), T(tree2float(y)), T(tree2float(z)))); fJSON.addVerticalSlider(checkNullLabel(varname, label).c_str(), NULL, tree2float(c), tree2float(x), tree2float(y), tree2float(z)); } else if ( isSigHSlider(sig, path,c,x,y,z) ) { fClass->incUIActiveCount(); fClass->addUICode(subst("interface->addHorizontalSlider(\"$0\", &$1, $2, $3, $4, $5);", checkNullLabel(varname, label), tree2str(varname), T(tree2float(c)), T(tree2float(x)), T(tree2float(y)), T(tree2float(z)))); fJSON.addHorizontalSlider(checkNullLabel(varname, label).c_str(), NULL, tree2float(c), tree2float(x), tree2float(y), tree2float(z)); } else if ( isSigNumEntry(sig, path,c,x,y,z) ) { fClass->incUIActiveCount(); fClass->addUICode(subst("interface->addNumEntry(\"$0\", &$1, $2, $3, $4, $5);", checkNullLabel(varname, label), tree2str(varname), T(tree2float(c)), T(tree2float(x)), T(tree2float(y)), T(tree2float(z)))); fJSON.addNumEntry(checkNullLabel(varname, label).c_str(), NULL, tree2float(c), tree2float(x), tree2float(y), tree2float(z)); } else if ( isSigVBargraph(sig, path,x,y,z) ) { fClass->incUIPassiveCount(); fClass->addUICode(subst("interface->addVerticalBargraph(\"$0\", &$1, $2, $3);", checkNullLabel(varname, label, true), tree2str(varname), T(tree2float(x)), T(tree2float(y)))); fJSON.addVerticalBargraph(checkNullLabel(varname, label).c_str(), NULL, tree2float(x), tree2float(y)); } else if ( isSigHBargraph(sig, path,x,y,z) ) { fClass->incUIPassiveCount(); fClass->addUICode(subst("interface->addHorizontalBargraph(\"$0\", &$1, $2, $3);", checkNullLabel(varname, label, true), tree2str(varname), T(tree2float(x)), T(tree2float(y)))); fJSON.addHorizontalBargraph(checkNullLabel(varname, label).c_str(), NULL, tree2float(x), tree2float(y)); } else { fprintf(stderr, "Error in generating widget code\n"); exit(1); } }
status_t BnMediaMetadataRetriever::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case DISCONNECT: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); disconnect(); return NO_ERROR; } break; case SET_DATA_SOURCE_URL: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); sp<IMediaHTTPService> httpService; if (data.readInt32()) { httpService = interface_cast<IMediaHTTPService>(data.readStrongBinder()); } const char* srcUrl = data.readCString(); KeyedVector<String8, String8> headers; size_t numHeaders = (size_t) data.readInt64(); for (size_t i = 0; i < numHeaders; ++i) { String8 key = data.readString8(); String8 value = data.readString8(); headers.add(key, value); } reply->writeInt32( setDataSource( httpService, srcUrl, numHeaders > 0 ? &headers : NULL)); return NO_ERROR; } break; case SET_DATA_SOURCE_FD: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); int fd = data.readFileDescriptor(); int64_t offset = data.readInt64(); int64_t length = data.readInt64(); reply->writeInt32(setDataSource(fd, offset, length)); return NO_ERROR; } break; case SET_DATA_SOURCE_CALLBACK: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); sp<IDataSource> source = interface_cast<IDataSource>(data.readStrongBinder()); reply->writeInt32(setDataSource(source)); return NO_ERROR; } break; case GET_FRAME_AT_TIME: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); int64_t timeUs = data.readInt64(); int option = data.readInt32(); ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif sp<IMemory> bitmap = getFrameAtTime(timeUs, option); if (bitmap != 0) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeStrongBinder(IInterface::asBinder(bitmap)); } else { reply->writeInt32(UNKNOWN_ERROR); } #ifndef DISABLE_GROUP_SCHEDULE_HACK restoreSchedPolicy(); #endif return NO_ERROR; } break; case EXTRACT_ALBUM_ART: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif sp<IMemory> albumArt = extractAlbumArt(); if (albumArt != 0) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeStrongBinder(IInterface::asBinder(albumArt)); } else { reply->writeInt32(UNKNOWN_ERROR); } #ifndef DISABLE_GROUP_SCHEDULE_HACK restoreSchedPolicy(); #endif return NO_ERROR; } break; case EXTRACT_METADATA: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif int keyCode = data.readInt32(); const char* value = extractMetadata(keyCode); if (value != NULL) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeCString(value); } else { reply->writeInt32(UNKNOWN_ERROR); } #ifndef DISABLE_GROUP_SCHEDULE_HACK restoreSchedPolicy(); #endif return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
int Volume::mountVol() { dev_t deviceNodes[DirectVolume::MAX_PARTITIONS]; int n, i, rc = 0, curState; char errmsg[255]; int flags = getFlags(); /* we igore the setting of "VOL_PROVIDES_ASEC". if the storage is primary, then we will handle "Asec" */ //bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0; const char* externalStorage = getenv("EXTERNAL_STORAGE"); bool providesAsec = externalStorage && !strcmp(getFuseMountpoint(), externalStorage); // TODO: handle "bind" style mounts, for emulated storage char decrypt_state[PROPERTY_VALUE_MAX]; char crypto_state[PROPERTY_VALUE_MAX]; char encrypt_progress[PROPERTY_VALUE_MAX]; if (mPreState != Volume::State_Shared && mVm->isSomeVolumeShared()) { SLOGI("Some volume is State_Shared, force to share current volume, %s \n", getLabel()); return mVm->shareVolume(getLabel(), "ums"); } property_get("vold.decrypt", decrypt_state, ""); property_get("vold.encrypt_progress", encrypt_progress, ""); #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT char *otgNodePath = getOtgNodePath(); #endif /* Don't try to mount the volumes if we have not yet entered the disk password * or are in the process of encrypting. */ if ((getState() == Volume::State_NoMedia) || ((!strcmp(decrypt_state, "trigger_restart_min_framework") || encrypt_progress[0]) && providesAsec)) { snprintf(errmsg, sizeof(errmsg), "Volume %s %s mount failed - no media", getLabel(), getFuseMountpoint()); mVm->getBroadcaster()->sendBroadcast( ResponseCode::VolumeMountFailedNoMedia, errmsg, false); errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; if (getState() == Volume::State_Pending) { mRetryMount = true; } return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX return 0; } #ifdef MTK_SHARED_SDCARD SLOGI("mountvol: IsEmmcStorage=%d", IsEmmcStorage()); if (IsEmmcStorage()) { property_set("ctl.start", "sdcard"); waitForServiceState("sdcard", "running"); setState(Volume::State_Mounted); return 0; } #endif n = getDeviceNodes((dev_t *) &deviceNodes, DirectVolume::MAX_PARTITIONS); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } SLOGD("Found %d device nodes", n); #ifndef MTK_EMULATOR_SUPPORT if (!IsEmmcStorage() && !strncmp(getLabel(), "sdcard", 6)) { #ifdef MTK_FAT_ON_NAND if( -1 == mLoopDeviceIdx){ #endif SLOGD("Reinit SD card"); if (mVm->reinitExternalSD()){ SLOGE("Fail: reinitExternalSD()"); /* Card inserted but fail to reinit, there is something wrong with this card */ errno = EIO; return -1; } #ifdef MTK_FAT_ON_NAND } #endif } #endif /* If we're running encrypted, and the volume is marked as encryptable and nonremovable, * and also marked as providing Asec storage, then we need to decrypt * that partition, and update the volume object to point to it's new decrypted * block device */ property_get("ro.crypto.state", crypto_state, ""); if (providesAsec && ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) && !strcmp(crypto_state, "encrypted") && !isDecrypted()) { char new_sys_path[MAXPATHLEN]; char nodepath[256]; int new_major, new_minor; if (n != 1) { /* We only expect one device node returned when mounting encryptable volumes */ SLOGE("Too many device nodes returned when mounting %s\n", getMountpoint()); return -1; } if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]), new_sys_path, sizeof(new_sys_path), &new_major, &new_minor)) { SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint()); return -1; } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { if (createDeviceNode(otgNodePath, new_major, new_minor)) { SLOGE("usbotg: Volume mountVol Error making device node '%s' (%s)", otgNodePath, strerror(errno)); } updateDeviceInfo(otgNodePath, new_major, new_minor); } else #endif /* We now have the new sysfs path for the decrypted block device, and the * majore and minor numbers for it. So, create the device, update the * path to the new sysfs path, and continue. */ { snprintf(nodepath, sizeof(nodepath), "/dev/block/vold/%d:%d", new_major, new_minor); if (createDeviceNode(nodepath, new_major, new_minor)) { SLOGE("Error making device node '%s' (%s)", nodepath, strerror(errno)); } // Todo: Either create sys filename from nodepath, or pass in bogus path so // vold ignores state changes on this internal device. updateDeviceInfo(nodepath, new_major, new_minor); /* Get the device nodes again, because they just changed */ n = getDeviceNodes((dev_t *) &deviceNodes, DirectVolume::MAX_PARTITIONS); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } } } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { setState(Volume::State_Checking); if (0 != mkdir(getMountpoint(), 0700)) { SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getMountpoint(), strerror(errno)); } else { SLOGD("usbotg: Volume mountVol (%s) mkdir success", getMountpoint()); } if (0 != chown(getMountpoint(), AID_MEDIA_RW, AID_MEDIA_RW)) { SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getMountpoint(), strerror(errno)); } else { SLOGD("usbotg: Volume mountVol (%s) mkdir success", getMountpoint()); } if (0 != mkdir(getFuseMountpoint(), 0755)) { SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getFuseMountpoint(), strerror(errno)); } else { SLOGD("usbotg: Volume mountVol (%s) mkdir success", getFuseMountpoint()); } int fd; int counter = 0; while(1) { counter++; if( counter == 10) { SLOGD("timeout open otgNodePath counter:%d\n",counter); break; } if ((fd = open(otgNodePath, O_RDONLY)) < 0) { SLOGE(" cannot open device '%s' (errno=%d) (%s)", otgNodePath, errno,strerror(errno)); usleep(30000); } else { SLOGD(" can access %s successfully", otgNodePath); close(fd); break; } } if (Fat::check(otgNodePath)) { SLOGE("usbotg: %s fat check fail (%s)\n", otgNodePath, strerror(errno)); char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); return -1; } if (Fat::doMount(otgNodePath, getMountpoint(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { SLOGE("usbotg: Volume mountVol %s Otg failed to mount via VFAT (%s)\n", otgNodePath, strerror(errno)); char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); setState(Volume::State_Idle); return -1; } extractMetadata(otgNodePath); //fork sdcard process instead of witch service in init.rc struct sigaction act, oact; act.sa_handler = sigCld; act.sa_flags = 0; sigemptyset(&act.sa_mask); if (sigaction(SIGCHLD, &act, &oact) <0) { SLOGD("Error occured on signal"); return -1; } pid_t pid = fork(); if (pid < 0) { SLOGD("Error occured on fork"); return 0; } else if (pid == 0) { SLOGD("usbotg: Volume mountVol go execv,pid=%d", pid); const char* mountCmd = "/system/bin/sdcard"; const char* mountpoint = getMountpoint(); const char* fusemountpoint = getFuseMountpoint(); const char* argv0[] = { mountCmd, "-u", "1023", "-g", "1023", "-w", "1023", "-d", mountpoint, fusemountpoint, NULL }; SLOGD("%s %s %s %s %s %s %s %s %s %s", argv0[0], argv0[1], argv0[2], argv0[3], argv0[4], argv0[5], argv0[6], argv0[7], argv0[8], argv0[9]); if (execv(mountCmd,(char* const*)argv0) < 0) { ALOGE("execv(%s) failed: %s\n", mountCmd, strerror(errno)); SLOGD("usbotg: Volume mountVol mounted failed"); char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); exit(127); } exit(127); } else{ SLOGD("usbotg: Volume mountVol mounted succed,pid=%d",pid); setState(Volume::State_Mounted); mPid = pid; return 0; } } #endif for (i = 0; i < n; i++) { char devicePath[255]; sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]), minor(deviceNodes[i])); if (deviceNodes[i] == (dev_t)(-1)) { SLOGE("Partition '%s' is invalid dev_t. Skip mounting!", devicePath); continue; } SLOGI("%s being considered for volume %s\n", devicePath, getLabel()); errno = 0; if ((getState() == Volume::State_NoMedia) ) { SLOGI("NoMedia! skip mounting the storage. Update errno to ENODEV"); errno = ENODEV; return -1; } setState(Volume::State_Checking); /* * If FS check failed, we should move on to next partition * instead of returning an error */ __CHECK_FAT_AGAIN: if (Fat::check(devicePath)) { #if 0 if (errno == ENODATA) { SLOGW("%s does not contain a FAT filesystem\n", devicePath); continue; } errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); return -1; #else #ifdef MTK_EMMC_SUPPORT if ( mVm->isFirstBoot() && IsEmmcStorage()) { SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath); if (Fat::format(devicePath, 0, false)) { SLOGE("Failed to format (%s)", strerror(errno)); } else { SLOGI("Format successfully. (%s)\n", devicePath); property_set("persist.vold.first_boot", "0"); goto __CHECK_FAT_AGAIN; } } #endif #ifdef MTK_FAT_ON_NAND char first_boot[PROPERTY_VALUE_MAX] ; property_get("persist.vold.fat_first_boot", first_boot, "1"); if (!strcmp(first_boot, "1") && !strcmp(getLabel(), "sdcard0")) { SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath); if (Fat::format(devicePath, 0, false)) { SLOGE("Failed to format %s(%d)", strerror(errno), errno); } else { SLOGI("%s format successfully\n", devicePath); property_set("persist.vold.fat_first_boot", "0"); goto __CHECK_FAT_AGAIN; } } #endif SLOGW("%s failed FS checks, move on to next partition", devicePath); continue; #endif } #ifdef MTK_EMMC_SUPPORT else { if ( mVm->isFirstBoot() && IsEmmcStorage()) { property_set("persist.vold.first_boot", "0"); } } #endif errno = 0; int gid; #ifdef MTK_EMMC_DISCARD if (Fat::doMount(devicePath, getMountpoint(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true, IsEmmcStorage())) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } #else //MTK_EMMC_DISCARD if (Fat::doMount(devicePath, getMountpoint(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } #endif //MTK_EMMC_DISCARD SLOGI("providesAsec = %d", providesAsec); extractMetadata(devicePath); #ifdef MTK_2SDCARD_SWAP char secImgDir[PATH_MAX]; sprintf(secImgDir, "%s/.android_secure", getMountpoint()); SLOGI("Create %s in advance", secImgDir); /* Whether primary or secondary storage, create .android folder in advance to prevent from media out of space for Bindmounts fail This case happens in SWAP feature. */ if (access(secImgDir, R_OK | X_OK)) { if (errno == ENOENT) { if (mkdir(secImgDir, 0777)) { SLOGE("Failed to create %s (%s)", secImgDir, strerror(errno)); } } else { SLOGE("Failed to access %s (%s)", secImgDir, strerror(errno)); } } #endif if (providesAsec && mountAsecExternal() != 0) { SLOGE("Failed to mount secure area (%s)", strerror(errno)); umount(getMountpoint()); setState(Volume::State_Idle); return -1; } char service[64]; char service_id[64]; strcpy(service_id, getMountpoint()+strlen(Volume::MEDIA_DIR)+1); snprintf(service, 64, "fuse_%s", service_id); property_set("ctl.start", service); waitForServiceState(service, "running"); int fd; if ((fd = open(devicePath, O_RDONLY)) < 0) { SLOGE("Cannot open device '%s' (errno=%d)", devicePath, errno); } else { setState(Volume::State_Mounted, Fat::isFat32(fd)); close(fd); } mCurrentlyMountedKdev = deviceNodes[i]; return 0; } SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); curState = getState(); if (curState == Volume::State_NoMedia) { SLOGI("Mount fail caused by NoMedia! Update errno to ENODEV"); errno = ENODEV; } if ((curState != Volume::State_NoMedia) && (curState != Volume::State_Mounted)) { setState(Volume::State_Idle); } if(curState == Volume::State_Mounted) { return 0; } return -1; }