转载请注明文章出处和作者!
出处:http://blog.csdn.net/xl19862005
作者:大熊(Xandy)
由于项目的要求,需要限制用户安装APP的数量,对android app安装流程了解的都知道,核心的东西都在installd这个服务里面,我这里所做的处理也在这里面。
installd的源码位于frameworks/native/cmds/installd(android5.1),这个服务随init启来之后,通过socket和上层进行数据交互,在installd里面能处理的命令集如下(android版本不同,这些命令略有差异):
struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
{ "install", 4, do_install },
{ "dexopt", 6, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "movedex", 3, do_move_dex },
{ "rmdex", 2, do_rm_dex },
{ "remove", 2, do_remove },
{ "rename", 2, do_rename },
{ "fixuid", 3, do_fixuid },
{ "freecache", 1, do_free_cache },
{ "rmcache", 2, do_rm_cache },
{ "rmcodecache", 2, do_rm_code_cache },
{ "getsize", 7, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
{ "linklib", 3, do_linklib },
{ "mkuserdata", 4, do_mk_user_data },
{ "mkuserconfig", 1, do_mk_user_config },
{ "rmuser", 1, do_rm_user },
{ "idmap", 3, do_idmap },
{ "restorecondata", 3, do_restorecon_data },
{ "patchoat", 5, do_patchoat },
};
对app限制安装只看install这个命令的处理函数,在frameworks/native/cmds/installd/commands.c这个文件中的install函数这里,我增加了如下处理代码:
int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{
………………
/****************************Xandy add for app install control***************************/
if(app_install_cnt_ctrl() < 0)
return -1;
………………
}
相关实现代码如下:
#define APP_CNT_PATH "/data/misc/installctrl/cnt"
static int app_cnt = 0;
/********从文件读取用户安装APP的数量*******/
static int get_user_install_app_cnt(void)
{
int fd;
char buf[10];
fd = open(APP_CNT_PATH, O_RDONLY | O_NONBLOCK);
if(fd < 0)
{
ALOGE("File:%S doesn't exist", AP_CNT_PATH);
return 0;
}
if(read(fd, buf, 10) < 0)
{
ALOGE("Read file:%s error",APP_CNT_PATH);
return 0;
}
close(fd);
return atoi(buf);
}
/***********保存用户安装APP的数量*************/
static void save_user_install_app_cnt(void)
{
FILE* fp = NULL;
int fd;
char buf[10];
app_cnt++;//a new app install
sprintf(buf, "%d", app_cnt);
if(acces(APP_CNT_PATH, F_OK) != 0)
{
fp = fopen(APP_CNT_PATH, "w+");
fputs(buf, fp);
fclose(fp);
fp = NULL;
}
else
{
fd = open(APP_CNT_PATH, O_RDWR);
if(fd >= 0)
{
write(fd, buf, 10);
close(fd);
}
}
}
/*********获取开机完成状态*********/
static int boot_animation_finish(void)
{
char value[PROPERTY_VALUE_MAX];
property_get("service.bootanim.exit",value, "1");
return atoi(value);
}
//************************************
static int app_install_cnt_ctrl(void)
{
char value[PROPERTY_VALUE_MAX];
int ctrl_cnt;
if(boot_animation_finish() == 1)
{
property_get("ro.ctrl.app_install_cnt", value, "0");//用户可安装的APP数量,通过ro.ctrl.app_install_cnt这个prop获取
ctrl_cnt = atoi(value);
app_cnt = get_user_install_app_cnt();
if(app_cnt < ctrl_cnt)
{
save_user_install_app_cnt();
return 0;
}
else
return -1;
}
return 0;
}
实现原理:
将每次用户安装的APP数目记录到文件,当安装的数目达到由ro.ctrl.app_install_cnt这个prop设置的上限值时,直接退出install处理流程。
上面的代码我是留了一个小后门的(在某种情况下可以安装APP,这也是方法以后自己调试的方便),仔细的你肯定能发现,这里就不直说了哈,有需要的小伙伴自己慢慢琢磨……