FirefoxOS の日本語化

FirefoxOS の日本語化の解説はすでに先人の方々が詳しくされているので、素直に日本語化したい方はそちらを参照したほうがよいかと思います。また MDN では Localizing FirefoxOS にL10N化のドキュメントがあります。
flame goes to v2.2-master

以下では、ローカルツリーに差分 commit して、upsteam に追従出来る形で進めた手順です。
(※ 以下のコマンドライン例をコピー&ペーストで実行しないでください。git や repo は理解した上で使用してください)

ローカルツリーのプロジェクト切替

ツリーは manifest にあるように、多数のモジュールを各地サーバから特定ブランチorタグを指定して取得し、repo コマンドでモジュールを管理しています。それぞれのモジュールは指定された状態のまま置かれているので、何か変更を加えた後に ‘repo sync’ で最新版を取り込むと変更が消されてしまいます。

それを避けるために repo でローカルプロジェクトを開始します。全てのモジュールにブランチを切り、sync 時には manifest で指定されたブランチorタグに対して git rebase する形で追従してくれます。以下ではプロジェクト名を myenvビルドディレクトリを ~/B2G とした例です。

$ cd ~/B2G
$ git checkout -b myenv origin/default
$ ./repo start myenv --all

L10n パッケージの追加

日本語化を行うためのパッケージは gaia, gecko に対する追加ファイルとして提供されていて、mercurial によって管理されているため mercurial のインストールが必要です。

mercurial のコマンド(hg)を使ってそれぞれのパッケージをツリーに取り込み、ローカルツリーのプロジェクトに登録しておきます。

$ cd ~/B2G/gaia/locales
$ hg clone http://hg.mozilla.org/gaia-l10n/ja
$ git add ja
$ git commit -m "add gaia-l10n/ja"

$ cd ~/B2G/gecko
$ hg clone http://hg.mozilla.org/l10n-central/ja l10n-central/ja
$ git add l10n-central/ja
$ git commit -m "add l10n-central/ja"

$ cd ~/B2G/build
$ hg clone http://hg.mozilla.org/build/compare-locales
$ git add compare-locales
$ git commit -m "add compare-locales"

これらを有効にするために ~/B2G/.userconfig を作成し、ビルド時に設定する環境変数を記載しておきます。

export LOCALE_BASEDIR=$PWD/gaia/locales
export LOCALES_FILE=$PWD/gaia/locales/languages_all.json
export GAIA_DEFAULT_LOCALE=ja

export L10NBASEDIR=$PWD/gecko/l10n-central
export MOZ_CHROME_MULTILOCALE="ja"

export PATH="$PATH:$PWD/build/compare-locales/scripts"
export PYTHONPATH="$PWD/build/compare-locales/lib"

 日本語キーボード及び辞書の登録

日本語IME に必要な辞書を入手します。辞書は Sourceforge.net にて ipadic または naist-dic が入手可能です。これらのパッケージの *.dic ファイルを gaia 内に取り込みます。

$ mkdir ~/B2G/gaia/apps/keyboard/js/imes/jskanji/dict/src
$ tar zxvf ipadic-x.x.x.tar.gz
$ cp ipadic-x.x.x/*.dic ~/B2G/gaia/apps/keyboard/js/imes/jskanji/dict/src/

*. dic ファイルはそのままでは使えないため、IME で使える形に変換します。dict ディレクトリで make を実行します。

$ cd ~/B2G/gaia/apps/keyboard/js/imes/jskanji/dict
$ make

エラーになる場合は Makefile の find コマンドがどのディレクトリを参照しているかを確認してください。src になっていない場合は、ディレクトリ名を変更してください。

make に成功すると dict.json, dict/dict, dict/dict.utf8, dict/jcconv.pyc が作成または更新されます。一旦この状態でツリーに登録しておきます。

$ cd ~/B2G/gaia/apps/keyboard/js/imes/jskanji
$ git add dict dict.json
$ git commit -m "add ipadic"

この辞書と日本語IMEを有効にするため、 ~/B2G/.userconfig に以下を追加します。

export GAIA_KEYBOARD_LAYOUTS=en,jp-kanji"

あとは build.sh を実行するだけです。一度ビルド済みのツリーの場合は念のため out 及び objdir-gecko ディレクトリを削除しておいてください。

ツリーの更新

新たに upstream から ./repo sync で更新を取得した場合、取得後に上記の変更を加えて更新されます。ただし、upstream で上記に当たるファイルが更新された場合は conflict しますので、それぞれのモジュールで confilict を除去する必要があります。

.userconfig もツリーに登録しておくことができます。しかしながら .userconfig は .gitignore により登録対象外に指定されていますので、-f オプションで強制登録するか、別途保存することになります。

Flame のビルド

flame を v1.3 のままにしていたものの、せっかく最新版が投入できる端末なので、ようやく時間ができたこともありビルドからやってみました。
flame goes to v2.2-master

ビルド

最新ツリーでは flame の config (./config.sh./.repo/manifests/flame.xml) が用意されているので、素直にビルドするだけで完了します。

$ git clone git://github.com/mozilla-b2g/B2G.git
$ cd B2G
$ ./config.sh flame
$ ./build.sh

デフォルトの flame では JellyBeans ベースですが、config.sh の引数に flame-kk を指定することで KitKat ベースでもビルドできます。ちなみに flame の場合は Linux kernel もビルドしています。

最初のビルドでは flame 端末のバックアップを行うため、予め実機を adb で繋いでおく必要があります。adb での接続は後述します。実際のバックアップは device/t2m/flame/extract-files.sh で行っています。

実機の接続

自環境では Windows から VMWare Player で Ubuntu を起動しているため、Windows で接続を行った後に Ubuntu に再接続するようにしています。

Windows の場合、実機を接続すると ドライバのインストールが要求されますが、Windows Update では完了できないため Flame用のドライバを導入する必要があります。Flame 用のドライバは MDN の Flame ページ から辿れます。成功すると以下のデバイスが登録されます。

  • USB Composite Device 9025
  • ALCATEL HS-USB Android Modem 9025 #2
  • ALCATEL HS-USB Diagnostics 9025(COMxx)
  • ALCATEL HS-USB NMEA 9025 (COMxx)
  • YunOS ACB Interface
  • ALCATEL HS-USB WWAN Adapter 9025 #2
  • USB 大容量記憶装置
  • Linux File-CD Gadget USB Device
  • Linux File-CD Gadget USB Device

Ubuntu(udev を使う Linux) の場合、udev に flame のデバイスIDを登録しておきます。/etc/udev/rule.d/50-firefoxos.rules を以下のように作成します(android.rules があればそこに追記でも可)。

SUBSYSTEM=="usb", ATTR{idVendor}=="05c6", MODE="0666", GROUP="plugdev"
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666", GROUP="plugdev"

1つ目は Qualcomm として、2つ目は Google(Android Device) として認識した場合のルールです。
基本的に1つ目だけでよいはずですが、端末状態によっては 2つ目で認識することもあったので記載しておきます。

lsusb などで USB として認識していれば、adb で接続できていることを確認します。

$ lsusb
  :
Bus xxx Device xxx: ID 05c6:9025 Qualcomm, Inc. 
  :
$ adb devices
list of devices attached
12345678        device

permission のエラーなどで繋がらない場合は、一旦端末を外して以下を実行した後に接続を試みます。

$ sudo adb kill-server
$ sudo adb start-server

実機への書き込み

ビルドと接続が終わっていれば、書き込みスクリプトを実行するだけです。実行中はフラッシュメモリの各パーティションの消去と書き込み経過が逐次表示されます。

$ ./flash.sh

Flame 到着!

ようやくOSSストア経由で発売された Firefox OS リファレンス機「Flame」ですが、申込み当日いきなり注文が殺到して40分で売り切れたそうです。

人気によるものというよりFirefox OS クラスタの人たちが動く機体をひたすら待ってたわけで、ビルドROM入れ換えで既存端末をFirefox OS bootable にした人や並行輸入で入手した人を除けば、普通に通販で手に入る最初の端末なわけで、この状態もまぁ想定できたことでしょう。

入手に成功!

で、私はそのスタートダッシュに間に合わなかったものの、30分後になんとかボタンを押して注文確保しました。10分遅れてたら終了していたわけですが。

注文して3~4日ほどで到着したもの不在で受け取れず、1週間後に受け取りました。

10351759_821561041211259_8616082811080461454_n 10592802_821561074544589_6604504814846193373_n

ある種「ちゃんと携帯電話として動いてる」端末は初めて手にするのでいろいろ興味深いところですが、SIMがないので電話機能は使えず今はまだ Wi-Fi のみです。

今まで Android Stick では飾りだった FM Radio、Volume Up/Down、Camera、Sim Manager などがちゃんと動きますし、Network も mDNS が正しく動いて Web のレスポンスも実用範囲内です。搭載されている SoC が Snapdragon 200 とのことで、リファレンスとしてこのくらいのクラスでもちゃんと動きますよということを示しているのかもしれません。

技適マーク問題

到着するや否や、技適マークがおかしいという不穏な噂が流れました。で、電池を取り出して見てみると確かに規定には存在しない「J」のマークが。日本では「〒稲妻マーク」に続いて技術基準適合証明「R」(電波法による適合)と技術基準適合認定「T」(電気通信事業法による適合)が正しい端末には表示されているはずなので、これがないとなると使用時点でそれぞれの法律に違反することになります。これは大変。

端末個体の話ではなくて全てがこのマークらしいということで、しばらくして「回収」のお知らせが出回り、早速着払いで発送することに。それから5日後に正しい端末として受け取りました。

最近では iPhone のように電子的に表示することで、何か瑕疵が見つかれば Update で対応するのが一般的になってきましたが、まさかの物理シールだったためにこのような対応にならざるを得なかったようです。これは買った方も売った方も不幸としか言いようがないわけですが、法律に関わるところはもうちょっと注意できなかったもんですかね…

mbed を動かしてみる

高性能SoCばかり追っていて最近のマイコン事情をほとんど知らなかったのですが,たまたま流れてきた “mbed” なるものを試してみました.

mbed とは?

mbed は「プロトタイプ開発向けのワンボードマイコンと開発環境」で最近流行のフィジカルコンピューティングを可能とするものなので,元々 NXP 独自のリリースだったものが OpenHard/Software になって各社でリリースされるようになりました.

で、いわゆるマイコンボードと何が違うのかと言うと「オンラインビルドができる」というのです.ところでオンラインビルドってなんだろう…

手元に入手したのは「STmicro Nucleo F401RE」と「NXP LPCXpresso LPC11U68」です.それぞれ展示会でアンケートによるサンプル配布されたものが放置されていたので貸していただきました.どちらもブリスターパックに入ってるのはなかなかインパクトがあります.

IMG_6343

双方とも Arduino Shield 互換のコネクタを持っているため,Arduino 互換周辺ボードを活用することが出来ます.これらが簡単に活用できるといろいろ面白そうです.

PCに接続

mbed 環境を使うにはどちらのボードも変わらないので F401RE を例に導入してみます.

PCへの接続は USB 経由で,F401RE は mini-B でボードに接続します.Windows にてドライバを要求されるので,STMのサポートページからアーカイブをダウンロードして導入し,成功すれば次のドライバがインストールされます.

  • ディスクドライブ > MBED microcontroller USB Device
  • ポート(COMとLPT) > STMicroelectronics STLink Virtual COM Port (COMxx)
  • Universal Serial Bus devices > STMicroelectronics STLink dongle

USB 一つでデバッガ・マスストレージ・シリアルの3つが接続されたことになります.ICE や JTAG を接続してる環境を見てるとこんなのでいいのかと思うほどシンプルです.

mbedサイトに登録、そして開発

上記に成功するとドライブが追加されていて,中にある mbed.htm をブラウザで開くと mbed.org のサイトに行きます.ここでサインアップしてユーザを作成することで,mbed.org 上にある開発環境が web ブラウザ上で使えるようになります.

サンプルを使った大まかな流れとしては,まずサンプルプログラムを開発環境(mbed compiler) に取り込みます.

  1. プロフィールのページ右下の「ST Nucleo F401RE」をclick
  2. 製品ページの右下の「example programs」の導入したいプログラムをclick
  3. 「Import the program」をclick

新たにプログラムを一から開発する場合は,Workspace を作る必要があります.

  1. 右上の「Compiler」をclick (mbed compiler のページへ)
  2. 「New」で新たにWorkspaceを作成,templete を使うか Empty Program で空を作成
    (空の場合は mbed パッケージを import する必要あり)

Workspace の準備ができたらソースを登録,コンパイルして実機に投入します.

  1. ソースを作成・編集して保存 (起動関数は引数なしの main() )
  2. Compile
  3. 出来たバイナリファイル(firmwareイメージ)を追加されたドライブにコピー
  4. USB が一瞬切断されて,firmwareイメージが自動的にflash に書かれて実行

ローカルPCで実施しているのはブラウザの操作とイメージのコピーだけです.チュートリアルを紹介するサイトがいろいろありますので,検索して流れを追ってみるとよいでしょう.まずはLED点滅,次にシリアル表示がお約束ですが,どちらも mbed.org にはサンプルが登録されているのでそのまま Workspace に import して試すことができます.

mbed-f401re

ちなみにコードは以下のような感じで、LED を1秒おきに点滅する例です.

#include "mbed.h"
DigitalOut myled(LED2);
int main()
{
    while(1) {
        myled = 1;
        wait(1.0);
        myled = 0;
        wait(1.0);
    }
}

sample を使えばここまで10分かそこらで “Hello, World” に相当する LED 点滅に到達できると言うのはかなり衝撃でした.昔ならまず最初にIDEやtoolchainのインストール,そしてボード接続と転送でつまずきますから…

IMG_6344

 開発環境だけじゃない?

mbed.org に登録すると開発環境が得られるだけでなく, Repogitory を作成して管理・公開したり,コミュニティとのQ&Aに参加したり,必要な周辺機器を衝動買い(!)することができます.フィジカルコンピューティングという キーワードによってどんどん組込みマイコン開発環境の障壁が取り除かれて参加人口が増えつつあり,この取り組みは非常にすばらしいことだと思います.

とはいえ,これだけ上位操作で簡単に制御できるとなるとこの下回り作ってる人たちは結構苦労してるんだろうなぁ…

FirefoxOS v2.0 を試してみる

ビルドしてみる

先日,正式に v2.0 branch が切られ、master は v2.1-pre に移行しました.ということで早速試してみようとビルドしてみました.

しかし…build/ の v2.0 branch に build/target/product/mini.mk が消えていてビルドが出来ないというエラー.master にはちゃんとあるので,v2.0 のビルドはちゃんと成功してるのでしょうか.ひとまず master(v2.1-pre) で試してみることにします.

と,嘆いてたら b2g-manifest で

<b4b3f48> 2014-06-11 [Aki Sasaki]  (origin/v2.0) bug 1023966 - revert platform_build branch switch for non-master branches. r=bustage

あっさり直ってました.

起動してみたら…

Firefox OS Simulator も 2.0 が使えるようになっているようですが,見た目的に何も変化がないようなので,master を build して mk808b に投入してみました.

起動時にいろいろエラーが出てまた何かデバイス向けの対応しないといけないような感じですが,暫く待ってたら何とか起動しました.ところがその画面が

v2.1-pre 試行

アイコンがでかい!

いやなんかおかしい.新バージョンの改良で解像度に関わらず3列固定で横幅最大で表示するようになっているようです.これは大画面向けに修正されるまで待つしかないですかね.

実機を見てないのでよく分かりませんが,Flame のデモを見てると home-screen にも pan/zoom などの two-finger action が追加されているらしいです.タッチパネルがなくマウス操作しかない環境ではこのままでは恩恵が受けられないので,別アクションでサポートされるのを待ちましょう.(マウス対応のような patch 方法が見つかればいいんですが)

 

PicUntu導入

一昨年,Rockchip SoC が搭載された Stick 型や Box 型のデバイスがかなりの勢いで発売されました.HDMI 端子に TV を,USB 端子にマウスを繋いで電源を供給すれば,Android 端末として動作するというものです.最近では Amazon でも比較的簡単に入手することができ,DualCore や QuadCore の Cortex-A9 環境が 5000~10000円という破格値で売られています.

FirefoxOS on AndroidStick もこの PicUntu の最小インストールをスタート地点にしています.

PicUntu とは?

PicUntu とは,その Rockchip SoC 搭載の AndroidStick で動作している Ubuntu Distribution で,DualCore の RK3066,QuadCore の RK3166 がターゲットとして開発が進んでいます.とりあえず 手順に従って導入し,LXDE のデスクトップ環境を構築してみました.

PicUntu_LXDE

導入方法はサイトを見ていただければよいのですが,サイトは英語ということもあるので,FirefoxOS を載せるベースとなる準備段階までをメモしておきます.ここでは RK3066 ベースの mk808b を例としておきますが,PicUntu の開発ストリームは RK3166 ベースに移行していますので,最新環境に追従したい方は別途情報を収集してください.

用意するもの

  • Android Stick 本体
  • microSD カード (4GB 以上)
  • 電源供給用 miniUSB-USB ケーブル
  • miniHDMI-HDMI ケーブル (TV やモニタに接続)
  • USB ハブ,キーボード,マウス
  • USB-LAN (option; ASIX AX88772 は動作確認済)
  • USB-WiFi (option; Ralink RT2870 は動作確認済)

mk808b の PicUntu は内蔵 Wi-Fi や内蔵 Bluetooth が使えませんので,必要に応じて USB-LAN や USB-WiFi を導入します.
(※ kernel を再構築すれば Wi-Fi は使えそうなのですが再構築 kernel の搭載に成功してません.さらに mk808b はクローンが存在し,異なるチップが載ってたりして開けないと分からないため厄介です.)

インストール手順としては,bootloader と kernel の入った ROM イメージを本体の NAND flash に書き込む作業と,root ファイルシステムを microSD に書き込む作業の2つです.先人が詳しい説明を書かれていますので,そちらも参考にしてみてください.

ROMイメージのNAND flash への書き込み

RK3066 の PicUntu は NAND flash の Recovery 領域に bootloader と kernel の ROM イメージを置くため,Recovery 領域から起動する必要がありますが,残念ながら購入時の Android ではできません.そのためカスタム ROM の導入(要は root 化)が必要です.メジャーなところでは Finless ROM があります.mk808b 向けの Finless ROM は V1.7 を使いましたが,書いた時点より上がってるので探してみてください.ただし PicUntu の導入には新しい必要はありません.

RK3066 の PicUntu は開発が止まっていますので 0.9RC3 が最新のようです.ダウンロードファイルより ROM イメージ(*.img) を取り出します.

WindowsPC にて ROM パッケージに含まれる RKAndroidTools(ROM_Flash_Tool_xxx.exe) で NAND flash への書き込みを行います.

  • まず「本体裏の左側の穴をピンで突きながら電源を入れる」ことで bootloader モードに入ります.ドライバが要求されますので,ROMパッケージに含まれる rockusb.inf を指定してインストールします.インストールできれば NAND flash の書き込みが出来る状態です.
  • RKAndroidTools を起動します.recovery の Path を PicUntu の ROM イメージに書き直し,「Flash ROM」で書き込みが完了します.

Root ファイルシステムの microSD への書き込み

PicUntu は microSD 上の ext4fs を使います.rootfs のファイルは 「picuntu-linuxroot-0.9-RC*.tgz」 の形で配布されていますので,PC Linux や GParted LiveCD などを使って,microSD にパーティションを作成してラベル “linuxroot” で ext4fs にフォーマットした後,mount して rootfs のファイルを展開します.

起動

microSD を本体に挿して電源を入れ直します.カスタム ROM の Android が起動し,terminal を起動して recovery モードでリブートします.terminal がない場合は Google Play から入手してください.

$ su
# reboot recovery

コンソールが接続されたモニタに表示され,root:12qwaszx で login できれば成功です.

あとは煮るなり焼くなりどうぞ.apt-get install で用意されている arm 版 package が PC と同じ感覚で導入できます(速度は…同じ感覚とはいきませんが)

Firefox Developers Conference 2014 in Kyoto に参加してきました

京都にて Firefox の開発者向けカンファレンスが開催されました.13:00~19:00 の長丁場ながら200人以上が参加したとか.詳しい内容は Slideshare などで公開されてます.

FirefoxOS が注目される中,Webプラットフォームへの転換期にいるのが実感できました.Webがあらゆる表現を包括できれば後はそれベースで全て語れるわけで,プラットフォームとして十分価値があります.発表もWebアプリ技術が中心でしたから,Web を作ってきた人達はアプリ開発への移行も期待できます.

とはいえまだ動く実機が少なく,アピールするには実機が普及しないことには始まりません.会場には実機が展示されていましたが,まだまだ手にするには時間が掛かりそうです.作るほうも単に作ればいいと言うものではなく,ベースとなるプラットフォームも UI/UXに必要なパフォーマンス・機器間の接続・規格の取り込みなどの進化が必要です.FirefoxOS が動く実機環境を(無理矢理)構築している自分としても何か一端の役に立てればと思います.

先月の勉強会に引き続き同じネタで LT 発表してきました(全然進展してませんが).懇親会会場だったこともあってすごい盛り上がりの中だったのでネタを仕込んでおくべきだったと仕切りに後悔(^^;)


あと,フォクすけを賭けたじゃんけんには初戦敗退でした…

FirefoxOS の色反転問題

AndroidStick に FirefoxOS を乗せる時に引っかかった問題として,色反転問題があります.詳しく調べ切れていないのですが,JellyBeans をベースとする場合には通常使う色フォーマットが Android とは異なることで現れるようです.

Window の色フォーマット決定

色フォーマットは場面ごとに使う手段によって決まるため,ここでは Window に描画されるフォーマットについて扱います.Window 向けのフォーマットは Gonk 層との境界 gecko/widget/gonk/libdisplay/GonkDisplayJB.cpp にある GonkDisplayJB() の surfaceformat にて決められます.

GonkDisplayJB::GonkDisplayJB()
{
  :
    if (!err && mFBDevice) {
        :
        /* The emulator actually reports RGBA_8888, but EGL doesn't return
         * any matching configuration. We force RGBX here to fix it. */
        surfaceformat = HAL_PIXEL_FORMAT_RGBX_8888;
    }
    :
    if (!err && mHwc) {
        :
        surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888;
    }
    :
}

ここでは,Framebuffer が open できたらまず RGBX_8888 を設定し,Hwcomposer が open できたら RGBA_8888 に設定しなおすようです.Hwcomposer は画面の全部または一部を反転・回転・拡縮などを制御する Android 実装機能ですが,FirefoxOS では API 1.1 以上でないと使えないようで,まだ API 1.0 がほとんどの状況で使えない場合が多いです.AndroidStick の Hwcomposer もそうでした.

つまり「Hwcomposerが使えない」場合は surfaceformat は RGBX_8888 が選択されることになります.これは 1pixel が 32bit で扱われるとともに, Red,Green,Blue と 8bit とずつ並ぶフォーマットです(最後は空の8bit).ちなみに RGBA_8888 は 最後が alpha 情報が入るフォーマット,BGRA_8888 は並びが Blue,Green,Red,Alpha と並ぶフォーマットです.

画面モードの選択

フォーマットは選択されましたが,実際に Gonk 層へは EGL ライブラリを通じて設定されます. EGL では FirefoxOS や Android が期待するフォーマット情報を渡し,それにマッチする画面モードを返します.

その中にビット幅も情報に含まれるのですが,その値を取得するのは gecko/widget/gonk/nsWindows.cpp にある ColorDepth() です.先ほどの surfaceformat を参照して決めているようですが…

static uint32_t
ColorDepth()
{
    switch (GetGonkDisplay()->surfaceformat) {
    case GGL_PIXEL_FORMAT_RGB_565:
     return 16;
    case GGL_PIXEL_FORMAT_RGBA_8888:
     return 32;
    }
    return 24; // GGL_PIXEL_FORMAT_RGBX_8888
}

先ほど surfaceformat は RGBX_8888 が選択されていたので 24 が戻ります.Android で実装される EGL が正しく 24bit で RGBX のモードを持っていれば正しく表示されるはずですが,そうでなければ期待しないモードに設定されてしまいます.その結果がこれ.

色反転homescreen

キツネさんが青い…(T_T)

どうも RGBX_8888, 24bit と指定される EGL には BGRA_8888 相当が選択されてしまったようで,初期の段階では Red と Blue が反転してしまう問題が起こってしまっていました.

EGL の仕組みを知らなかったこともあって,なぜこうなるかまでたどり着くのにかなり掛かりましたが,Hwcomposer が有効な場合と同じ「最初に設定した surfaceformat を RGBA_8888 に修正」することで EGL の持つ正しいモードに設定されて解決しました.

Gonk 層に期待すること

Gonk 層,つまり Linux Kernel (Config) や Driver や Android Library は Android をベースにしている場合,Android が動くようにチューニングされています.そのため,FirefoxOS を動かすと必ずしも Android とは動作条件や受け渡す情報が同じにならないため,想定していない状態に陥ると残念ながら期待通りには動作しません.

となると,Gonk 層は Android だけでなく FirefoxOS が期待する条件でも動くように実装されている必要があります.これは地道に「Gonk 層は何が期待されているのか」を探っていくしかないでしょうね…

 

 

FirefoxOS v1.4 のアドレス解決

FxOS on AndroidStick にて v1.3 までは DNS によるアドレス解決がすんなりできていたのですが,v1.4 では全くできなくなっていて調査したところ,ソフト構成の変更があったようです.

ソフト構成の変更点

ソースを辿ってみたところ,名前解決は NSPR 実装の gecko/nsprpub/pr/src/misc/prnetdb.c 内にある PR_GetAddrInfoByName() にて実施していました.この API 内では,GETADDRINFO() にて変数 _pr_getaddrinfo に設定された関数を呼び出され,この変数はライブラリから検索されて見つかった関数が設定されています.

v1.3 までは gecko/other-licenses/android/getaddrinfo.c の __wrap_getaddrinfo() に誘導されていましたが,v1.4 からはこの other-licenses/android が無効になり,bionic の getaddrinfo() が直接呼ばれるようになったようです.

gecko/moz.build にて MOZ_WIDGET_TOOLKIT が ‘gonk’ の場合,other-licenses/android が無効にされているのが分かります.

- if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
- add_tier_dir('base', ['other-licenses/android'])
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
+ add_tier_dir('base', ['other-licenses/android'])

bionic の getaddrinfo() は netd にアドレス解決を依頼します.ソケットを介して “getaddrinfo” コマンドが送られてアドレスを解決するようですが,この応答が timeout してアドレス解決できなくなっていたようです.netd は android の daemon なので ”setprop net.dnsN” で解決しそうに思いますが,残念ながらこの方法では解決しませんでした.

※追記(4/19): FxOS は multicastDNS に対応しているため,導入ネットワークに接続していればこの問題は発生しないと思われます.つまり自室内LANは未対応…

netd への登録

android には netd が open した socket にコマンドを送り込むコマンド “/system/bin/ndc” が用意されています.これを使うと netd に直接 DNS サーバ情報を送り込めるようです.これを用いて以下のように netd に google DNS サーバのアドレスを設定したところ,v1.4 でのアドレス解決ができるようになりました.

# ndc
Usage: ndc [sockname] <monitor>|<cmd> [arg1] [arg2...]
# ndc resolver setdefaultif eth0
# ndc resolver setifdns eth0 ^ 8.8.8.8 8.8.4.4
Using alt socket netd
200 0 Resolver command succeeded

書式はソースから起こしたのですが,resolver が名前解決コマンド,setifdns がサブコマンドでI/Fへのサーバ情報設定,”^” はドメイン名で「省略」を表し,後ろの2つはサーバIPアドレスです.

今のところ手動で対応する必要がありますが,実施するなら netd の起動後の script に設定しておくのがよいかと思います.

補足ですが,ストレージ制御の vold にも “/system/bin/vdc” コマンドが用意されており,これらの daemon の挙動チェックに外部コマンドが用意されているのはなかなか便利です.残念ながらコマンド一覧が見当たらないのですが,ソースから起こしておくと便利かもしれません.

Proxy への影響

FirefoxOS は一部を除いて HTTP でのアクセスが基本ですので,proxy を設定すれば URL のアドレス解決は proxy サーバに委ねられるため,この問題は proxy サーバのアドレス解決だけが影響を受けます.proxy サーバの設定を IP アドレスで行えばこの問題は起こりません.

 

FreeBSD で VPN サーバ環境

以前より自室に BSD で常時運転サーバを立てていたものの,外からアクセスするのにサービス毎に firewall に穴を開けるか,Web で操作するかをしてたのですが,いい加減面倒になってきたところで何か手段がないか探してたタイミングで SoftEther が Open 化されたということで(VPNとは何かを頭に叩き込んで)導入してみました.

SoftEther のインストール

SoftEther のビルドは実に簡単で,download ページGitHub からソースコードを取得して,configure,gmake install で終わりです.実に簡単.iconv が無くて make が通らない場合は,Makefile に -I/usr/local/include とか -L/usr/local/lib とかつければよいです.

インストール先が /usr/vpnserver とか /usr/vpnclient に設定されているのでやや違和感があります./usr/local/vpn/vpnserver 辺りに直しています.

自室サーバでは VPN サーバ機能だけを root で起動し,自室内 LAN とはローカルブリッジで接続することで外にいる端末をローカル LAN に接続できるようになります(ローカルブリッジなどの設定は後述).

# vpnserver start

VPN サーバの設定

室内 LAN は ルータ・終端装置(ONU)を介して WAN と接続していて,ルータ内はローカル LAN を構成して NAT で運用されているものとします.VPN サーバの FreeBSD はローカルLAN内に接続しています.

基本設定

VPN サーバの設定は vpncmd でも出来ますが,LAN 内のWindows PC から「サーバ管理マネージャ」をインストールすれば GUI で設定できます.

  • 新しい接続設定→ホスト名(サーバIP),ポート番号(どれか一つ),サーバ管理モード,管理パスワード
  • 接続
  • 仮想HUBの作成→仮想HUB名,パスワード
  • 仮想HUBの管理→ユーザの管理→新規作成→ユーザ名,パスワード認証,パスワード

ローカルブリッジの設定

ローカルブリッジとは,VPN を通して外部の仮想ネットワークと内部の物理ネットワークを接続する手段です.これを使えば仮想ネットワークをLAN内PCに参加させる手間が省けます.

  • ローカルブリッジ設定→仮想HUB(先に作成した仮想HUB名),LANカード(I/F名)→ローカルブリッジの作成

なお,「仮想 HUB とローカルブリッジを組んだ」 I/F は VPN からアクセスできないという OS 上の制約があるようです.そのため,VPN サーバがローカル LAN 内にある場合でも I/F は2つ用意しないといけないようです.自室では VPN 専用に USB-Ethernet 変換で I/F を増設しました.

L2TPの設定 

最近はスマートフォンが VPN 経由のリモートアクセス(L2TP)に対応しているので,利用できるようにその設定を行います.

  • IPsec/L2TP 設定→L2TPサーバー機能を有効にする,IPsec事前共有鍵(任意文字列)

ファイアウォールの設定

室内 LAN はルータを介して WAN(ONU) に接続しているので,外部から VPN サーバにアクセスするポート制御が必要です.構成によりますが,以下のポートを IP マスカレードに設定する必要があります.

  • UDP port 500 (IKE)
  • UDP port 4500 (IPSec NAT-Traversal)
  • UDP port 1701 (L2TP)
  • ESP port (Encapsulated Security Payload) … VPNスルー機能

VPN クライアントの設定

クライアントは OS に合わせて VPN クライアントを用意し,仮想 LAN カードを作成して VPN サーバ(WAN から見える IP または FQDN) の 仮想 HUB,ユーザ名,パスワードを設定して接続します.接続が完了すると ローカル LAN で DHCP が動いていればその IP アドレスが仮想 LAN カードに設定されます.

iPhone や Android の場合は,VPN メニューから VPN サーバ(WAN から見える IP または FQDN),ユーザ名(@仮想HUB名),パスワード,シークレット文字列(IPsec事前共有鍵で設定した文字列) を設定して接続します.

これで,外にいながら自室のローカル LAN と同じ条件で端末を扱うことができます(たぶん).速度は圧縮などの技術でかなり使えるレベルになってきています(とはいえペイロードにカプセル化したパケット載せてるんだから過剰に期待するのも酷というもの…).