Android Property System


Android Property System
属性システムはandroidの重要な特性である.サービスとして動作し、システムの構成とステータスを管理します.これらの構成とステータスはすべて属性です.各プロパティはキー値ペア(key/value pair)で、そのタイプは文字列です.
機能的にはwindowsシステムのレジストリによく似ています.多くのandroidアプリケーションおよびライブラリは、このプロパティに直接または間接的に依存し、実行時の動作を決定します.たとえば、adbdプロセスクエリープロパティサービスは、シミュレータ環境で現在実行されているかどうかを確認します.もう一つの例はjavaです.io.File.pathSpearatorは、属性サービスに格納されている値を返します.
プロパティシステムがどのように動作するか
プロパティシステムの上位アーキテクチャを下図に示します.
図には、3つのプロセス、永続プロパティファイルのセット、共有メモリ領域があります.共有メモリ領域は、すべての属性レコードの格納場所です.共有メモリ領域は、永続ファイルから属性レコードをロードし、共有メモリに保存するプロパティ・サービス・プロセスのみに書き込むことができます.
consumerプロセスは、共有メモリを自身の仮想アドレス空間にロードし、これらのプロパティに直接アクセスします.setterプロセスは、共有メモリを自身の仮想アドレス空間にロードしますが、メモリを直接書くことはできません.setterが属性を追加または更新しようとすると、unix domain socketを介して属性サービスに送信されます.プロパティ・サービスはsetterプロセスを表し、共有メモリと永続ファイルにプロパティを書き込みます.(疑問1.共有メモリを自身の仮想アドレスにロードする方法;2.setterプロセスはなぜ共有メモリを自身の仮想アドレスにロードするのか)
プロパティ・サービスはinitプロセスで実行されます.Initプロセスは、まず共有メモリ領域を作成し、その領域を指す記述子fdを保存する.Initプロセスはこの領域をMAP_を使用して通過しましたSHAREDフラグのmmapはそれ自身の仮想アドレス空間にマッピングされ、このようにして、この領域に対する更新はすべてのプロセスに対して可視である.fdと領域サイズはANDROIDという名前で格納されるPROPERTY_WORKSPACEの変数にあります.consumerやsetterなどの他のプロセスは、この変数を使用してfdとサイズを取得し、mmapという領域を自身の仮想アドレス空間に配置することができます.この共有メモリ領域を下図に示します.
その後、initプロセスは次のファイルからプロパティをロードします.
/default.prop/system/build.prop/system/default.prop/data/local.prop
次に、プロパティ・サービスを開始します.このステップでは、unix domain socketサービスが作成されます.このsocketのパスは/dev/socket/property_です.サービスは、他のクライアントプロセスについてよく知られています.最後に、initプロセスはpollを呼び出してsocket上の接続イベントを待つ.
consumer側では、libc(bionic/libc/bionic/libc_common.c__libc_init_common関数)を初期化すると、環境変数からfdとサイズが返され、共有メモリが自身のアドレス空間にマッピングされる(bionic/libc/bionic/system_properties.c__system_properties.c__properties_init関数).その後libcutilsは、通常のメモリを読み出すようにconsumerのプロパティを読み出すことができます.
現在、属性は削除できません.すなわち,属性を追加すると削除できず,キーも変更できない.
プロパティの読み込み/設定方法
Androidにはget/setプロパティに3つの主要なルートがあります.
1、  native code
ローカルアプリケーションを作成する場合はproperty_を使用します.getとproperty_setこの2つのAPIは、プロパティを読み取り/設定します.それらを使用するにはinclude cutils/propertiesが必要です.h、libcutilsライブラリをリンクします.
2、  java code
Javaパッケージ(java.lang.System)にSystemを提供する.getPropertyとSystem.setPropertyメソッド.しかしながら、この2つのAPIは、native関数と意味的に同等であるにもかかわらず、データを全く異なる位置に格納することに注目すべきである.実際、dalvik VMは、これらのプロパティを格納するためにハッシュ・テーブルを使用します.したがって,この2つのAPIで格納される属性は独立しており,native属性にアクセスできず,逆も同様である.
しかしAndroidには内部隠蔽クラス(@hide,SDKには見えない)androidがある.os.SystemPropertiesはnativeプロパティを操作します.jniによってnativeプロパティライブラリにアクセスします.
3、shellスクリプト
Androidはgetpropとsetpropコマンドラインツールを提供し、プロパティを取得および更新します.それはlibcutils実装に依存する.
getprop<属性名>setprop<属性名><<属性値>
 
特別属性属性属性名が「ro.」の場合最初は、このプロパティは読み取り専用プロパティとみなされます.設定すると、属性値は変更できません.属性名が「persist.」の場合最初に、このプロパティを設定すると、その値も/data/propertyに書き込まれます.属性名が「net.」の場合最初に、このプロパティを設定すると、「net.change」プロパティが自動的に設定され、最後に変更したプロパティ名に追加されます.(これは巧みです.netresolveモジュールは、net.*属性の変化を追跡するためにこの属性を使用します.)プロパティ「ctrl.start」および「ctrl.stop」は、サービスを開始および停止するために使用されます.各サービスは/initでなければなりません.rcで定義する.システムが起動すると、initデーモンとinitが解析されます.rcとプロパティサービスを開始します.「ctrl.start」プロパティの設定を要求されると、プロパティ・サービスはこのプロパティ値をサービス名として使用してサービスを見つけ、サービスを開始します.このサービスの開始結果は「init.svc.<サービス名>」プロパティに格納されます.クライアント・アプリケーションは、そのプロパティ値をポーリングして結果を決定できます.
 
補足:propertyを表示するservice.c、私たちは以下の事実を明確にすることができます.
1、属性名は勝手に取ったものではありません.property_perms配列には、現在のシステムで使用可能なすべての属性の接頭辞と、対応するアクセス権限UIDが定義されています.プロパティの設定は、権限要件を満たし、これらの定義の範囲内で名前を付けます.
2、  PA_COUNT_MAXは、システム(共有メモリ領域)が最大でどれだけの属性を格納できるかを指定します.
3、  PROP_NAME_MAXは1つの属性のkey最大許容長を指定する.PROP_VALUE_MAXはvalueの最大許容長を指定します.
また、http://blog.csdn.net/tekkamanitachi/archive/2009/06/18/4280982.aspxこの文章はAndroidの公式ドキュメントを翻訳し、別の角度から属性システムを述べています.必要な人は参照してください.
 
4、keyのvalueを設定する場合、認証を行う必要があり、設定プログラムが存在するプロセスのfdに基づいてuid値を知る必要がある.例えば、system serverプロセスはnetヘッダのkeyを設定することができ、gsmヘッダのkeyを設定することはできない.関連する定義は以下の通りである.
5、Androidのシステム属性には、ファイルに保存されている永続属性と、電源を入れるたびにインポートされるcache属性の2つの部分が含まれています.(cacheプロパティは、起動初期化プログラム時にsetpropを呼び出すなど、永続プロパティとしても理解できます).プログラムで設定したプロパティはtempプロパティ(自分で理解)と呼ぶべきで、メモリに保存されているので、電源を入れるたびに空になります.
 
Androidシステム属性の命名方法:
Android属性用Systempropertiesを作成して変更する.set(name,value),android属性用Systempropertiesを取得する.get(name)、android属性の名前には一定のフォーマット要件があります.接頭辞はsystemcoreinitproperty_を使用する必要があります.service.cで定義された接頭辞は、システム属性設定を行うプログラムにも対応するプロセス権限が必要である.
androidプログラムの権限をsystem権限に上げるにはどうすればいいですか?方法は次のとおりです.
1、AndroidManifest.xmlでは、manifestにandroid:sharedUserId="android.uid.system"を追加します.
2、Android.mkでLOCAL_をCERTIFICATE:=XXXをLOCAL_に変更CERTIFICATE := platform .
以上の2つのステップでapの権限をsystem権限に昇格させることができます.しかし、この方法で権限を向上させるには、次の2つの弊害があります.
1、プログラムの所有にはプログラムのソースコードが必要である.
2、プログラムの所有はandroid開発環境が必要で、つまり自分がandroidシステム全体をmakeすることができる.
---------
私が変更したのはContactsで、権限を加えた後、明らかに2つの問題があることを発見しました.SynSimServiceを起動した時にwithout permission private to packageと言ったが、分からなかった.2.データベースの読み込み中に異常が発生し、最初はContactsがsystemプロセスに変更されたのか、ContactsProviderがcomなのかが疑われた.uid.sharedプロセス、ContactsProviderをcomに変更します.uid.System、結果は相変わらず、ヒント:
01-0100:15:10.270: ERROR/DatabaseUtils(1319): Writing exception to parcel
01-0100:15:10.270: ERROR/DatabaseUtils(1319):java.lang.UnsupportedOperationException: Only CrossProcessCursor cursors aresupported across process for now
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    atandroid.database.CursorToBulkCursorAdaptor.<init>(CursorToBulkCursorAdaptor.java:97)
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    atandroid.content.ContentProvider$Transport.bulkQuery(ContentProvider.java:155)
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    atandroid.content.ContentProviderNative.onTransact(ContentProviderNative.java:111)
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    at android.os.Binder.execTransact(Binder.java:288)
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    at dalvik.system.NativeStart.run(Native Method)
01-0100:15:10.270: ERROR/DatabaseUtils(1319): Caused by:java.lang.ClassCastException:com.android.providers.contacts.ContactsProvider2$3
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    atandroid.database.CursorToBulkCursorAdaptor.<init>(CursorToBulkCursorAdaptor.java:81)
01-0100:15:10.270: ERROR/DatabaseUtils(1319):    ... 4 more
01-0100:15:10.280: WARN/AsyncQuery(1311): java.lang.UnsupportedOperationException:Only CrossProcessCursor cursors are supported across process for now

この問題を理解するために、裏口を開けましょう.
/system/core/init/prepery_service.c
static int check_perms(const char *name, unsigned int uid, unsigned int gid)
{
    int i;
    if (uid == 0)
        return 1;

    if(!strncmp(name, "ro.", 3))
        name +=3;
    /*      ,    UID,           ,         begin*/
    if(!strcmp(name, "xxx.yyy")){
    	return 1;
    }
    /*end*/
    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)) {
                return 1;
            }
        }
    }

    return 0;
}