system/core/init/
bionic/libc/bionic/
system/core/libcutils/
adb shell getprop
[ro.product.device]: [lcsh92_wet_jb9] [ro.product.locale.language]: [zh] [ro.product.locale.region]: [CN] [ro.product.manufacturer]: [Xiaomi]
property_init(); queue_builtin_action(property_service_init_action, "property_service_init");
void property_init(void)
{
init_property_area();
}
static int property_area_inited = 0;
static workspace pa_workspace;
static int init_property_area(void)
{
// 属性空间是否已经初始化
if (property_area_inited)
return -1;
if (__system_property_area_init())
return -1;
if (init_workspace(&pa_workspace, 0))
return -1;
fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC);
property_area_inited = 1;
return 0;
}
__system_property_area_init
__system_property_area_init函数位于/bionic/libc/bionic/system_properties.c文件中,具体代码实现如下:
struct prop_area {
unsigned bytes_used;
unsigned volatile serial;
unsigned magic;
unsigned version;
unsigned reserved[28];
char data[0];
};
typedef struct prop_area prop_area;
prop_area *__system_property_area__ = NULL;
#define PROP_FILENAME "/dev/__properties__"
static char property_filename[PATH_MAX] = PROP_FILENAME;
#define PA_SIZE (128 * 1024)
static int map_prop_area_rw()
{
prop_area *pa;
int fd;
int ret;
/**
* O_RDWR ==> 读写
* O_CREAT ==> 若不存在,则创建
* O_NOFOLLOW ==> 如果filename是软链接,则打开失败
* O_EXCL ==> 如果使用O_CREAT是文件存在,则可返回错误信息
*/
fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
if (fd < 0) {
if (errno == EACCES) {
abort();
}
return -1;
}
ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
if (ret < 0)
goto out;
if (ftruncate(fd, PA_SIZE) < 0)
goto out;
pa_size = PA_SIZE;
pa_data_size = pa_size - sizeof(prop_area);
compat_mode = false;
// mmap映射文件实现共享内存
pa = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (pa == MAP_FAILED)
goto out;
/*初始化内存地址中所有值为0*/
memset(pa, 0, pa_size);
pa->magic = PROP_AREA_MAGIC;
pa->version = PROP_AREA_VERSION;
pa->bytes_used = sizeof(prop_bt);
__system_property_area__ = pa;
close(fd);
return 0;
out:
close(fd);
return -1;
}
int __system_property_area_init()
{
return map_prop_area_rw();
}
typedef struct {
void *data;
size_t size;
int fd;
}workspace;
static int init_workspace(workspace *w, size_t size)
{
void *data;
int fd = open(PROP_FILENAME, O_RDONLY | O_NOFOLLOW);
if (fd < 0)
return -1;
w->size = size;
w->fd = fd;
return 0;
}
void __attribute__((constructor)) __libc_prenit(void);
void __libc_prenit(void)
{
// ...
__libc_init_common(elfdata); // 调用这个函数
// ...
}
__libc_init_common函数为:
void __libc_init_common(uintptr_t *elfdata)
{
// ...
__system_properties_init(); // 初始化客户端的属性存储区域
}
__system_properties_init函数有回到了我们熟悉的/bionic/libc/bionic/system_properties.c文件:
static int get_fd_from_env(void)
{
char *env = getenv("ANDROID_PROPERTY_WORKSPACE");
if (! env) {
return -1;
}
return atoi(env);
}
static int map_prop_area()
{
bool formFile = true;
int result = -1;
int fd;
int ret;
fd = open(property_filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
if (fd >= 0) {
/* For old kernels that don't support O_CLOEXEC */
ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
if (ret < 0)
goto cleanup;
}
if ((fd < 0) && (error == ENOENT)) {
fd = get_fd_from_env();
fromFile = false;
}
if (fd < 0) {
return -1;
}
struct stat fd_stat;
if (fstat(fd, &fd_stat) < 0) {
goto cleanup;
}
if ((fd_stat.st_uid != 0)
|| (fd_stat.st_gid != 0)
|| (fd_stat.st_mode & (S_IWGRP | S_IWOTH) != 0)
|| (fd_stat.st_size < sizeof(prop_area))) {
goto cleanup;
}
pa_size = fd_stat.st_size;
pa_data_size = pa_size - sizeof(prop_area);
/*
* 映射init创建的属性内存到本地进程空间,这样本地进程就可以使用这块共享内存了。
* 注意:映射时制定了PROT_READ属性,所以客户端进程只能读属性,不能设置属性。
*/
prop_area *pa = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
if (pa == MAP_FAILED) {
goto cleanup;
}
if ((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION && pa->version != PROP_AREA_VERSION_COMPAT)) {
munmap(pa, pa_size);
goto cleanup;
}
if (pa->version == PROP_AREA_VERSION_COMPAT) {
compat_mode = true;
}
result = 0;
__system_property_area__ = pa;
cleanup:
if (fromFile) {
close(fd);
}
return result;
}
int __system_properties_init()
{
return map_prop_area();
}
static int property_service_init_action(int nargs, char **args)
{
start_property_service();
return 0;
}
static void load_override_properties()
{
#ifdef ALLOW_LOCAL_PROP_OVERRIDE
char debuggable[PROP_VALUE_MAX];
int ret;
ret = property_get("ro.debuggable", debuggable);
if (ret && (strcmp(debuggable, "1") == 0)) {
load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
}
#endif
}
static void load_properties(char *data)
{
char *key, *value, *eol, *sol, *tmp;
sol = data;
while ((eol = strchr(sol, '\n'))) {
key = sol;
// 赋值下一行的指针给sol
*eol ++ = 0;
sol = eol;
value = strchr(key, '=');
if (value == 0) continue;
*value++ = 0;
while (isspace(*key)) key ++;
if (*key == '#') continue;
tmp = value - 2;
while ((tmp > key) && isspace(*tmp)) *tmp-- = 0;
while (isspace(*value)) value ++;
tmp = eol - 2;
while ((tmp > value) && isspace(*tmp)) *tmp-- = 0;
property_set(key, value);
}
}
int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
{
struct sockaddr_un addr;
int fd, ret;
char *secon;
fd = socket(PF_UNIX, type, 0);
if (fd < 0) {
ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", name);
ret = unlink(addr.sun_path);
if (ret != 0 && errno != ENOENT) {
goto out_close;
}
ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret) {
goto out_unlink;
}
chown(addr.sun_path, uid, gid);
chmod(addr.sun_path, perm);
return fd;
out_unlink:
unlink(addr.sun_path);
out_close:
close(fd);
return -1;
}
#define PROP_PATH_SYSTEM_BUILD "/system/build.prop"
#define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop"
#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
#define PROP_PATH_FACTORY "/factory/factory.prop"
void start_property_service(void)
{
int fd;
load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
load_override_properties();
/*Read persistent properties after all default values have been loaded.*/
load_persistent_properties();
fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);
if (fd < 0) return;
fcntl(fd, F_SETFD, FD_CLOEXEC);
fcntl(fd, F_SETFL, O_NONBLOCK);
listen(fd, 8);
property_set_fd = fd;
}
int main(int argc, char **argv)
{
// ...省略不相关代码
for (;;) {
// ...
for (i = 0; i < fd_count; i ++) {
if (ufds[i].fd == get_property_set_fd())
handle_property_set_fd();
}
}
}
void handle_property_set_fd()
{
prop_msg msg;
int s;
int r;
int res;
struct ucred cr;
struct sockaddr_un addr;
socklen_t addr_size = sizeof(addr);
socklen_t cr_size = sizeof(cr);
char *source_ctx = NULL;
// 接收TCP连接
if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
return;
}
// 接收客户端请求数据
r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
if (r != sizeof(prop_msg)) {
ERROR("sys_prop: mis-match msg size received: %d expected : %d errno: %d\n", r, sizeof(prop_msg), errno);
close(s);
return;
}
switch(msg.cmd) {
case PROP_MSG_SETPROP:
msg.name[PROP_NAME_MAX - 1] = 0;
msg.value[PROP_VALUE_MAX - 1] = 0;
if (memcmp(msg.name, "ctl.", 4) == 0) {
close(s);
if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) {
handle_control_message((char*) msg.name + 4, (char*) msg.value);
} else {
ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n", msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
}
} else {
if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) {
property_set((char *) msg.name, (char*) msg.value);
}
close(s);
}
break;
default:
close(s);
break;
}
}
int property_set(const char *name, const char *value)
{
prop_info *pi;
int ret;
size_t namelen = strlen(name);
size_t valuelen = strlen(value);
if (! is_legal_property_name(name, namelen)) return -1;
if (valuelen >= PROP_VALUE_MAX) return -1;
// 从属性空间中寻找是否已经存在该属性值
pi = (prop_info*) __system_property_find(name);
if (pi != 0) {
// ro开头的属性被设置后,不允许再被修改
if (! strncmp(name, "ro.", 3)) return -1;
__system_property_update(pi, value, valuelen);
} else {
ret = __system_property_add(name, namelen, value, valuelen);
}
// 有一些特殊的属性需要特殊处理,例如net.和persist.开头的属性
if (strncmp("net.", name, strlen("net.")) == 0) {
if (strcmp("net.change", name) == 0) {
return 0;
}
property_set("net.change", name);
} else if (persistent_properties_loaded && strncmp("persist.", name, strlen("persist.")) == 0) {
write_persistent_property(name, value);
}
property_changed(name, value);
return 0;
}
int property_set(const char *key, const char *value)
{
return __system_property_set(key, value);
}
struct prop_msg
{
unsigned cmd;
char name[PROP_NAME_MAX];
char value[PROP_VALUE_MAX];
};
typedef struct prop_msg prop_msg;
static int send_prop_msg(prop_msg *msg)
{
struct pollfd pollfds[1];
struct sockaddr_un addr;
socklen_t alen;
size_t namelen;
int s;
int r;
int result = -1;
s = socket(AF_LOCAL, SOCK_STREAM, 0);
if (s < 0) {
return result;
}
memset(&addr, 0, sizeof(addr));
namelen = strlen(property_service_socket);
strlcpy(addr.sun_path, property_service_socket, sizeof(addr.sun_path));
addr.sun_family = AF_LOCAL;
alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
if (TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen)) < 0) {
close(s);
return result;
}
r = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
close(s);
return result;
}
int __system_property_set(const char *key, const char *value)
{
int err;
prop_msg msg;
if (key == 0) return -1;
if (value == 0) value = "";
if (strlen(key) >= PROP_NAME_MAX) return -1;
if (strlen(value) >= PROP_VALUE_MAX) return -1;
memset(&msg, 0, sizeof(msg));
msg.cmd = PROP_MSG_SETPROP;
strlcpy(msg.name, key, sizeof(msg.name));
strlcpy(msg.value, value, sizeof(msg.value));
err = send_prop_msg(&msg);
if (err < 0) {
return err;
}
return 0;
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有