android sdcard 蛋疼集锦

1. 拔掉sdcard文件管理器显示sdcard一直存在

sdcard的插拔是通过uevet事件传递给上层的,在kernel的 kernel\lib\kobject_uevent.c
kobject_uevent_env 函数中添加打印信息获取查看所有的uevent事件,发现只有sdcard插上时上传的add事件,sdcard拔掉时并没有相应的remove事件。。。
跟踪sd卡驱动源码,插拔会触发一个中断,在中断处理函数中添加打印,没有问题,插拔都会执行到;中断处理函数会调度一个工作队列,工作队列的核心函数是 drivers\mmc\core\core.c 的 mmc_rescan 函数,
所有sdcard、mmc、sdio添加移除工作都是这函数处理。添加过程没有问题,关注sdcard移除阶段的操作

bus_ops->detect()操作去探测SD总线上是否还存在SD卡,如果不存在了,就执行bus_ops->remove()拔出SD卡。对应下面的代码,跟踪发现“ !(host->caps & MMC_CAP_NONREMOVABLE))” 这个条件不满足,所以根本没有执行后面的 detect 、remove操作

//如果已经有 bus_ops ,表示注册过sdcard,发生了中断现在去用 bus_ops->detect 函数去检测sdcard是否存在
     if (host->bus_ops && host->bus_ops->detect && !host->bus_dead && !(host->caps & MMC_CAP_NONREMOVABLE))
        host->bus_ops->detect(host);  

2.不支持格式的sdcard挂载失败没有任何提示

对比机中插入不支持sdcard会弹出一个view提示不支持格式,格式不支持那么出错阶段就在挂载过程
梳理一遍sdcard插入流程

//  插入sd卡-》kernel发出add的uevent事件,上层处理去挂载sd卡
//  上层处理挂载消息的对应代码为 mountService.java 的doMountVolume方法
//  添加log打印出错误码,发现没有一个对应的,心累,果断将OpFailedMediaBlank的错误码改成打印出来的值fix

    try {
            mConnector.execute("volume", "mount", path);
        } catch (NativeDaemonConnectorException e) {
            /*
             * Mount failed for some reason
             */
            String action = null;
            int code = e.getCode();
        Slog.i("zch","MountService.java=====MountService.java doMountVolume code ="+code);
            if (code == VoldResponseCode.OpFailedNoMedia) {

            ...
            // 挂载失败时不支持格式的错误码
             else if (code == VoldResponseCode.OpFailedMediaBlank) {
                if (DEBUG_EVENTS) Slog.i(TAG, " updating volume state :: media nofs");
                /*
                 * Media is blank or does not contain a supported filesystem
                 */
                updatePublicVolumeState(volume, Environment.MEDIA_NOFS);
                action = Intent.ACTION_MEDIA_NOFS;
                rc = StorageResultCode.OperationFailedMediaBlank;
            } 

3.不能移动apk到sdcard

log中看出在 /mnt/secure 目录创建一个文件失败,提示没有权限,果断关掉selinux,仍然失败,adb shell手动进去创建一个文件,仍然失败,这下懵逼了….
求助大神,大神说/mnt/目录下的文件都会挂载,如果没有指定,就会按照默认的 rootfs 格式挂载,rootfs的挂载格式为 ro ,在init.rc中重新挂载 /mnt/secure 目录为rw的tmpfs,fix。

mkdir /mnt/secure 0700 system system
mount tmpfs tmpfs /mnt/secure mode=0700,gid=1000

4.安装到sdcard的apk重启后失效

分析移动apk到sdcard的log,发现会将 /data/app/com.xxx.xxx apk安装包文件全部拷贝到 /mnt/asec目录,不是移到sdcard吗,套路不对啊,代码逻辑有问题?查看对比机的log,也是移到/mnt/asec。网上搜“android /mnt/asec ”果然找到答案了:这个目录就是sdcard 的.android_secure目录的挂载点。进adb shell一看sd卡下面压根就没有这个目录,android_secure是啥时候创建、挂载的?

system/vold 目录下一grep找到了: Volume::mountAsecExternal 方法就是专门挂载这个目录的。添加一些打印,压根没有执行这个函数。。。。

分析源码 Volume 在构造函数中传入的flags为 VOL_PROVIDES_ASEC 时才会执行Volume::mountAsecExternal

代码追踪 flags的赋值

// DirectVolume.cpp  追踪到Volume的构造
DirectVolume::DirectVolume(VolumeManager *vm, const fstab_rec* rec, int flags) :
        Volume(vm, rec, flags) {


----------

// system/vold/main.cpp    追踪到 DirectVolume 的构造和flags的赋值
 for (i = 0; i < fstab->num_entries; i++) {
        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
            DirectVolume *dv = NULL;
            flags = 0;

            /* Set any flags that might be set for this volume */
            if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
                flags |= VOL_NONREMOVABLE;
            }
            if (fs_mgr_is_encryptable(&fstab->recs[i])) {
                flags |= VOL_ENCRYPTABLE;
            }
            /* Only set this flag if there is not an emulated sd card */
            // ★条件判断★
            if (fs_mgr_is_noemulatedsd(&fstab->recs[i]) &&
                !strcmp(fstab->recs[i].fs_type, "vfat")) {
                flags |= VOL_PROVIDES_ASEC;  // flags 赋值为需要的值
            }
            dv = new DirectVolume(vm, &(fstab->recs[i]), flags);

            if (dv->addPath(fstab->recs[i].blk_device)) {
                SLOGE("Failed to add devpath %s to volume %s",
                      fstab->recs[i].blk_device, fstab->recs[i].label);
                goto out_fail;
            }

查看 fstab.qcom配置文件,发现vfat 满足,追踪 fs_mgr_is_noemulatedsd 函数


int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
{
    return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
}

fstab.qcom 文件
这里写图片描述
发现源文件中并未设置 NOEMULATEDSD flag,添加验证fix。

你可能感兴趣的:(linux/android,driver)