AndroidSystemProperties設定/読み取り--prop



Android Systemproperties Set Read Prop



ガイドパッケージ
android.os.SystemPropertiesをインポートします

2. AndroidSystemPropertiesの設定/読み取り
#設定
Systemproperties.set(name、value);




Systemproperties.get(name);

システムプロパティを設定するプログラムには、システム権限またはルート権限も必要です。



Androidプログラムのアクセス許可をシステムのアクセス許可にアップグレードするにはどうすればよいですか?方法は次のとおりです。

1. AndroidManifest.xmlで、android:sharedUserId = 'android.uid.system'をマニフェストに追加します。

2. Android.mkで、LOCAL_CERTIFICATE:= XXXをLOCAL_CERTIFICATE:= platformに変更します。



上記の2つの手順を実行した後、ap権限をシステム権限にアップグレードできます。ただし、この方法を使用して権限を向上させることには、次の2つの欠点があります。

1、プログラムの所有者はプログラムのソースコードを持っている必要があります

2、プログラムの所有者は、Android開発環境も持っている必要があります。つまり、Androidシステム全体を作成できます。

一般的に、これら2つのポイント、基本的には開発者が実行できます。

2.Androidシステムプロパティ(SystemProperties)設定分析

Androidのシステムプロパティは、ファイル保存の永続プロパティと各起動のキャッシュプロパティの2つの部分で構成されています。

前者は主に次のファイルに保存されます。
android属性の名前には、次のような特定の形式要件があることに注意してください。プレフィックスは、system core init property_service.cで定義されているプレフィックスを使用する必要があります。
bionic / libc / include / sys / _system_properties.h

#define PROP_SERVICE_NAME'property_service '
#define PROP_PATH_RAMDISK_DEFAULT '/ default.prop'
#define PROP_PATH_SYSTEM_BUILD '/ system / build.prop'
#define PROP_PATH_SYSTEM_DEFAULT '/ system / default.prop'
#define PROP_PATH_LOCAL_OVERRIDE '/ data / local.prop'

後者は、frameworks / base / core / java / android / os /SystemProperties.javaのインターフェースによって定義されます。
プライベート静的ネイティブ文字列native_get(文字列キー)
プライベート静的ネイティブ文字列native_get(String key、String def)
プライベート静的ネイティブvoidnative_set(String key、String def)
public static void set(String key、String val){
if(key.length()> PROP_NAME_MAX){
新しいIllegalArgumentException( 'key.length>' + PROP_NAME_MAX)をスローします
}
if(val!= null && val.length()> PROP_VALUE_MAX){
新しいIllegalArgumentException( 'val.length>' +をスローします
PROP_VALUE_MAX)
}
native_set(key、val)
}

インターフェイスクラスは、対応するcppインターフェイスandroid_os_SystemProperties.cppを初期化ランタイム環境に登録し、実際の操作では、JNIを介してcppファイルに対応するインターフェイスを呼び出します。
http://blog.csdn.net/ameyume/article/details/8056492
フレームワーク/ベース/コア/jni/AndroidRuntime.cpp

名前空間android {
extern int register_android_os_SystemProperties(JNIEnv * env)

}
////////////////////////////////////////////////// // //////////////////////////////

Androidシステムプロパティ
多くのコードがあります:SystemProperties.set()/ SystemProperties.get()
システムのプロパティは、これら2つのインターフェイスを介して読み取り/設定できます。
名前が示すように、システムプロパティは間違いなくグローバルに共有されます。通常、プログラムの実行は、プロセスに関して互いに独立しています。グローバル共有を実現する方法は?
システムプロパティとは何ですか?どのように実装されますか?
属性システムはAndroidの重要な機能です。これはサービスとして実行され、システム構成とステータスを管理します。これらの構成と状態はすべてプロパティです。
各属性は、タイプが文字列であるキーと値のペアです。
これらの属性は、一部のリソースの使用状態、プロセスの実行状態、システムの固有のプロパティなどです。
adbシェルによって命令することができます:

Getpropは、電話のすべての属性ステータス値を調べます。

または、getprop init.svc.bootanimを使用して、属性のステータスを表示します

setprop init.svc.bootanimstartを使用して属性の状態を設定します

特別なプロパティ:

属性名が「ro。」で始まる場合、この属性は読み取り専用属性として扱われます。一度設定すると、属性値は変更できません。

プロパティ名が「persist。」で始まる場合、このプロパティが設定されると、その値も/ data / propertyに書き込まれます。

属性名が「net。」で始まる場合、この属性が設定されると、「net.change」属性が自動的に設定され、最後に変更された属性名に追加されます。

(これは非常に賢いです。netresolveモジュールはこのプロパティを使用して、net。*プロパティの変更を追跡します。)

プロパティ「ctrl.start」および「ctrl.stop」は、サービスを開始および停止するために使用されます。各サービスは/init.rcで定義する必要があります。システムが起動すると、initで保護されます。

プロセスはinit.rcを解析し、プロパティサービスを開始します。 'ctrl.start'プロパティを設定するリクエストを受信すると、プロパティサービスはそのプロパティ値をサービスとして使用します

サービスに名前を付けて、サービスを開始します。このサービスの起動結果は、「init.svc」に配置されます。属性。クライアントアプリケーションは、そのプロパティ値をポーリングして結果を判断できます。

2番目のフレームワークアクセスシステムサービスプロセス
フレームワークは、SystemPropertiesインターフェイスを使用して、SystemPropertiesを介してシステムプロパティにアクセスします。

フレームワーク base core java android os SystemProperties.java:

パブリッククラスSystemProperties
{{
// JNI
プライベート静的ネイティブ文字列native_get(String key、String def)
プライベート静的ネイティブvoidnative_set(String key、String def)

public static String get(String key、String def){
native_get(key、def)を返します
}

public static void set(String key、String val){
native_set(key、val)
}
}

Jniコードの場所:

frameworks base core jni android_os_SystemProperties.cpp

システムプロパティの取得ブロッキングメソッド:

static jstring SystemProperties_getSS()
{{
len = property_get(key、buf、 '')
}
操作は bionic libc bionic system_properties.cにあります。

int __system_property_get(const char * name、char * value)
{{
//データはすでにメモリに保存されています__system_property_area__読み取りが戻るのを待っています
const prop_info * pi = __system_property_find(name)
戻り値__system_property_read(pi、0、value)
}
プロセスの開始後、データはシステムプロパティデータを対応する共有メモリに読み込み、グローバル変数__system_property_area__に保存します。

プロセスは独立していますが、システムプロパティデータは現在のプロセススペースにどのように読み込まれますか?フォローアップ紹介。

プロパティ非同期ソケット通信を設定します。

int __system_property_set(const char * key、c​​onst char * value)
{{
msg.cmd = PROP_MSG_SETPROP
strlcpy(msg.name、key、sizeof msg.name)
strlcpy(msg.value、value、sizeof msg.value)
err = send_prop_msg(&msg)
}

static int send_prop_msg(prop_msg * msg)
{{
//ソケット通信/ dev / socket / property_service
s = socket(AF_LOCAL、SOCK_STREAM、0)
connect(s、(struct sockaddr *)&addr、alen)
send(s、msg、sizeof(prop_msg)、0)
閉じる
}

ソケットを介してproperty_serviceにメッセージを送信します。 property_serviceはどこで実行されていますか?

Three PropertyServiceはサーバーソケットを作成します
initプロセスがリッスンを開始します: system core init Init.c

コードをコピーする
コードをコピーする
int main(int argc、char ** argv)
{{
//アクションキューに追加します
queue_builtin_action(property_service_init_action、 'property_service_init')
ために()
//アクションキューを実行します
//ソケットを介してプロパティサービスに送信されたデータを受信します
nr = poll(ufds、fd_count、timeout)
……
handle_property_set_fd()
}

static int property_service_init_action(int nargs、char ** args)
{{
start_property_service()

}

system core init property_service.c:
void start_property_service(void)
{{
//プロパティ構成ファイルをロードします
load_properties_from_file(PROP_PATH_SYSTEM_BUILD)
load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT)
load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE)
load_persistent_properties()

//ソケットリソースを作成してバインドします
fd = create_socket(PROP_SERVICE_NAME、SOCK_STREAM、0666、0、0)
//聴く
listen(fd、8)
}

プロパティサービスは、initデーモンで実行されます。

メッセージを実行した後でも、プロパティサービス全体がどのように実装されているかを理解する必要がありますか。

プロパティサービスがメッセージを受信した後の処理を最初に確認します。

Four PropertyServiceはソケット処理をリッスンします
プロパティサービスは、ソケットメッセージ処理をリッスンします。

void handle_property_set_fd()
{{
//通信の確立を待ちます
s = accept(property_set_fd、(struct sockaddr *)&addr、&addr_size)

//ソケット関連情報を取得するuidgid
Getsockopt(s、SOL_SOCKET、SO_PEERCRED、&cr、&cr_size)
//プロパティ設定要求メッセージを受信します
recv(s、&msg、sizeof(msg)、0)
//メッセージを処理しています
switch(msg.cmd){
ケースPROP_MSG_SETPROP:
// ctlを処理しています。システムプロパティを設定する
if(memcmp(msg.name、 'ctl。'、4)== 0)
{{
//権限の検出
if(check_control_perms(msg.value、cr.uid、cr.gid))
{{
handle_control_message((char *)msg.name + 4、(char *)msg.value)
}
} そうしないと
{{
//システムプロパティ値を変更します
if(check_perms(msg.name、cr.uid、cr.gid))
{{
property_set((char *)msg.name、(char *)msg.value)
}
}
ブレーク
}
閉じる
}

システムプロパティを設定して、サービスを開始/終了します。

当局の判断:

static int check_control_perms(const char * name、unsigned int uid、unsigned int gid)
{{
//システム/ rootユーザーは直接アクセスできます
if(uid == AID_SYSTEM || uid == AID_ROOT)
戻り値1

//ユーザーリストをクエリして、テーブルがあり、対応する権限があるかどうかを判断します
for(i = 0 control_perms [i] .service i ++){
if(strcmp(control_perms [i] .service、name)== 0){
if((uid && control_perms [i] .uid == uid)||
(gid && control_perms [i] .gid == gid)){
戻り値1
}
}
}
0を返す
}

したがって、アプリにネイティブサービスを開始/閉じる権限を付与する場合は、次のようにします。

システム/ root権限が必要

対応するアプリケーションuidgidを見つけて、アプリ名をcontrol_permsリストに追加します。

メッセージの処理システムプロパティの開始/停止を設定することにより、サービスの実行状態を変更できます。

void handle_control_message(const char * msg、const char * arg)
{{
if(!strcmp(msg、 'start')){
msg_start(arg)
} else if(!strcmp(msg、 'stop')){
msg_stop(arg)
} else if(!strcmp(msg、 'restart')){
msg_stop(arg)
msg_start(arg)
}
}

static void msg_start(const char * name)
{{
service_start(svc、args)
}
void service_start(struct service * svc、const char * dynamic_args){
//プロセス開始サービスを作成します
pid = fork()
execve(svc-> args [0]、(char **)svc-> args、(char **)ENV)

//サービスのシステムプロパティを変更します。実行状況
notify_service_state(svc-> name、 'running')
}

前面に接続されているのは、ctr.startおよびctr.stopシステムプロパティです。サービスの開始と停止に使用されます。

例えば:

//ブートアニメーションを開始します

property_set( 'ctl.start'、 'bootanim')

init.rcで、サービスが起動時に開始されるかどうかを示します。

サービスadbd / sbin / adbd
クラスコア
無効//自動的に起動しない

サービスを開始すると、次のように判断します。

static void service_start_if_not_disabled(struct service * svc)
{{
//開始するかどうかを判断します
if(!(svc-> flags&SVC_DISABLED)){
service_start(svc、NULL)
}
}

システムプロパティ値の変更:

static int check_perms(const char * name、unsigned int uid、unsigned int gid)
{{
//権限の検出
for(i = 0 property_perms [i] .prefix i ++){
int tmp
if(strncmp(property_perms [i] .prefix、name、
strlen(property_perms [i] .prefix))== 0){
if((uid && property_perms [i] .uid == uid)||
(gid && property_perms [i] .gid == gid)){
戻り値1
}
}
}

0を返す
}

この変更されたシステムプロパティのアクセス許可テーブルを見てください。

property_perms [] = {
{'net.dns'、AID_RADIO、0}、
{'net。'、AID_SYSTEM、0}、
{'dev。'、AID_SYSTEM、0}、
{'ランタイム。'、AID_SYSTEM、0}、
{'sys。'、AID_SYSTEM、0}、
{'サービス。'、AID_SYSTEM、0}、
{'persist.sys。'、AID_SYSTEM、0}、
{'persist.service。'、AID_SYSTEM、0}、
……
{NULL、0、0}
}

特定のユーザーを指定して、いくつかのプレフィックスを付けてシステムプロパティの値を変更します。

基本的に本物件の基本的なワークフロー、本物件サービスの内部運用の実施方法、運用・運用、

クロスプロセスの虚数メモリなどの問題に対処する方法はまだクリアされていません。

5属性システム設計
属性システムの上部構造を以下に示します。

プロパティサービスはinitプロセスで実行され、ブートローダーはプロパティファイルから共有メモリにロードされます。システムプロパティは、ソケットを介してプロパティサービスと通信するように設定されています。

プロパティコンシューマープロセスは、システムプロパティ値の共有メモリを現在のプロセス仮想空間にロードして、システムプロパティ値を読み取ります。

プロパティセッタープロセスは、システムプロパティを変更し、ソケットを介してプロパティサービスにメッセージを送信し、システムプロパティ値を変更します。

6つの属性システムの実装
システム設計の属性となる鍵は、プロセス間での共有メモリの実装です。

プロパティシステムの実装の特定のプロセスを見てみましょう。

プロセス実行の初期化:

int main(int argc、char ** argv){
//プロパティシステム初期化関数をアクションキューに追加します
queue_builtin_action(property_init_action、 'property_init')
ために()
}

static int property_init_action(int nargs、char ** args)
{{
property_init(load_defaults)
}

プロパティサービスを初期化します。

system core init property_service.c

void property_init(bool load_defaults)
{{
//共有メモリスペースを初期化します
init_property_area()
//プロパティファイルをロードします
load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT)
}

共有メモリスペースを初期化します。

static int init_property_area(void)
{{
//匿名メモリスペースを作成しますPA_SIZE = 32768
init_workspace(&pa_workspace、PA_SIZE)
//メモリ領域を2つの部分に分割します:属性システムの基本情報と属性キーと値のペア
pa_info_array =(void *)(((char *)pa_workspace.data)+ PA_INFO_START)

//属性システム情報を初期化します
pa = pa_workspace.data
memset(pa、0、PA_SIZE)
pa-> magic = PROP_AREA_MAGIC
pa-> version = PROP_AREA_VERSION

/ * libプロパティサービスにプラグインします* /
__system_property_area__ = pa
}

__system_property_area__:

各プロセスがこの変数を使用し、システムプロパティの共有メモリ領域をポイントし、システムプロパティにアクセスすることが重要です。

bionic libc bionic system_properties.cにあり、bionicライブラリに属しています。各プロセスが共有メモリをロードする方法については、後で説明します。

ファイルを共有メモリとしてマップして、スペースメモリの使用量を処理します。

static int init_workspace(workspace * w、size_t size)

// devはtmpfsは仮想メモリファイルシステムです
int fd = open( '/ dev / __ properties __'、O_RDWR

システムプロパティのデフォルトデータファイルをロードします。

#define PROP_PATH_RAMDISK_DEFAULT '/ default.prop'
static void load_properties_from_file(const char * fn)
{{
//システムプロパティキー値を読み取り、共有メモリにデータを書き込みます
データ= read_file(fn、&sz)
load_properties(data)
}

上記に加えて:プロパティサービスソケットリソースの作成、ソケット通信接続設定システムプロパティをリッスンするために、

プロパティサービスは、初期化プロセスで初期化を完了しました。

メモリ領域のデータ構造が取得されます。

7つのプロセス共有システム属性メモリ空間の実装
プロパティサービスはinitプロセスで実行され、ファイルをマッピングして共有メモリスペースを作成しますが、システム全体では、

他のプロセスもこのメモリマップを現在のプロセススペースに読み込むことができますが、どのように実現されますか?

サービスプロセスの起動:共有メモリスペースのfdサイズを環境変数として新しく作成されたプロセスに渡します

void service_start(struct service * svc、const char * dynamic_args)
{{
//プロセスを作成します
pid = fork()

if(pid == 0){
if(properties_inited()){
//システムプロパティスペースファイルの説明を取得します
get_property_workspace(&fd、&sz)
//利用可能な最小のファイル記述子を複製します
sprintf(tmp、 '%d、%d'、dup(fd)、sz)
// ANDROID_PROPERTY_WORKSPACE環境変数をENVに追加します
//共有メモリfdを含める
add_environment( 'ANDROID_PROPERTY_WORKSPACE'、tmp)
}
//プログラムを実行する環境変数ENVを渡す
execve(svc-> args [0]、(char **)svc-> args、(char **)ENV)
//サービスシステムのプロパティを設定します
notify_service_state(svc-> name、 'running')
}
}

void get_property_workspace(int * fd、int * sz)
{{
* fd = pa_workspace.fd
* sz = pa_workspace.size
}

共有メモリスペースのfdサイズが環境変数として新しく作成されたプロセスに渡された後、どこで使用されますか?

システムプロパティのメモリ空間を現在のプロセス仮想空間にマップします。

プロセスが開始すると、ダイナミックライブラリbioniclibcライブラリがロードされます。

bionic libc bionic libc_init_dynamic.c:

void __attribute __((constructor))__ libc_preinit(void)

GCCのコンストラクタ/デストラクタ属性によると:

関数にコンストラクタまたはデストラクタを与えます。ここで、mainが実行を開始する前にコンストラクタが呼び出されます。

デストラクタは、メイン関数が終了した後に呼び出されます。複数のコンストラクタまたはデストラクタがある場合は、各コンストラクタを指定できます

または、デストラクタが優先されます。コンストラクターの場合、優先度の値が小さいほど、実行が早くなります。デストラクタは反対です。

複数のコンストラクターに優先順位を付ける必要があります。

__attribute __((constructor(1)))void func1()
{{
printf( 'fooのコンストラクター内 n')
}
__attribute __((constructor(2)))void func2()
{{
printf( 'foo1のコンストラクター内 n')
}
__attribute __((destructor))void bar()
{{
printf( 'バーのコンストラクター内 n')
}

__libc_preinitは、bioniclibcライブラリがロードされたときに呼び出されます。

void __libc_preinit(void)
{{
__libc_init_common(elfdata)
}

void __libc_init_common(uintptr_t * elfdata)
{{
__system_properties_init()
}

int __system_properties_init(void)
{{
prop_area * pa int s、fd unsigned sz char * env
//環境変数ANDROID_PROPERTY_WORKSPACEを取得します
//上記のinitプロセス設定に対応します
env = getenv( 'ANDROID_PROPERTY_WORKSPACE')
//共有メモリファイル記述子メモリサイズ
fd = atoi(env)
sz = atoi(env + 1)
//ファイル記述子を共有メモリの現在のプロセス仮想空間メモリにマップします
pa = mmap(0、sz、PROT_READ、MAP_SHARED、fd、0)
//グローバル変数は共有システム属性メモリの最初のアドレスを指します
__system_property_area__ = pa
}

これは、システムプロパティ全体のアクセスの相互作用と実装プロセスです。ソースコードを参照してください。

リファレンスドキュメント:

http://blog.chinaunix.net/uid-20459533-id-3168973.html

http://www.cnblogs.com/simonshi/archive/2010/04/08/1707516.html

http://blog.csdn.net/zhangchiytu/article/details/7539101

Androidプロパティbuild.prop生成プロセス:
http://www.cnblogs.com/bastard/archive/2013/02/28/2937014.html