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 */