Android一个权限相关的bug修复过程
2015-08-06 10:25
239 查看
这篇文章3天前就应该成文了。但是由于最近比较懒惰,一拖再拖到了现在。马上要开始找工作了,必须把自己的状态调整到正确的模式了。那么就从这篇博客开始吧~~
这篇文章的起因是我修复的一个Android中关于权限的bug。此bug是一款Android TV app上读取插入的usb设备中的内容问题。首先是app代码:
private static void searchFile(File filepath, ArrayList<LocalMediaData> mediaDatas, int filetype,ContentResolver filecr, String query) {
File[] files = filepath.listFiles();
if (null == files || files.length <= 0) {
Log.e(TAG, "Error, no file found!!!");
return;
}
......
}
跑起来打印log发现会报文件为空的错误。关于外部存储文件的读写,自然想到是否是没有配置读取sd卡的权限。去AndroidManifest.xml中查
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
OK,没问题已经配置了。那么为什么还是读不到呢?又想到Android底层是Linux的内核,那么去看看相应文件夹的权限吧。进入到Android操作系统,ls -al以下发现,相应文件夹的权限是: d---rwxr-x system sdmedia_rw **** 也就是说,这个文件夹所属用户是system,所属用户组是sdmedia_rw。但是,system用户对此文件夹没有任何的权限。回头去查一下,是否这个app是system用户。果然,在AndroidManifest.xml中发现了 android:sharedUserId="android.uid.system"。也就是说这个App是系统应用,它分享了system这个Linux系统用户,所以它对要读取的文件没有权限。那么问题找到了,解决问题的方法就是要么把应用变成非系统用户,要么修改usb文件夹的权限。第一种是不可行的,因为此App中有一些功能需要用到系统用户的权限。那么就只能用第二种解决方法了。
由于这是一个usb文件,故而想到了Android的挂载usb的命令:mount。mount了以下后,发现挂载的usb的fmask和dmask都是0702,挂载上后,文件权限就成了075。那么把挂载的fmask和dmask变成0002就可以了。问题是怎么变呢?各种百度,google,stackoverflow后依然没有发现解决方法。手工umount掉原文件夹,再mount上去倒是可以临时改变文件权限,但是重启后就失效。没办法了,只好去源代码中找解决方法了。
记住一个关键词"0702",既然这个是在源代码中设置好的,那么在代码中一定有这个数值。所以,我就全文搜索0702这个关键词。果然在./system/vold文件夹的 MediaVolume.h中发现了static const int MOUNT_PERMMASK=0702; 不管从常量定义上还是数值上,都可以确定,Android在挂载usb的时候一定用到了这个mask,所以才造成了挂载的文件权限是诡异的075。那么,把这个数值改掉,重新编译以下Android就好了呗。
回去找Android最开始的源代码发现system/vold/文件夹下面根本没有MediaVolume.h这个文件。那么一定是在编译的时候,编译脚本加上去的。所以在到编译脚本中找0702,果然找到了.....改了它,再重新编译Android。 回过头来再看MediaVolume.h中的static const int MOUNT_PERMMASK=0002;OK,把image烧到班子上,再看看,挂载的usb文件夹权限已经变成了775了,再跑一遍app就能读出usb上的视频和图片了。。。
至此,问题是解决了。但是牵扯出的问题有很多,这里先列以下,我想以这个为突破点,认真研究下Android源代码和内核层的东西
1,Android权限管理机制原理
2,Android mount实现
3,Android编译
这篇文章的起因是我修复的一个Android中关于权限的bug。此bug是一款Android TV app上读取插入的usb设备中的内容问题。首先是app代码:
private static void searchFile(File filepath, ArrayList<LocalMediaData> mediaDatas, int filetype,ContentResolver filecr, String query) {
File[] files = filepath.listFiles();
if (null == files || files.length <= 0) {
Log.e(TAG, "Error, no file found!!!");
return;
}
......
}
跑起来打印log发现会报文件为空的错误。关于外部存储文件的读写,自然想到是否是没有配置读取sd卡的权限。去AndroidManifest.xml中查
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
OK,没问题已经配置了。那么为什么还是读不到呢?又想到Android底层是Linux的内核,那么去看看相应文件夹的权限吧。进入到Android操作系统,ls -al以下发现,相应文件夹的权限是: d---rwxr-x system sdmedia_rw **** 也就是说,这个文件夹所属用户是system,所属用户组是sdmedia_rw。但是,system用户对此文件夹没有任何的权限。回头去查一下,是否这个app是system用户。果然,在AndroidManifest.xml中发现了 android:sharedUserId="android.uid.system"。也就是说这个App是系统应用,它分享了system这个Linux系统用户,所以它对要读取的文件没有权限。那么问题找到了,解决问题的方法就是要么把应用变成非系统用户,要么修改usb文件夹的权限。第一种是不可行的,因为此App中有一些功能需要用到系统用户的权限。那么就只能用第二种解决方法了。
由于这是一个usb文件,故而想到了Android的挂载usb的命令:mount。mount了以下后,发现挂载的usb的fmask和dmask都是0702,挂载上后,文件权限就成了075。那么把挂载的fmask和dmask变成0002就可以了。问题是怎么变呢?各种百度,google,stackoverflow后依然没有发现解决方法。手工umount掉原文件夹,再mount上去倒是可以临时改变文件权限,但是重启后就失效。没办法了,只好去源代码中找解决方法了。
记住一个关键词"0702",既然这个是在源代码中设置好的,那么在代码中一定有这个数值。所以,我就全文搜索0702这个关键词。果然在./system/vold文件夹的 MediaVolume.h中发现了static const int MOUNT_PERMMASK=0702; 不管从常量定义上还是数值上,都可以确定,Android在挂载usb的时候一定用到了这个mask,所以才造成了挂载的文件权限是诡异的075。那么,把这个数值改掉,重新编译以下Android就好了呗。
回去找Android最开始的源代码发现system/vold/文件夹下面根本没有MediaVolume.h这个文件。那么一定是在编译的时候,编译脚本加上去的。所以在到编译脚本中找0702,果然找到了.....改了它,再重新编译Android。 回过头来再看MediaVolume.h中的static const int MOUNT_PERMMASK=0002;OK,把image烧到班子上,再看看,挂载的usb文件夹权限已经变成了775了,再跑一遍app就能读出usb上的视频和图片了。。。
至此,问题是解决了。但是牵扯出的问题有很多,这里先列以下,我想以这个为突破点,认真研究下Android源代码和内核层的东西
1,Android权限管理机制原理
2,Android mount实现
3,Android编译
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories