zeerd's blog     Article     Search     About     Tags     Pebble     Feed

闲来生雅趣,无事乐逍遥。对窗相望雪,一盏茶香飘。

Android系统是如何瞒天过海的限制用户访问SD卡的

#Android #Device #mount


拿我的Nexus5为例。
我们可以先看一下fstab文件:
root@hammerhead:/ # cat fstab.hammerhead
# Android fstab file.
#                                              
# The filesystem that contains the filesystem checker binary (typically /system) cannot
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK

/dev/block/platform/msm_sdcc.1/by-name/system       /system         ext4    ro,barrier=1                                                    wait
/dev/block/platform/msm_sdcc.1/by-name/userdata     /data           ext4    noatime,nosuid,nodev,barrier=1,data=ordered,nomblk_io_submit,noauto_da_alloc,errors=panic wait,check,encryptable=/dev/block/platform/msm_sdcc.1/by-name/metadata
/dev/block/platform/msm_sdcc.1/by-name/cache        /cache          ext4    noatime,nosuid,nodev,barrier=1,data=ordered,nomblk_io_submit,noauto_da_alloc,errors=panic wait,check
/dev/block/platform/msm_sdcc.1/by-name/persist      /persist        ext4    nosuid,nodev,barrier=1,data=ordered,nodelalloc,nomblk_io_submit,errors=panic wait
/dev/block/platform/msm_sdcc.1/by-name/modem        /firmware       vfat    ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0        wait
/dev/block/platform/msm_sdcc.1/by-name/boot         /boot           emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/recovery     /recovery       emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/misc         /misc           emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/modem        /radio          emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/sbl1         /sbl1           emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/tz           /tz             emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/rpm          /rpm            emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/sdi          /sdi            emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/aboot        /aboot          emmc    defaults                                                        defaults
/dev/block/platform/msm_sdcc.1/by-name/imgdata      /imgdata        emmc    defaults                                                        defaults

看看其中的第二行:
/dev/block/platform/msm_sdcc.1/by-name/userdata     /data ...
这一行的作用是告诉vold将内部存储器中的userdata分区挂载到/data分区。
而/data/media就是我们实际的SD卡目录。
root@hammerhead:/ # ll /data/media
drwxrwx--- media_rw media_rw          2015-03-24 16:30 0
drwxrwxr-x media_rw media_rw          1970-12-03 06:27 legacy
drwxrwxr-x media_rw media_rw          2014-12-04 07:47 obb

接下来,我们看看这个目录是如何变成JAVA层可以看到的另一个完全不同的路径的。
在init.hammerhead.rc中,我们可以找到下面几行内容:
# virtual sdcard daemon running as media_rw (1023)
service sdcard /system/bin/sdcard -u 1023 -g 1023 -l /data/media /mnt/shell/emulated
    class late_start

这里的作用是启动一个名字叫做sdcard的服务。这个服务做了一件事情,通过fuse机制将/data/media挂载到/mnt/shell/emulated分区。
这个“/mnt/shell/emulated”是不是看着很眼熟了?

稍后,MountServie会通过createEmulatedVolumeForUserLocked()函数将“/mnt/shell/emulated”下的目录mount到“/storage/emulated”下。而这个目录就是JAVA层通过getExternalStorage()函数获取的SD卡路径了。