ntpclientをAndroidに組み込む

Android用によく配布されているbusyboxスタティックバイナリに含まれるntpdでは、時刻合わせの動作はするのだけど、名前引きができない。
それも不便すぎる。
最近のものでは、binderに対応できるように直されているという情報もあるのだけど、busyboxのNDKビルド環境を作るのは結構骨だ。
glibcでスタティックビルドしたら簡単なんだけど、それもなんだか美しくない。
残念なことに、新しいコードで、そのままNDKビルドに使える決定打になるようなパッチを提供しているところがない。
いくつか試してみたけど、時間かかりそうなので挫折。


そこで、ntpclientを導入することにした。
ターゲットは、いまさらながら2.3.7。


コードは、オリジナルのntpclient(http://doolittle.icarus.com/ntpclient/)を元に、adjtimex_android.cを追記した、https://github.com/wlach/ntpclient-androidを使用する。
結構不要ファイルがあるのと、configureが用をなさない構成だったので、フォークして、Android.mk仕様に書き換える。
このマシンからはgithubが使えるようになっていなかったので、キーを生成してgithubに登録しておく。


Githubからフォークしたリポジトリをクローンする。

$ git clone https://github.com/kinneko/ntpclient-android.git
$ cd ntpclient-android/
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

作業用ブランチを切る。

$ git branch mytest
$ git branch -a
* master
  mytest
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
$ git checkout mytest
Switched to branch 'mytest'

いらないファイルを削除する。

$ rm Makefile.in adjtimex.1 adjtimex.c configure envelope log2date.pl ntpclient.1 rate.awk rate2.awk test.dat todo
$ git rm Makefile.in adjtimex.1 adjtimex.c configure envelope log2date.pl ntpclient.1 rate.awk rate2.awk test.dat todo
rm 'Makefile.in'
rm 'adjtimex.1'
rm 'adjtimex.c'
rm 'configure'
rm 'envelope'
rm 'log2date.pl'
rm 'ntpclient.1'
rm 'rate.awk'
rm 'rate2.awk'
rm 'test.dat'
rm 'todo'

$ git commit -m "remove unuse files."
[mytest ac97ced] remove unuse files.
 Committer: kinneko <kinneko@L2012.(none)>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 11 files changed, 875 deletions(-)
 delete mode 100644 Makefile.in
 delete mode 100644 adjtimex.1
 delete mode 100644 adjtimex.c
 delete mode 100755 configure
 delete mode 100755 envelope
 delete mode 100644 log2date.pl
 delete mode 100644 ntpclient.1
 delete mode 100644 rate.awk
 delete mode 100644 rate2.awk
 delete mode 100644 test.dat
 delete mode 100644 todo

$ git log
commit ac97cedb4002f9933587bb15068e37c83ebd6de7
Author: kinneko <kinneko@L2012.(none)>
Date:   Mon Feb 17 16:56:02 2014 +0900

    remove unuse files.

gitの基本設定ができていなかったので、設定してログを更新する。

$ git config --global user.name "kinneko"
$ git config --global user.email kinneko@gmail.com
$ git commit --amend --reset-author

変更点はないので、エディタは^xで終了。

commit e891f5154eb67be339d5db2d4f05120d3dd77001
Author: kinneko <kinneko@gmail.com>
Date:   Mon Feb 17 16:58:40 2014 +0900

    remove unuse files.

更新された。


ライセンスファイルを追記する。
オリジナルのコードがGPL2なので、GNUから持ってくる。

$ wget http://www.gnu.org/licenses/gpl-2.0.txt
$ mv gpl-2.0.txt LICENSE
$ git add LICENSE
$ git commit -m "add license file."
[mytest 894c2d5] add license file.
 1 file changed, 339 insertions(+)
 create mode 100644 LICENSE

Android.mkファイルを追記する。

$ cd [your AOSP/mydroid/]external
$ git clone https://github.com/kinneko/ntpclient-android.git
$ cd ntpclient-android

$ vi Android.mk
ifneq ($(TARGET_SIMULATOR),true)

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_C_INCLUDES:= \
	$(KERNEL_HEADERS) \
	$(LOCAL_PATH)

LOCAL_CFLAGS:=-O2 -std=c99 -W -Wall \
	-Wpointer-arith -Wcast-align -Wcast-qual -Wshadow \
	-Waggregate-return -Wnested-externs -Winline -Wwrite-strings \
	-Wstrict-prototypes \
	-DENABLE_DEBUG \
	-DENABLE_REPLAY

LOCAL_SRC_FILES := \
        adjtimex_android.c \
        ntpclient.c \
        phaselock.c
LOCAL_MODULE := ntpclient
LOCAL_LDLIBS:=-lrt

LOCAL_MODULE_TAGS := optional

include $(BUILD_EXECUTABLE)

endif

mmでローカルビルドテストを行う。

mydroid/external$ cp -a ~/QCDongle/ntpclient-android ./
$ cd ntpclient-android

確認内容。
・ntpclientが生成されているか
・ROM内のどこに配置されるか(とりあえず/system/binを想定)
パーミッションは実行可能な状態か

$ export ARCH=arm
$ export CROSS_COMPILE="../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-"
$ export TOP="../../"
$ export TARGET_PRODUCT_NAME=dongle
$ export VENDER=kinneko
$ export BUILD_PRODUCT=${VENDER}_${TARGET_PRODUCT_NAME}
$ export TARGET_PRODUCT=${BUILD_PRODUCT}
$ source ../../build/envsetup.sh
$ mm
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.7
TARGET_PRODUCT=kinneko_dongle
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IOTTGJK
============================================
make: Entering directory `/home/kinneko/QCDongle/work0124/mydroid'
(snip)
Install: out/target/product/dongle/system/bin/ntpclient
make: Leaving directory `/home/kinneko/QCDongle/work0124/mydroid'

$ file ../../out/target/product/dongle/system/bin/ntpclient
../../out/target/product/dongle/system/bin/ntpclient: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped

$ ls -l ../../out/target/product/dongle/system/bin/ntpclient
-rwxr-xr-x 1 kinneko kinneko 13888 Feb 17 18:02 ../../out/target/product/dongle/system/bin/ntpclient

・ファイルができている。
・インストール先は、/system/bin。
パーミッションは、ビルドユーザーのまま。実行は可能。


出来たバイナリをAndroidにpushして実行すると、ちゃんと動作しているようだ。

$ adb push ntpclient /udata/data/
5079 KB/s (39466 bytes in 0.007s)

$ adb shell /udata/data/ntpclient -c 1 -d -h pool.ntp.org -s
Configuration:
  -c probe_count 1
  -d (debug)     1
  -g goodness    0
  -h hostname    pool.ntp.org
  -i interval    600
  -l live        0
  -p local_port  0
  -q min_delay   800.000000
  -s set_clock   1
  -x cross_check 1
Listening...
Sending ...
packet of length 48 received
Source: INET Port 123 host 218.45.21.199
LI=0  VN=3  Mode=4  Stratum=2  Poll=4  Precision=-19
Delay=9231.6  Dispersion=25146.5  Refid=133.243.238.164
Reference 3601017775.125719
(sent)    4064896018.075263
Originate 4064896018.075263
Receive   3601018097.157951
Transmit  3601018097.157994
Our recv  4064896018.194372
Total elapsed: 118658.00
Server stall:      41.21
Slop:          118616.79
Skew:          -463877920976831.88
Frequency:             0
 day   second     elapsed    stall     skew  dispersion  freq
set time to 1392029297.157994000
47047 35218.194  118658.0     41.2  -463877920976831.9  25146.5         0

$ adb shell date
Mon Feb 17 18:10:45 JST 2014


作成したAndroid.mkをリポジトリに追加。

 $ git add Android.mk
 $ git commit -m "add Android.mk file."
[mytest a79b3ed] add Android.mk file.
 1 file changed, 29 insertions(+)
 create mode 100644 Android.mk

ローカルのmasterに反映する。

$ git checkout master
Switched to branch 'master'
$ git merge mytest
Updating f4523a6..a79b3ed
Fast-forward
 Android.mk  |   29 +++++
 LICENSE     |  339 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 Makefile.in |   29 -----
 adjtimex.1  |   60 -----------
 adjtimex.c  |  156 ---------------------------
 configure   |   11 --
 envelope    |   75 -------------
 log2date.pl |   15 ---
 ntpclient.1 |  100 ------------------
 rate.awk    |   18 ----
 rate2.awk   |  193 ----------------------------------
 test.dat    |  200 -----------------------------------
 todo        |   18 ----
 13 files changed, 368 insertions(+), 875 deletions(-)
 create mode 100644 Android.mk
 create mode 100644 LICENSE
 delete mode 100644 Makefile.in
 delete mode 100644 adjtimex.1
 delete mode 100644 adjtimex.c
 delete mode 100755 configure
 delete mode 100755 envelope
 delete mode 100644 log2date.pl
 delete mode 100644 ntpclient.1
 delete mode 100644 rate.awk
 delete mode 100644 rate2.awk
 delete mode 100644 test.dat
 delete mode 100644 todo

リモートリポジトリにpushする。

$ git push
Username for 'https://github.com': kinneko
Password for 'https://kinneko@github.com':
To https://github.com/kinneko/ntpclient-android.git
   f4523a6..a79b3ed  master -> master

オンラインでちょっとmdファイルを修正して作業終了。