现在的位置: 首页 > 综合 > 正文

Android “无法查看***。请释放部分手机内存”

2013年09月09日 ⁄ 综合 ⁄ 共 2284字 ⁄ 字号 评论关闭

 

Android   "无法查看***。请释放部分手机内存"

(北大众志小本(MPRC)上移植Android 2.1

通过浏览器下载(ucweb)软件后,点击安装,弹出对话框:“无法查看***。请释放部分手机内存”。

通过logcat查看发现是:"Couldn't clear application caches"

跟进源码发现错误信息是从:PackageManagerService.java (frameworks/base/services/java/com/android/server) 中的freeStorage()函数中打印出来的。

 

 

 

通过一步步跟进

freeCache()->execute()->transaction()->connect()

connect()函数中实例化了一个本地的socket,用于进程间通信。那么它到底和谁在进行进程间通信呢?

  

 

原来PackageManagerService在与init.rc中开启的守护进程:installd通信。

 

梳理一下我们可以推断错误来源:

客户端service发送的cmd"freeCache"没有得到服务器端守护进程的响应。

通过查看installd的相关源码installd.c中的

 

我们可以找到响应命令的处理函数:do_free_cache

再一步步跟进:

do_free_cache()->free_cache()->disk_free()

下面就重点看看这个函数:

 

可以发现这个函数首先通过statfs获取PKG_DIR_PREFIX("data/data")文件系统信息,然后返回非超级用户可以获取的空闲内存块数。

然后再看看保存文件系统信息的结构体

 

最后通过加调试信息,找到了错误的根源是google 源码本身的bug:

首先,statfs()函数获取"data/data"的信息成功,然后返回非超级用户可以获取的空闲内存块大小,即:sfs.f_bavail * sfs.f_bsize;

变量sfs.f_bavailsfs.f_bsize是两个long类型的变量,相乘后却保存在一个int类型的变量中,导致32位变量溢出越界,最终返回一个负数。free_cache()函数返回错误,最终客户端PackageManagerService收到错误信息反馈,导致安装失败。

另一方面,我们的众志小本硬盘空间比一般的娱乐终端(手机,pad)内存空间大很多,所以sfs.f_bavail的值会很大,相乘后的结果保存在int类型变量中,肯定会溢出。

解决方法:将disk_free()函数的返回值改为uint64_t就ok了。

补充

有空的话,仔细梳理一下应用程序的安装过程:

·通过adb install 命令安装

·通过软件安装

·installd 和PackageInstall.apk和PackageManagerService.java之间通信

 

抱歉!评论已关闭.