frameworks/native/services/fileinotify/FileInotify.cpp

280 lines
6.3 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*******************************
程序功能把抖音极速版的数据库文件挂载到tmpfs内存中。避免频繁写入内部存储提高EMMC使用寿命。
********************************/
#define LOG_TAG "FileInotify"
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <cutils/properties.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <pthread.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#define CMD_BASE 0xCBAABC10
#define FK_IS_GET_POWER2 (CMD_BASE + 12)
#define EVENT_SIZE (sizeof(struct inotify_event))
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
#define MAX_BUF_SIZE 256
#define NOTIFY_DIR_NUM 2
//监控文件名
#define NOTIFY_FILE "apm_monitor_t1.db"
#define NOTIFY_FILE_2 "apm_monitor_t1.db-journal"
//监听目录
#define NOTIFY_PATH "/data/data/com.ss.android.ugc.aweme.lite/databases/"
#define NOTIFY_PATH_2 "/data/data/com.ss.android.ugc.live/databases/"
//挂载目录
#define TMPFS_PATH "/data_mirror/com.ss.android.ugc.aweme.lite/databases/"
#define TMPFS_PATH_2 "/data_mirror/com.ss.android.ugc.live/databases/"
typedef enum INDEX
{
DIR1,
DIR2,
}INDEX_T;
typedef struct {
int dir_exists[NOTIFY_DIR_NUM];
int wd[NOTIFY_DIR_NUM];
int fd;
}inotify_info;
void *inotify_func(void *argc)
{
inotify_info *info = (inotify_info *)argc;
char buf[MAX_BUF_SIZE];
while(1)
{
if(access(NOTIFY_PATH, F_OK) == 0 && info->dir_exists[DIR1] == 0)
{
//监听目录
info->dir_exists[DIR1] = 1;
info->wd[DIR1] = inotify_add_watch(info->fd, NOTIFY_PATH, IN_CREATE | IN_DELETE);
//pthread_exit(NULL);
//ALOGD("add dir %s,wd=%d\n", NOTIFY_PATH, info->wd[DIR1]);
}
if(access(NOTIFY_PATH_2, F_OK) == 0 && info->dir_exists[DIR2] == 0)
{
//监听目录
info->dir_exists[DIR2] = 1;
info->wd[DIR2] = inotify_add_watch(info->fd, NOTIFY_PATH_2, IN_CREATE | IN_DELETE);
//pthread_exit(NULL);
//ALOGD("add dir %s,wd=%d\n", NOTIFY_PATH_2, info->wd[DIR2]);
}
//应用卸载目录删除,重新设置标志
if(access(NOTIFY_PATH, F_OK) != 0)
{
info->dir_exists[DIR1] = 0;
}
if(access(NOTIFY_PATH_2, F_OK) != 0)
{
info->dir_exists[DIR2] = 0;
}
sleep(5);
}
}
int do_mount(char *name, int wd, inotify_info *info)
{
char buf[MAX_BUF_SIZE];
//1. 创建tmpfs目录
if(access(TMPFS_PATH, F_OK) != 0) //如果目录不存在
{
sprintf(buf, "mkdir -p %s", TMPFS_PATH);
system(buf);
memset(buf, 0, sizeof(buf));
}
if(access(TMPFS_PATH_2, F_OK) != 0) //如果目录不存在
{
sprintf(buf, "mkdir -p %s", TMPFS_PATH_2);
system(buf);
memset(buf, 0, sizeof(buf));
}
//2. 创建tmpfs文件
sprintf(buf, "%s/%s", TMPFS_PATH, name);
if(access(buf, F_OK) != 0) //如果文件不存在
{
sprintf(buf, "touch %s/%s", TMPFS_PATH, name);
system(buf);
memset(buf, 0, sizeof(buf));
}
sprintf(buf, "%s/%s", TMPFS_PATH_2, name);
if(access(buf, F_OK) != 0) //如果文件不存在
{
sprintf(buf, "touch %s/%s", TMPFS_PATH_2, name);
system(buf);
memset(buf, 0, sizeof(buf));
}
//3. 挂载
if(info->wd[DIR1] == wd)
{
sprintf(buf, "%s/%s", NOTIFY_PATH, name);
if(access(buf, F_OK) == 0) //如果文件存在
{
//mount -o vcloud --bind /data_mirror/com.ss.android.ugc.aweme.lite/apm_monitor_t1.db /data/data/com.ss.android.ugc.aweme.lite/databases/apm_monitor_t1.db
sprintf(buf, "mount -o vcloud --bind %s/%s %s/%s", TMPFS_PATH, name, NOTIFY_PATH, name);
system(buf);
memset(buf, 0, sizeof(buf));
}
}
if(info->wd[DIR2] == wd)
{
sprintf(buf, "%s/%s", NOTIFY_PATH_2, name);
if(access(buf, F_OK) == 0) //如果文件存在
{
sprintf(buf, "mount -o vcloud --bind %s/%s %s/%s", TMPFS_PATH_2, name, NOTIFY_PATH_2, name);
system(buf);
memset(buf, 0, sizeof(buf));
}
}
return 0;
}
int do_umount(char *name, int wd, inotify_info *info)
{
char buf[MAX_BUF_SIZE];
if(info->wd[DIR1] == wd)
{
//1. 卸载
sprintf(buf, "%s/%s", NOTIFY_PATH, name);
if(access(buf, F_OK) == 0) //如果文件存在
{
sprintf(buf, "umount %s/%s", NOTIFY_PATH, name);
system(buf);
memset(buf, 0, sizeof(buf));
}
//2. 删除文件
memset(buf, 0, sizeof(buf));
sprintf(buf, "rm %s/%s", TMPFS_PATH, name);
system(buf);
}
if(info->wd[DIR2] == wd)
{
//1. 卸载
sprintf(buf, "%s/%s", NOTIFY_PATH_2, name);
if(access(buf, F_OK) == 0) //如果文件存在
{
sprintf(buf, "umount %s/%s", NOTIFY_PATH_2, name);
system(buf);
memset(buf, 0, sizeof(buf));
}
//2. 删除文件
memset(buf, 0, sizeof(buf));
sprintf(buf, "rm %s/%s", TMPFS_PATH_2, name);
system(buf);
}
return 0;
}
void do_rmfile(char *name)
{
char buf[MAX_BUF_SIZE];
memset(buf, 0, sizeof(buf));
sprintf(buf, "rm %s/%s", NOTIFY_PATH, name);
system(buf);
memset(buf, 0, sizeof(buf));
sprintf(buf, "rm %s/%s", NOTIFY_PATH_2, name);
system(buf);
}
int main(void)
{
inotify_info info;
pthread_t tid;
int length, i = 0;
char buf[EVENT_BUF_LEN];
//selinux
prctl(FK_IS_GET_POWER2, 0, 0, 0);
//inotify初始化
info.fd = inotify_init();
if (info.fd < 0)
{
perror("inotify_init");
return -1;
}
//监听目录
pthread_create(&tid, NULL, inotify_func, &info);
while(1)
{
i = 0;
length = read(info.fd, buf, EVENT_BUF_LEN);
if (length < 0)
{
perror("read");
continue;
}
while (i < length)
{
struct inotify_event *event = (struct inotify_event *) &buf[i];
if (event->len)
{
if (event->mask & IN_CREATE)
{
if (!(event->mask & IN_ISDIR))
{
if(strcmp(NOTIFY_FILE, event->name) == 0 || strcmp(NOTIFY_FILE_2, event->name) == 0)
{
//ALOGD("file %s created wd=%d\n", event->name, event->wd);
#if 0
do_mount(event->name, event->wd, &info);
#else
//直接删除文件
do_rmfile(event->name);
#endif
}
}
}
else if (event->mask & IN_DELETE)
{
if (!(event->mask & IN_ISDIR))
{
if(strcmp(NOTIFY_FILE, event->name) == 0 || strcmp(NOTIFY_FILE_2, event->name) == 0)
{
//ALOGD("file %s deleted wd=%d\n", event->name, event->wd);
#if 0
do_umount(event->name, event->wd, &info);
#endif
}
}
}
}
i += EVENT_SIZE + event->len;
}
}
inotify_rm_watch(info.fd, info.wd[DIR1]);
inotify_rm_watch(info.fd, info.wd[DIR2]);
close(info.fd);
return 0;
}