Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android-init進程(2)

Android-init進程(2)

編輯:關於Android編程

init屬性服務就好比windows的注冊表,應用可以對其應用信息進行屬性操作

以下介紹屬性服務的原理:


屬性關鍵方法:
*void property_init(void)>>分析
void property_init(void)
{
    init_property_area();
}
static int init_property_area(void)
{
	prop_area *pa;
	//創建共享內存
	if(init_workspace(&pa_workspace, PA_SIZE))
        return -1;
	/**設置空間大小等其他信息*/
	//系統自動調用__libc_prenit函數,完成共享內存到本地進程的工作
	__system_property_area__ = pa;
}

//通知其他進程
void __libc_preinit(void)
{
	__libc_init_common(elfdata);
}
void __libc_init_common(uintptr_t *elfdata)
{
	__system_properties_init();
}
int __system_properties_init(void)
{
	//取出init創建環境變量獲得文件描述符
	env = getenv("ANDROID_PROPERTY_WORKSPACE");
    fd = atoi(env);
	//映射 init創建的內存到本地進程空間
	//這樣其他進程就可以共享這個內存了
	//在這裡 客戶端只能做讀取的操作
	pa = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0);
}

*void start_property_service(void)>>分析

1)加載屬性文件到屬性空間裡面去 同時創建scoket

*void start_property_service(void)
{
	//加載屬性文件
	load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
    load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
    load_override_properties();
	//加載持久化文件
    load_persistent_properties();
	//創建socket
	fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);
}

init.c::int main(){
	nr = poll(ufds, fd_count, timeout);
	if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
				}
	}
}

2)main函數等待其他進程對該scoket調用並做出處理 修改屬性
void handle_property_set_fd()
{
	//接收scoket
    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
        return;
    }

    //取出進程的權限屬性
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s); 
        return;
    }
	
	//接收數據
	r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
	
	if(memcmp(msg.name,"ctl.",4) == 0) {
            // ctl.* 控制消息
	    //如setprop  ctl.start bootanim
            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);
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",cr.uid, msg.name);
            }
    }
	 
}

int property_set(const char *name, const char *value)
{
	prop_info *pi = (prop_info*) __system_property_find(name);
	
	if(pi != 0) {
        /* ro.* properties 只讀屬性 不能設置 */
        if(!strncmp(name, "ro.", 3)) return -1;
		//更新屬性
        update_prop_info(pi, value, valuelen);
    } else {
        //增加屬性最多247項
    }
	//處理持久屬性/net.*/
	.....................
	//修改屬性同時執行的操作
	property_changed(name, value);
}

3)客戶端創建scoket請求
//Android提供System.getProperty來獲得屬性服務。 以下以android2.3為例
/**SystemProperties.java*/

private static native String native_get(String key);

    public static String get(String key) {
        if (key.length() > PROP_NAME_MAX) {
            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
        }
        return native_get(key);
    }

/**jni調用部分采用動態注冊的 android_os_SystemProperties.cpp*/
static JNINativeMethod method_table[] = {
		{ "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
		  (void*) SystemProperties_getS },
		  
		  .......//省略部分代碼
		}
	}
	static jstring SystemProperties_getS(JNIEnv *env, jobject clazz,jstring keyJ)
	{
		return SystemProperties_getSS(env, clazz, keyJ, NULL);
	}


	static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz,jstring keyJ, jstring defJ)
	{
		int len;
		const char* key;
		char buf[PROPERTY_VALUE_MAX];
		jstring rvJ = NULL;
		
		.............//省略部分代碼
		
		key = env->GetStringUTFChars(keyJ, NULL);
		
		len = property_get(key, buf, "");
		//構造獲得的屬性
		rvJ = env->NewStringUTF(buf);
		.............
	}

/**Properties.c*/ //查看property_get獲取屬性服務源碼
int property_get(const char *key, char *value, const char *default_value)
	{
		char sendBuf[1+PROPERTY_KEY_MAX];
		char recvBuf[1+PROPERTY_VALUE_MAX];
		int len = -1;
		...............
		//執行init函數獲取屬性
		pthread_once(&gInitOnce, init);
		...............
		return len;
	}


	static void init(void)
	{
		................
		gPropFd = connectToServer(SYSTEM_PROPERTY_PIPE_NAME);
		................
	}


	static int connectToServer(const char* fileName)
	{
		int sock = -1;
		int cc;
		struct sockaddr_un addr;
		.................
		/* connect to socket; fails if file doesn't exist */
		//采用TCP連接服務器 定義地址和協議族AF_UNIX
		strcpy(addr.sun_path, fileName);    // max 108 bytes
		addr.sun_family = AF_UNIX;
		cc = connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
		if (cc < 0) {
			close(sock);
			return -1;
		}
		return sock;
	}


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved