首页 > 代码库 > 设置内部sdcard存储下限

设置内部sdcard存储下限

在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) %u@%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);

    ......

}