2011年06月29日

Androidのsystem propertyの保存が効かない。(解決)

Androidのinitのソースを読むと、"persist."で始まるkeyのpropertyはファイルに保存されて、次回以降の電源投入時にもその値は保持されるようになっています。

しかし、実際にやってみたらうまくいきません。この件を調べてみました。



system propertyの保存

"persist."で始まるkeyのpropertyは書き込みのときに特別扱いされています。PERSISTENT_PROPERTY_DIR(=/data/property)にkeyをファイル名とするファイルにvalueの内容が書き込まれます。

実際にやってみると、確かに/data/propertyのディレクトリにそれらしいファイルが作成されています。しかし、resetして再度動かして、getpropコマンドでsystem propertiesの一覧を見ても該当するpropertyがありません。

デバッガで追いかけてみる

initが起動して/data/propertyのディレクトリから値を読むところをデバッガで追いかけてみました。

system/core/init/property_service.c 

static void load_persistent_properties()
{
    DIR* dir = opendir(PERSISTENT_PROPERTY_DIR);
    struct dirent*  entry;
    char path[PATH_MAX];
    char value[PROP_VALUE_MAX];
    int fd, length;

    if (dir) {
        while ((entry = readdir(dir)) != NULL) {
            if (strncmp("persist.", entry->d_name, strlen("persist.")))
                continue;
#if HAVE_DIRENT_D_TYPE
             if (entry->d_type != DT_REG)
                continue;
#endif
            /* open the file and read the property value */
            snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, entry->d_name);
            fd = open(path, O_RDONLY);
            if (fd >= 0) {
                length = read(fd, value, sizeof(value) - 1);
                if (length >= 0) {
                    value[length] = 0;
                    property_set(entry->d_name, value);
                } else {
                    ERROR("Unable to read persistent property file %s errno: %d\n", path, errno);
                }
                close(fd);
            } else {
                ERROR("Unable to open persistent property file %s errno: %d\n", path, errno);
            }
        }
        closedir(dir);
    } else {
        ERROR("Unable to open persistent property directory %s errno: %d\n", PERSISTENT_PROPERTY_DIR, errno);
    }

    persistent_properties_loaded = 1;
}

entry->d_typeにDT_REGでなく0が入っているためにループがcontinueされてしまっていました。

0というのはDT_UNKNOWNです。

マニュアルで調べる

簡単にオンラインマニュアルで調べてみます。

$ man readdir
       On Linux, the dirent structure is defined as follows:

           struct dirent {
               ino_t          d_ino;       /* inode number */
               off_t          d_off;       /* offset to the next dirent */
               unsigned short d_reclen;    /* length of this record */
               unsigned char  d_type;      /* type of file; not supported
                                              by all file system types */
               char           d_name[256]; /* filename */
           };

d_typeは全てのfile systemでサポートされているわけではない。ですと?

さらに見ると、

       If the file type could not  be  determined,  the  value  DT_UNKNOWN  is
       returned in d_type.

       Currently,  only  some file systems (among them: Btrfs, ext2, ext3, and
       ext4) have full support returning the file type in d_type.  All  appli‐
       cations must properly handle a return of DT_UNKNOWN.

今はデバッグのためにルートファイルシステムをまるごとNFSでやっていました。どうやらNFSではd_typeをサポートしていないようです。

ルートファイルシステムをext3のSDカードの書いて試してみたら、きちんと動作しました。

対策

デバッグのときにはNFSを使いたいし、デバッグのときだけソースやビルドオプションを変えるのも煩雑です。

以下のように、d_typeがDT_UNKNOWNの時でも処理を続行するように修正しました。

$ diff -u property_service.c.org property_service.c
--- property_service.c.org	2011-02-18 19:08:48.007726588 +0900
+++ property_service.c	2011-06-25 12:16:53.502650691 +0900
@@ -460,7 +460,7 @@
             if (strncmp("persist.", entry->d_name, strlen("persist.")))
                 continue;
 #if HAVE_DIRENT_D_TYPE
-            if (entry->d_type != DT_REG)
+            if (entry->d_type != DT_REG && entry->d_type != DT_UNKNOWN)
                 continue;
 #endif
             /* open the file and read the property value */


トラックバックURL

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード