Android系统是如何瞒天过海的限制用户访问SD卡的
Charles Chan @ 2015-03-25 #Device #mount @Android
Contents:
我们可以先看一下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卡路径了。