月別アーカイブ: 2013年11月

Android 4.1 SmartWatch SmartQ Z Watch

SmartQ Z Watch を買ってみました。Android の SmartWatch です。
Bluetooth 経由の RemoteDisplay だった LiveView と違い、
単体で Android 4.1 が動作しています。

zwatch01.png

スペックによると中身は Ingenic JZ4775。
CPU は Xburst 1.0GHz で ainol Novo 7 Paladin と同じ mips です。
RAM も同じく 512MB。下記は ZWatch 実機より cpuinfo。

system type		: s2122b
processor		: 0
cpu model		: Ingenic Xburst V4.15  FPU V0.0
BogoMIPS		: 812.64
wait instruction	: yes
microsecond timers	: no
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 1, address/irw mask: [0x0fff]
microMIPS		: no
ASEs implemented	: mxu
shadow register sets	: 1
kscratch registers	: 0
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available
Hardware		: s2122b

基本的には他の SmartWatch と同じように、母艦となる Android Smartphone
と Bluetooth 同期する使い方が想定されているようです。

そのため内蔵のアプリケーションは最小限で設定項目もごくわずか。
アプリケーション管理も無いので、単独で Z Watch 側のアプリの
追加や削除を行う方法が見当たりませんでした。

USB 接続で MTP ストレージとして認識するのでアクセスは容易です。
内部ストレージに update.zip を転送して、
Settings から Firmware Upgrade を選ぶだけでファームウエアの更新が可能。

Firmware 1.9 に更新したところ FileManager が追加されており、
Z Watch 単独で内部のファイルを閲覧できるようになりました。
FileManager で apk を開くと一度ブロックされますが、
ここから提供元不明アプリのインストールを許可することが可能です。
(設定からは出来なかった)

また偶然 Settings → About の Model number を連打していたら
Usb debug を Enable に切り替えられることがわかりました。
再び連打すると Disable になります。

Driver は inf 書き換えで google のものを利用できます。
USB 接続で adb が使えるようになったので、任意アプリの
install / uninstall 方法が確保できたことになります。

画面が狭いだけで普通の Android Device と変わらないようです。
内部ストレージ (/sdcard) は 2GB、System ストレージ (/data) が
およそ 1GB (900MB free) となっています。

install したアプリアイコンもメニューに追加されており実行できます。
Eclipse から直接デバッグも可能。
下記画像は ADT (DDMS) からキャプチャ。

zwatch02.png zwatch03.png
↑ Chot Calculator も画面が小さくキーが潰れてるが一応動作 (NDK使用)

母艦と同期するサブ画面的な用途ではなく、
単独でさまざまなアプリを入れて持ち歩ける超小型デバイスとしても
活用できるのではないかと思っています。

関連エントリ
Android 4.0 MIPS で RenderScript, ainol Novo 7 Paladin の浮動小数点演算速度
Android 4.0 ainol Novo 7 Paladin、MIPS CPU の NDK と Vivante GPU
Android LiveView MN800 プラグインの作り方
LiveView MN800 Android のマイクロディスプレイ

Android NDK r9b と ARMv7A の hard-float 補足

要するに新しい Android NDK r9b に入れ替えると
実行が速くなってプログラムサイズも小さくなるということです。
Android.mk に下記の行を追加してコンパイルするだけ。

ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS += -mhard-float
LOCAL_LDFLAGS += -Wl,--no-warn-mismatch
endif

より詳しくはこちら

関連エントリ
Android NDK r9b と ARMv7A の hard-float

Android NDK r9b と ARMv7A の hard-float

Android 4.4 (KitKat) とともに NDK r9b がリリースされています。
RenderScript 対応などいくつか新しい機能がありますが、
その中に ARMv7A の hard-float 対応が含まれています。
ちょうど NDK を使った関数電卓アプリを作っているところだったので試してみました。

Android NDK

ちょっと電卓

Android/iOS など ARM デバイスではこれまで float ABI として softfp が用いられていました。
関数呼び出しなどの引数は、浮動小数点数であっても必ず整数レジスタ r を経由しており、
FPU の有無にかかわらず共通化出来るようになっています。

その代わり VFP が搭載されているデバイスでの実行効率とコード効率がわずかに犠牲になっています。
これまでの iOS/Android スマートフォンで VFP が搭載されていないのは
MSM7225 など一部の ARM11 (ARMv6, Android では ARMv5TE) に限られていました。
ARMv7A では存在しておらず softfp を用いる必要はありませんでした。

Android NDK r9b で hard-float に対応したので VFP/NEON レジスタを直接用いた
関数呼び出しが可能となっています。

●コンパイル方法

NDK で hard-float を指定する手順は下記の通り。
Android.mk に追加します。

LOCAL_CFLAGS += -mhard-float
LOCAL_LDFLAGS += -Wl,--no-warn-mismatch

ただし対応しているコンパイラは gcc のみで clang ではまだ使用できません。
このオプションを指定できるのは ARMv7A ( TARGET_ARCH_ABI = armeabi-v7a ) の場合だけです。

●外部ライブラリの宣言

システムや外部ライブラリは softfp でコンパイルされているので、
コンパイラに ABI の違いを正しく認識させる必要があります。
NDK r9b 付属のヘッダでは、各関数に下記の宣言が追加されています。
これは softfp 関数の呼び出しであることを意味しています。

__attribute__((pcs("aapcs")))

例えば NDK 付属の math.h ヘッダを見ると下記のように宣言されています。

// math.h より抜粋
double	acos(double) __NDK_FPABI_MATH__;
double	asin(double) __NDK_FPABI_MATH__;

__NDK_FPABI_MATH__ や __NDK_FPABI__ は sys/cdefs.h で定義されています。

// sys/cdefs.h より一部抜粋
#define __NDK_FPABI__ __attribute__((pcs("aapcs")))
#define __NDK_FPABI_MATH__ __NDK_FPABI__

●コンパイル結果と libm の hard_float

実際に hard-float でコンパイルした結果は下記の通り。
ローカル関数呼び出しは直接 d0 レジスタが用いられていることがわかります。

// hard-float
// t_value f_bittof( t_value val )

   vcvt.u32.f64 s0, d0
   vcvt.f64.f32 d0, s0
   bx           lr

↓これまでの softfp でコンパイルすると下記の通り。
64bit 倍精度浮動小数点数は r0/r1 と 2つの 32bit 整数レジスタを使って
受け渡しが行われています。

// softfp
// t_value f_bittof( t_value val )

    vmov            d6, r0, r1
    vcvt.u32.f64    s15, d6
    vcvt.f64.f32    d6, s15
    vmov            r0, r1, d6
    bx              lr

hard-float でコンパイルした場合も、外部のライブラリ呼び出しでは
下記のように r0/r1 レジスタへのへのコピーが発生します。

// hard-float (-lm)

    vmov    r0, r1, d0
    bl      0 
    vmov    d0, r0, r1

ただし libm は hard-float でコンパイルした static ライブラリが付属しているので、
直接 VFP/NEON レジスタによる呼び出しも出来ます。

LOCAL_CFLAGS += -mhard-float -D_NDK_MATH_NO_SOFTFP=1
LOCAL_LDFLAGS += -Wl,--no-warn-mismatch -lm_hard

-lm (libm) の代わりに -lm_hard (libm_hard) を指定します。
この場合ヘッダの attribute 宣言を外す必要があるので -D_NDK_MATH_NO_SOFTFP=1 も
必要です。
↓ libm 呼び出しでもレジスタ転送が無くなりました。

// hard-float (-lm_hard)

    b       0 

アプリケーションコードは小さくなりますが libm_hard は static なので
プログラムコード全体は増えます。

● libm 以外のライブラリ呼び出し

浮動小数点数を用いるライブラリは libm 以外にもあります。
例えば OpenGL ES 2.0 関数にも attribute 宣言が追加されています。

// GLES2/gl2.h より
GL_APICALL void         GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);

// GLES2/gl2platform.h
#define GL_APICALL  KHRONOS_APICALL

// KHR/khrplatform.h より抜粋
#   define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__

実際に glClearColor() を呼び出してみると、hard-float でも r0-r3 へのコピーが
行われていることがわかります。

// hard-float (debug build)

    vstr    s0, [fp, #-8]
    vstr    s1, [fp, #-12]
    vstr    s2, [fp, #-16]
    vstr    s3, [fp, #-20]	; 0xffffffec
    ldr     r0, [fp, #-8]
    ldr     r1, [fp, #-12]
    ldr     r2, [fp, #-16]
    ldr     r3, [fp, #-20]
    bl      0 

libm 以外では特に hard-float 版が用意されているわけではないので
softfp 同様の転送が行われます。

実際のアプリケーションでどの程度の差が出るかわかりませんが、
NDK でさらに最適化出来る余地ができました。
もっとも、iOS の方はすでに ARMv8 に移行しつつあります。
Android も 64bit 化が行われればこのような違いを意識する必要は無くなるでしょう。

関連エントリ
Nexus 7 の Ubuntu で ARM の abi softfp と hard-float を比べる