在Android中,内部存储有一部分区域是必须预留出来供系统运行应用程序的。
但是在Android原生设计中没有考虑这点,内部存储是可以完全填充满的。
这样会导致系统在运行程序,尤其是需要操作数据库的程序时,出现SQLiteFullException的错误。
解决的方法是在sdcard.c文件中加入一个限制,比如限制当存储低于100M时,不再允许第三方应用存储媒体文件。
如adb push 文件到/storage/sdcard0/中,或录音,拍照等保存到/storage/sdcard0/中。
这100M的空间专门预留出来保证系统程序的运行。
sdcard.c文件所在路径为源码中:system/com/sdcard/sdcard.c
修改完后可直接编译sdcard目录,会生成一个sdcard文件,push到系统/system/bin目录下,重启后即生效。
修改代码:
1.在sdcard.c的开始位置定义宏
// begin:SQLiteFullException happened when device memory is empty.
#define LIMIT_USEDATA_SIZE (100 * 1024 * 1024)
// end:SQLiteFullException happened when device memory is empty.
2.在fuse结构体中增加变量free_blksize
struct fuse {
......
__u64 next_generation;
// begin:SQLiteFullException happened when device memory is empty.
__u64 free_blksize;
// end:SQLiteFullException happened when device memory is empty.
......
}
3.在init方法中做初始化
static void fuse_init(struct fuse *fuse, int fd, const char *source_path,
gid_t write_gid, derive_t derive, bool split_perms) {
......
fuse->next_generation = 0;
// begin:SQLiteFullException happened when device memory is empty.
struct statfs stat;
if (statfs(source_path, &stat) < 0) {
fuse->free_blksize = 0;
} else {
fuse->free_blksize = stat.f_bfree * stat.f_bsize;
}
// end:SQLiteFullException happened when device memory is empty.
fuse->derive = derive;
......
}
4.在handle_write方法中实现功能
static int handle_write(struct fuse* fuse, struct fuse_handler* handler,
const struct fuse_in_header* hdr, const struct fuse_write_in* req,
const void* buffer) {
......
TRACE("[%d] WRITE %p(%d) %[email protected]%llu\n", handler->token,
h, h->fd, req->size, req->offset);
// begin:SQLiteFullException happened when device memory is empty.
if (!strncmp(fuse->root.name, "/data/media", fuse->root.namelen)) {
pthread_mutex_lock(&fuse->lock);
fuse->free_blksize -= req->size;
pthread_mutex_unlock(&fuse->lock);
if (fuse->free_blksize <= LIMIT_USEDATA_SIZE) {
struct statfs stat;
if (statfs(fuse->root.name, &stat) < 0) {
fuse->free_blksize = 0;
return -errno;
} else {
pthread_mutex_lock(&fuse->lock);
fuse->free_blksize = stat.f_bfree * stat.f_bsize;
pthread_mutex_unlock(&fuse->lock);
}
errno = ENOSPC;
return -errno;
}
}
// end:SQLiteFullException happened when device memory is empty.
res = pwrite64(h->fd, buffer, req->size, req->offset);
......
}
设置内部sdcard存储下限