特集 1

Android
による
組込み開発

第1章

Androidが変える組込みシステム
第2章

Android高速化テクニック
第3章

Androidネイティブコードデバッグ手法
第4章

Android NDKによるJNI開発手法

G o o g l e が発表した A n d r o i dは、一般的に携帯電話向けのプラッ

トフォームとして認知されています。
組込み系のエンジニアにとっては、
携帯電話以外への応用も早くから注

目していますが、VM のパフォーマンスなど初期リリースにありがちな問題も指摘されています。 この特第5章

集では、Androidの組込み開発現第6章

化の手法など、実践的な情報を集め

プロファイリング手法
Androidポーティング事例

場で役に立つ開発テクニックや高速てみました。

組込みプレス Vol.16

1

特集 1

Android による組込み開発

第

第1章

1章

株式会社イーフロー
統括事業本部 第１事業部

金山 二郎

Kanayama Jiro

Androidが変える
組込みシステムがあったでしょうか。しかも、Androidの発表は2007

Androidが変える組込みシステム

なりました。

年11月、すでに1年半を経過してこの盛況はただ事でしかし、高機能プラットフォームは順風満帆というはなく、あらためて、Androidに対する関心の高さをわけにはいきませんでした。Windows Mobileはうかがわせました。

WindowsCEのころから粘り強く成長を続けていまし
たが、Win32APIをそのままサポートするという理想

Androidまでの道のりを満足できるレベルに引き上げるのに苦慮していまし

さて、Androidはかつてないプラットフォームである

は、Windows Mobileは携帯電話としてはまだまだわけですが、その素晴らしさを知るためには、これまはあまりにも高く、Microsoftの力をもってしても製品た。また、とくに3Gに移行して間もないころの日本で異端の扱いでした。

でのプラットフォームについて知ることが近道です。携Symbian OS、Linuxも大きな開発を必要とする

帯電話に代表される高機能組込み機器向けプラット

プラットフォームでしたが、当時は60％に迫る圧倒的フォームの歴史を振り返ってみたいと思います。

なシェアを誇っていたNTTドコモの主導により、携帯本誌の読者に説明は不要かもしれませんが、OSす電話向けプラットフォームとしての体をなすことができ

ら搭載しない組込み機器を除けば、ほんの10年ちょっました。

と前の組込み機器はいわゆるRTOSが搭載されておBREWもまた特別なプラットフォームで、これはクアル

り、普及のただ中にあった携帯電話なども例外ではあコムがチップセットと一緒に販売したために普及しまし2009年5月13日から3日間、東京ビックサイトにて、りませんでした。OSやドライバはもちろん高額な製品

たが、JavaなどのVM 形式と違い、ネイティブベース

「第 12回組込みシステム開発技術展（通称 ESEC ）」を購入する必要があり、さらにそれらのインテグレーのアプリケーションプラットフォームであったため、アが催されました。昨年から始まった世界不況の影響

ションに何億円もの投資を必要としました。しかし、プリケーションが環境に影響を及ぼさないかを検証すで、最近の展示会は出展取り止めのために空地が多

契約者数が伸び続けたこのころが、携帯電話開発のる手間がかかるという問題を抱えています。

かったり来場者も少なかったりと、さびしい内容でし一番華やかなりし時。まさに、高度成長期であったこ

MOAPやKCP+は、特定携帯電話事業者向けプた。しかし、ESECはこれまで同様に活気があり、組とも事実でした。そして、携帯電話はついにJavaを搭

ラットフォームとして成長し続けましたが、一携帯電話載するに至ります。

事業者がどこまでプラットフォームをけん引していける

Androidの衝撃

込み大国ニッポンの力強さを感じました。
その中でも、Androidは別格で、Androidの展示

写真1

Androidの展示にはつねに人だかりができた

しかし、高機能化に突き進む一方、不具合によるのか、3Gが浸透するにつれ、ガラパゴスという言葉も周辺には、不況をまったく感じさせない雰囲気があり回収が相次ぐようになります。また時を同じくして、契やや否定的に用いられるようになり、その動向は注目ました。弊社でも「高速化 Android 環境」と題して展

約者数の頭打ちが囁かれ、セット機ベンダが揃って売されていました。

示を行いましたが、Androidの展示エリアにはつねにり上げの下方修正を行いました。

人だかりができ、3日間で700枚用意したパンフレット

このような背景から、安定性／高機能化／低コスが初日でなくなり、会場にてインクジェットプリンタでト化への直接的な要求が高まり、これを満たすプラッ

増刷するはめになりました（写真1 ）。

トフォームに対する期待が高まりました。その中で、Androidの受難

また、定員50名の無料セミナーを催したところ、セWindows Mobile、Symbian OS、Linux、さらにAndroidはそんな喧騒のさなかに登場しました。IT

ミナー会場がかなりわかりにくい場所であったにもかか

BREWがそれぞれの特徴を生かした形で携帯電話に業界では、Microsoftに対抗できるということがひとつ

わらず、ほぼ満席になりました（写真2 ）。1日1回、協採用され、普及していきました。日本国内では、さらのステータスになったりしますが、当時、Googleは間力会社のブースの一角で開催したプライベートセミナーにFOMA 開発環境であるMOAPやauの携帯電話向

違いなくその有力な一社でした。そのGoogleが旗振でも、毎回、立ち見が出るほどの賑わいを見せました。

け開発プラットフォームであるKCP+などが登場し、プり役となってOHAを立ち上げ、世界中の主たる携帯

ラットフォームという言葉自体も広く認知されるように

電話関連企業30社以上と手を組んでプラットフォーム

かつてこれだけ大きな話題を提供したプラットフォーム

2

組込みプレス Vol.16

写真2

満席状態となったAndroidセミナー

組込みプレス Vol.16

3

特集 1

Android による組込み開発

第1章

Androidが変える組込みシステムを構築するというのですから、話題にならないはずがそこには景気が少しくらい悪くとも比較的元気であっありません。有力紙もこぞってこのセンセーショナルな

たIT 関連企業も名を連ねていました。Android 携帯

展示内容としては高速化 Android 環境という展示

ニュースを取り上げました。

電話の開発計画はほとんど公表されていませんでしたを行いました。Androidの基幹コンポーネントである

AndroidはLinuxをデフォルトのOSとしており、とテクニカルな面でも、Androidは実にセンセーショ

が、水面下で進んでいた計画の多くが、2008年末かDalvikVMには性能上の大きな問題が残っており、パ

りあえずLinuxが動作するデバイスへの展開の可能性ナルでした。Java 技術に基づくアーキテクチャは、実ら2009 年初頭にかけて中断の憂き目にあったことはフォーマンスを要求される部分はすべてネイティブ実を秘めています。CPU 対応としては、携帯電話用といは誰もが一度は夢見たアイデアでしたが、かつて、こ間違いありません。

装に置き換えられています。これがAndroid 環境自うことでまずARMがサポートされていますが、ARMと不幸中の幸いは、T-Mobile G1の出荷が始まって身のポータビリティを下げ、Java 言語で記述された

今後の組込み機器向けCPU 勢力を2分するといわれいたことかもしれません。これが間に合わなければ、秀逸なソフトウェア／サービスの速やかな導入を妨げるAtomベースのデバイスにおいても、実用化ベース

Androidそのものがまだ世に出ていなかったかもしれる元凶となっています。この大問題に取り組むため、のAndroidの対応が行われています。さらに、MIPS

ないのです。

弊社ではDalvikVMにJITコンパイラをサポートし、

テクノロジー社は自らMIPS 向けのAndroidの対応をAndroid 環境自体の高速化の可能性を示しました

発表し、国産CPUとしてはSH向けのポーティングも始（図1 ）。

まっています。

れほどの規模で実現に向けて動き出した会社はありませんでした。
そして発表から１年を経て、ついにAndroid 搭載
携帯電話『T-Mobile G1 』が発売されました。独
Deutsche Telekomが今年4月に行った決算発表によると、アメリカで発売されたこの端末は半年ほどで100万台を売り上げ、iPhone, BlackBerry Curve

Androidの飛翔1〜高速化〜

Androidの可能性の大きさを実感しました。

ました（写真5 ）。

製品化ということについて言えば、Androidはいま

さて、確かに好調を維持しているAndroidですが、日系企業の多くが2009年3月末を期末と定めておさすがに良いことばかりではありません。それも100年り、それはすなわち、少なくともそのころまで国内のAndroidの飛翔2〜デバイス対応〜に一度の大不況がやってきて、Androidを直撃したのAndroid 開発が進まないことも意味しました。また、

また、携帯電話以外のデバイスへの適用は、もす。しかし、おもに中国本土において、2009年末にはです。Androidのような大規模プラットフォームには大実質的な決算があきらかになる時期はもう少しあとにうひとつの大きな課題です。期待と言いかえてもい

2桁の製品が登場すると言われており、実際に、大小

きな初期投資を必要とします。まだバグも多く、他の章なりますので、4月もAndroidに関する動きは鈍かっ

いかもしれません。P N D やいわゆるモバイル情報で触れるような性能の問題の改善／解決が必須とされたと言えます。

端末はその典型です（図 2 ）。JavaはWrite Once

／Pearlに次ぐシェアを確保しました。

ました。

決算がおおむねあきらかになり、2009年度の計画

Run Anywhereというスローガンを掲げましたが、それが、かつてない大規模な不況のために、どのもなんとなく決まってきたゴールデンウィーク前後から、Androidも、そのプラットフォーム自身としてはRun

企業も研究開発や商品開発などの投資を凍結し、経Android 周辺の市場も再び動き出し、冒頭のESEC

Anywhereを自負していると言えるでしょう。前述の済の様子を窺う姿勢に移行しました。また、新聞やテ

へとつながっていったのです。来場者は皆熱心で、ESECにおいて、多様なデバイスへの応用が目につきレビでご存じの通り、大規模なリストラが敢行され、突っ込んだ質問をする人も多く、そういったことからも6000

インタープリタ

だ難産のさなかにあり、現時点ではT-Mobile G1とその後続機種が発売されているのみです。一般の目から見れば、1機種にしか映らないのではないかと思いま

JIT

5000
4000
3000
2000
1000
0

算
計
数
素

ープ
ル

算
演
理
論

図 1 Atom 搭 載 MID 端 末 に お け る イ ン タ プ リ タ と
JIT の実行速度比較。論理演算などの JIT コンパイルは何倍もの性能改善を示す

4

組込みプレス Vol.16

写真 3 Atom 搭載 MID 端末における JIT コンパイル
実行のデモ

写真 4 ご存知 Armadillo 500FX。ARM の JIT コン
パイル実行のデモを行った

写真 5 Android の動画コーデックを商品のコーデッ
クに置き換えて高速化したデモ

組込みプレス Vol.16

5

特集 1

Android による組込み開発

図2
Android の 適 用 可能性を示した図。特に ESEC の よ う な
会場では、Androidの携帯電話以外のデバイスへの適用に関する突っ込んだ質問
が相次いだ

第1章

Androidアプリ

Android
アプリ

ユーザ
アプリ

Android
フレームワーク

Android
フレーム
ワーク

拡張
フレーム
ワーク

Android
ランタイム

Android
ランタイム

Androidライブラリ

Android
ライブラリ

追加
ライブ
ラリ

Android
フレーム
ワーク

OSGI
プラット
フォーム

Dalvik（Android
VM）
Android
ライブラリ

OSGI
ライブラリ

すべてのレベルでインテグレーションできることは重要Linuxカーネル

Linuxカーネル

Linuxカーネル

携帯電話

モバイル情報端末

一般組込み機器（Networkデバイス、
STBなど）

さまざまな事業者／ベンダの動きが活発になってきてNCの現実解います。今年後半のAndroidの動向は、まさに目が離せない状況となるでしょう。

AndroidとJavaの関係性
最後にもう一点、JavaとAndroidの競合関係につとも言ってしまっても面白いでしょう（NCが目指した

これらを骨肉の争いと称する人も少なからずいます。

速度性能を第一とするAndroidの品質の向上が急務

Android、そしてその実質的基盤であり、Androidでしょう。その詳細は他の章に譲り、Android端末おの当面最大の敵であるJavaの両方はもともと同根であよびJava 端末、そして後続のさまざまな端末の群れ

り、まさに骨肉、その争いは兄弟喧嘩の様相を呈してがクラウド世界を気持ちよく駆け回る姿を夢見て、本います。ではこの戦いは、どのような展開を見せるので章を結びたいと思います。

しょうか。
この結論にはやや勇気を要しますが、誤解を恐れず、家電業界の事例にあてはめると、HD DVD vs Blu-Rayの争いに通じるものがあります。あるいは、

ベータマックス vs VHSと聞いて、なるほどと膝を打った方は、いわゆるアラ
フォー以上の世代になりますでしょうか。

ネットワークセントリックな世の中になりつつあるという

この結論は多分に私見を含みますので、その点をごことです。NC：Network Computerとは、1990年

了承いただきたいのですが、筆者としては、Googleと代半ばにOracleが中心となって策定した、現代で言Oracle、また他のクラウド事業者が、ベータマックス

うシンクライアント端末のことですが、普及はしませんとVHSのように長きに渡った争いを展開してほしいとでした）。

考えています。そのような争いは早く決着した方が消費者のためだという声も確かにあります。

いて述べたいと思います。2つのプラットフォームの争

そして、Ericがクラウドコンピューティングという言葉

いは、クラウドの覇権争いにもつながるものと言えまをまだ表明していなかったころ、次世代のクライアント

しかし、HD DVDとBlu-Rayの戦いがあまりにも早す。裁判準備のために、Androidのソースコードにはプラットフォームの最右翼と目されたのがJavaでした。

く決着してしまったため、「 過当競争のタイミングも早ま

絶対にアクセスしないようにと、Sun 社内でアナウンス

そして、それを真向うから覆したのが、Java 技術をふり、両者ともビジネス的に意味のある規格ではなくなっがなされたという噂もまことしやかに囁かれました。元んだんに盛り込んだAndroidだったのです。

てしまった」と漏らす関係者が少なくないこともまた事

次世代のITビジネスはクラウド・コンピューティングの実なのです。どんな技術も、一時の盛り上がりを見せに叛旗をひるがえした、SunよりJavaを知っている彼

覇権争いになるという見解はもはやあらためて申し上げ

たあとは一般化し、成長が鈍る局面を迎えます。究には勝てないといった言い方もされました。

るまでもないことです。Googleがその大事業のために極的には“空気のように浸透した”という成果だけが残Androidをプロデュースしたことは明白な事実です。

り、それ以上の発展はありません。一方、競い合ってはSunのCTOまで勤め上げたEric SchmidtがSun

そのEricが次世代のコンピューティング形態として掲げたのがクラウドコンピューティングです。クラウドについてはいろいろな見方がなされていますが、6

ユーザのアプリ（OSGIバンドル）

では、Javaはどうなったのでしょうか？これも、本いる間は、相手をやりこめ、自分たちが躍進するため誌の読者ならずとも周知の事実ですが、Oracleがに懸命になり、それが技術を活性化させる触媒となりSunを買収したことにより、JavaはOracleの技術となます。

現代のテクノロジーに基づく
クライアント・サーバの発展形

りました。すると、クラウドコンピューティングの支配

ポリティカルな理由で握りつぶしてしまうには、Java権を賭けたGoogleとOracleの大決戦という図式に、もAndroidも、どちらも惜しい存在です。両者とも、もという言い方ができると思います。あるいは、より端的

AndroidとJavaは見事に当てはまるのです（IBMが、

うひと働きもふた働きもしてもらわなければと強く願いに、数億ドルの譲歩ができずJavaの権利を逃したらしいとます。そして、Android 特集ということで申し上げますいうショートストーリーも残されました）。

と、今 JavaとAndroidを同じ土俵に並べるためには、

組込みプレス Vol.16

Androidが変える組込みシステム

column■ Javaは遅いか、

Androidは速いか

本章全体に渡って、Androidの遅さをその短所として挙げていますが、速度についてはJavaとAndroidは見事に明暗が分かれました。ご存じの通り、Javaは「動くホームページ」という、今にして思えば実に時代がかったうたい文句で登場しました。そして、当時の Microsoftと戦う勇敢な企業の一社であったSunの切り札として、
Microsoft 製品を駆逐するための対抗馬としての役割を負ったのです。

しかし、そのような場合によくあるパターンとして、機が熟しておりませんでした。当時のJavaはJITコンパイラなどの技術を搭載しない純粋なインタープリタでしたが、にもかかわらずデスクトップ

PCでユーザインターフェースの記述に使われ、また、組込み向けということで携帯電話に採用されていきました。そこで、その遅さがあきらかになり、Javaすなわち遅いというイメージを定着させてしまいました。その印象は今もって残り、Javaが世に出てから10有余年を経た今でも、Java 製品の売り込みの際に「でもJavaって遅いんですよね」という、懸命な弁解を要する素朴な疑問を投げかけられることは珍しくないのです。

Androidはどうでしょうか。実際には、現代のハードウェアのパフォーマンスを10%も引き出せな

いようなレベルのプラットフォームであるにもかかわらず、ごく好意的に迎えられています。これは、現代の組込み機器の性能が十分に上がったことと、T-Mobile G1向けの開発の段階で、十分にネ
イティブ化がなされた結果によります。そのおかげで、Androidはすぐにも搭載〜製品化が可能という誤解を与えています。

JavaとAndroidの対決に際し、突貫で製品化にこぎつけたAndroidは、第一印象こそ良かった

ものの、これから試練を迎えることになります。

組込みプレス Vol.16

7

特集 1

Android による組込み開発

第

2章

第2章

株式会社イーフロー
事業統括本部 第1事業部

中川 輪土

Nakagawa Rindo

Android高速化
テクニック

図2

Javaコードの変換

Javaコード

インスタンスを生成するコードを書くと、上記 1~3

Javaバイトコード

DEXバイトコード

合、不要になったオブジェクトを回収してヒープの空き

Iofjaofjaofjaofjaofj
Osaojaofafa

を作るためにGarbage Collection（以下、GC ）がSfajofjafo

発生します。GC 実行中はすべてのスレッドが停止して

Saofjaofja
Aoaooafoa.java.class.dex

Android構成図

Android Framework
DalvikVM

Androidの現状

Androidに移植した際にこの処置の遅さが一番問題となります。

Android 上で動くAndroidアプリケーションはJava 言語を使って作成することができます。高機能な
Android Frameworkがすでに用意されているため高い生産性を持っています。一方、Androidは同様

Androidが遅い理由のハードウェア構成であっても携帯 Javaに比べて処AndroidアプリケーションはJava 言語を使って理が遅いのが現状です。図1は携帯 JavaとAndroid

作成されます。Javaコードは図 2のようにJavaのバの 性 能を組 込み J a v a ベンチマークE m b e d d e d

イトコードである.classファイルに変換され、さらにCaffeineMarkで測定した結果です。スコアの高さはAndroid独自のDEXバイトコードに変換されます。

Androidライブラリ

CPU(ARM/x86)

呼び出す必要はなくなります。

化テクニックについて解説します。

組込みプレス Vol.16

高速化テクニックがそのまま使えます。

int size = inst.getSize（）;for（int i=0; i <size; i++）inst.getIndex（i）;

リスト2●インスタンス変数のキャッシュ

リスト3のcall01メソッドのようにインスタンス変数を1.クラスのロード、初期化のcall02ようにローカル変数にインスタンス変数をキャッマシンはさまざまな高速化手法が適用されており、ネ

2.インスタンスのヒープへの確保

シュして、結果をインスタンスに格納することでインスタ

イティブアプリケーションとさほど変わらない速度で実3.インスタンスの初期化

ンス変数の取得、値の格納を減らすことができます。

Javaの場合も同じバイトコード形式のclassファイルをLoop Logic String Float Method

Java 言語で作成するため、Javaアプリケーションの

for（int i=0; i < inst.getSize（）; i++）inst.getIndex（i）;

Java仮想マシン上で実行しますが、現在のJava仮想

2000

Sieve

クについて解説します。Androidアプリケーションは

リスト1

頻繁に使用すると、毎回インスタンス取得、値の格納

ティブアプリケーションと比べて格段に遅くなります。

0

リスト1のようにforループの終了条件でメソッドを呼●インスタンス生成の抑制

3000

1000

8

タ方式で実行されるためC 言語などで作成されたネイ●ローカル変数へのキャッシュ

培ったJava 高速化手法を元にしたAndroidの高速

まずはAndroidアプリケーション高速化のテクニッ

Androidアプリケーションを実行します。インタープリ

ションの分野で活用されています。

ローカル変数に入れることで、毎回getSizeメソッドを

DEXバイトコードはバイトコードであるためCPUに依P905i
ARM:500MHz

ドの場合はスレッドプールと呼ばれ、Webアプリケー分の差があることになります。本章ではこの10年間で

図1 Embedded CaﬀeineMark 結果

4000

戻してインスタンスを初期状態に戻します。とくにスレッ

この場合、リスト2のようにgetSizeメソッドの結果を

DalvikVMと呼ばれる仮想マシン上で実行されます。

DalvikVMはバイトコードインタープリタ方式でクトを取り出し、不要になったオブジェクトはプールに

Javaに似ています。AndroidとJavaの間には10年に比べて約2〜10倍性能が低いことがわかります。携

5000

プーリングし、必要な時にプール（pool ）からオブジェ

び出すと、終了条件判定ごとにメソッドが呼ばれます。

変 換 され た D E X バイトコードは 、図 3 にある存しません。

ジェクトプールと呼ばれます。生成したオブジェクトを行することができます。Androidは1990年代後半の性能の高さに比例しています。Androidは携帯 Java

Google Dev Phone 1
ARM 528MHz

たインスタンスを破棄せず、使いまわすことでインスタLinux Kernel

Androidアプリケーション
高速化テクニック

6000

しまうため、結果的に実行速度が低下します。生成しンスの生成を抑えることができます。この手法はオブAndroidアプリケーション

帯 Javaで問題なく動作しているアプリケーションを、が毎回実行されることになります（ただし、1については初回時のみ）。とくに2では、ヒープに空きがない場

Aafahifhdaih af aiofh
fapfasosfhafhapfhsanfiahfip
ahfipahfdipahfp
hasiofhaofihasfhafhak

図3

Android高速化テクニック

インスタンスは以下の手順を経て生成されます。

命令がDalvikVM上で実行されます。この場合リスト４

組込みプレス Vol.16

9

特集 1

Android による組込み開発

第2章

リスト3

リスト6

private int n = 0;
public void call01（）{n = 1 + n;n = 2 + n;n = 3 + n;n = 4 + n;n = 5 + n;}

XXXX.call02:（）V
iget v0, v1, LXXXX;.n:I
add-int/lit8 v0, v0, #int 1 // #01
add-int/lit8 v0, v0, #int 2 // #02
add-int/lit8 v0, v0, #int 3 // #03
add-int/lit8 v0, v0, #int 4 // #04
add-int/lit8 v0, v0, #int 5 // #05
iput v0, v1, LXXXX;.n:I
return-void

リスト4

private int n = 0;
public void call02（）{
int tmp = n;tmp = 1 + tmp;
tmp = 2 + tmp;
tmp = 3 + tmp;
tmp = 4 + tmp;
tmp = 5 + tmp;
n = tmp;}●スタティックメソッドの活用

インスタンスメソッドを呼び出すためには、インスタンスを生成する必要があります。スタティックメソッドの場合、インスタンス生成のコストがかかりません。また、インスタンスメソッドを呼び出す場合、DalvikVM
はinvoke-virtual 命令を実行してメソッド呼び出しを行います。スタティックメソッドの場合は、invoke-

リスト5がcall1メソッド、リスト6がcall2メソッドのstatic 命令を実行します。invoke-static 命令の方

バイトコードをAndroid SDKのdexdumpツールでがinvoke-virtual 命令よりも実行負荷が小さい実装

逆コンパイルしたものです。iget 命令がインスタンス変のため、スタティックメソッドの呼び出しの方が速くな

数取得、iput 命令がインスタンス変数格納の命令でります。

す。call01メソッドで頻繁にiget/iput 命令が実行されています。iput/iget 命令ではインスタンスがnullでないかのチェックなどが毎回実行されます。命令として●浮動小数点演算は極力使用しない

浮動小数点演算は整数演算に比べて演算速度がは実行負荷が高いため、この処理を省くことでアプリ遅いため、浮動小数点演算はなるべく使用しないようケーションの高速化が可能になります。

にします。

リスト5

XXXX.call01:（）V
iget v0, v1, LXXXX;.n:I
add-int/lit8 v0, v0, #int 1
iput v0, v1, LXXXX;.n:I
iget v0, v1, LXXXX;.n:I
add-int/lit8 v0, v0, #int 2
iput v0, v1, LXXXX;.n:I
iget v0, v1, LXXXX;.n:I
add-int/lit8 v0, v0, #int 3
iput v0, v1, LXXXX;.n:I
iget v0, v1, LXXXX;.n:I
add-int/lit8 v0, v0, #int 4
iput v0, v1, LXXXX;.n:I
iget v0, v1, LXXXX;.n:I
add-int/lit8 v0, v0, #int 5
iput v0, v1, LXXXX;.n:I
return-void●数はstatic ﬁnalで定義する

定数をstatic finalでフィールドに定義すると、C言語のマクロ定義のようにフィールドを使用している部分がDalvikVM 上ですべて定数として扱われます。
static finalを付けずにフィールドを定義した場合、スタティックフィールドのアクセスの度にスタティックフィールドの取得が必要になるため、その分速度が遅くなります。

●ポリモーフィズムの使用を控える

ポリモーフィズムを使用することで抽象化を行い、機能と実装を切り離すことができますが、抽象化される

10

組込みプレス Vol.16

Android高速化テクニック

分だけ実装のコード呼び出しの際オーバーヘッドが発Android Native Development Kit（以下、NDK ）生します。このオーバーヘッドの発生を減らすため、でです。JNIはJavaからCやC++で書いたネイティブ

きるだけポリモーフィズムの使用は控えるようにします。

コードを呼び出すためのインターフェースです。JNIを使うとJavaのコード実行処理に時間がかかっている●オブジェクト指向プログラミングを止めるとが可能になります。ネイティブコードで実行されるこ

オブジェクト指向プログラミングは、生産性が高いとになるので処理速度は向上しますが、Javaコードに半面、その分処理が全体的に重くなります。オブジェ

比べてポータビリティが悪くなります。また、JNI 呼び

部分をC/C++ 言語のネイティブコードに書き換えるこ

クト指向プログラミングを止め、インスタンスのアクセ

出しのオーバーヘッドも通常のJavaメソッドの呼び出

スを減らし、メソッドをインライン展開します。生産性

しに比べて大きいのが難点です。

は落ちますが、その分余計なオーバーヘッドが減るた
め速度は向上します。

● Androidアプリケーション描画の高速化

A n d r o i dアプリケーションで描画を行うためには、まずアクティビティ（Activity ）を生成して描画す

JNIを使用するメリット、デメリットに注意が必要です
が、Androidの一番のボトルネックであるインタープリ
タ実行がなくなることで、高速化の効果はかなり大きくなります。NDKの詳細については別項を参照願います。

●Designing for Performance

最後に、Android 開発ガイドのDesigning forる領域を設定します。描画する領域にはCanvasとPerformanceにもAndroidアプリケーションの高速

SurfaceViewの2種類があります。Canvasの描画は化の話が書かれていますので紹介します。

アプリケーション側のスレッドで行う必要があります。
描画に時間がかかるとその分だけアプリケーションの処理が止まることになります。また、Canvasはソフトウェ
ア上で描画処理を行うため描画速度も遅くなります。

DalvikVM高速化
テクニック

一方 SurfaceViewの場合は、ハードウェアアクセ

Androidはオープンソースで、一部のコードを除ラレータを使った描画を指定できます。Androidアプ

いてほとんどが公開されています。DalvikVMのソー

リケーションは描画スレッドを意識する必要がありま

スコードはApache License V2.0で公開されていません。2D 描画の場合はフレームバッファに描画されす。DalvikVMはおもにC 言語で書かれており、イン

ますが、3D 描画の場合はOpenGL ESが使用されタープリタの部分はARM v4／v5、x86の場合はアるのでハードウェアアクセラレータを使うことで描画をセンブラ言語で書かれています。DalvikVMの実装を高速化できます。ゲームなど描画時に大きな負荷がか変更することで高速化する手法について解説します。

かるAndroidアプリケーションを作成する場合には、Androidシステム開発者向けの解説になります。

SurfaceViewの使用が望ましいでしょう。

●Android Native
Development Kit（NDK ）の活用

JavaコードのJNI化

Android1.5からJNI（Java Native Interface ）Androidフレームワークのクラスと、システムクラス

が公式でサポートされました。そのためのツールが（java.lang 等）はJavaコードで実装されています。

組込みプレス Vol.16

11

特集 1

Android による組込み開発

第2章

このため、実行時にはインタープリタで実行されるこれており、命令によってコードユニットの数が定義され3. 1、2のレジスタの内容を加算する。

とになります。システムクラスのメソッドをJNI 化するこています。

4. 加算した結果をDalvikVMのAレジスタ（実体はAndroid高速化テクニック

GCの最適化メモリ）に格納する。

とで「Android Native Development Kit（NDK ）たとえばint 型の加算命令 add-int 命令の場合は、の活用」と同じ効果を得ることができます。たとえば頻リスト7のように2コードユニットの4バイトで定義されて1〜4を実行するネイティブコードを生成し、動的確

DalvikVMには未使用のオブジェクトを回収する

繁に使われるクラスのひとつにjava.lang.Stringが挙います。add-int 命令はレジスタBとレジスタCに加算保したJITコンパイルコードを格納するメモリにコピーGCが実装されています。DalvikVMのGCはMark &げられますが、これらのクラスのメソッドをJNI 化する

する2つのint 型整数を加算し、結果をレジスタAに入します。そのメモリ領域に実行権限をつけることで、コ

Sweep GCが採用されています。DalvikVMのGCは、だけでシステム全体の性能が上がる場合もあります。

れる命令です。このレジスタはCPUのレジスタではな

ピーしたネイティブコードを実行できるようにします。そまずGCが開始される前にすべてのスレッドを停止しまStringクラスのメソッドはシステム全体に影響するの

く、DalvikVMの仮想マシンのレジスタを指しているのあとに、JITコンパイルしたコードの先頭番地にジャす。図6のようにGlobal Rootから参照されるオブジェ

で、時にはJNIの中でアセンブリ言語を使用してさらなので、具体的にはメモリのどこかがレジスタとして扱わンプさせて、JITコンパイルコードの実行が終わったらクトAが存在し、オブジェクトAがオブジェクトCを、オる高速化を行う場合もあります。

れているだけになります。

インタープリタに戻るようにします。

ブジェクトCがオブジェクトEを参照しているとします。

Just-in-time（JIT ）コンパイラ
Just-in-time（以下、JIT）コンパイラは、Android

リスト7

add-int vAA, vBB, vCC
opcode（8bit）
A: destination register or pair（8 bits）
B: ﬁrst source register or pair（8 bits）
C: second source register or pair（8 bits）

アプリケーション実行中にDEXバイトコードをネイティ
ブコードに変換します。AndroidアプリケーションのJITコンパイラは、図 4のようにDEXバイトコード

DEXバイトコードをJITコンパイラでネイティブコード

とDalvikVMのレジスタのアドレスを元に、ネイティにコンパイルすることにより、Androidアプリケーショ

ブコードを生成します。生成するネイティブコードは、ンをDalvikVM 上でインタープリタとして実行するのIntel Core2 Duo 上のUbuntu／x86 環境で、

まず、参照をたどれるオブジェクトをマークします。

DalvikVMのオリジナル（インタープリタ版）とイー

オブジェクトA、C、Eがマークされるオブジェクトに

フローで開発したJ I Tコンパイラ版をE m b e d d e d

なります。次にマークされていないオブジェクトを回CaffeineMarkで測定した結果が図 5になります。

収します。このときマークされていないオブジェクトはSieve、Loop、Logicのみの測定結果となりますが、B、Dなので、オブジェクトB、Dが回収されます。オブ

JITコンパイラ版がDalvikVMのオリジナル（インタージェクトの回収が終わったらスレッドを再開させます。

プリタ版）に比べて2〜6倍速くなっていることがわかり

DalvikVMのGCのメリットは、実装が容易であることます。

です。一方デメリットとしては、GCの停止時間はヒー

JITコンパイラは、現在のJavaでは当たり前のプサイズが大きくなると増加していくことが挙げられま

add-int命令の場合以下になります。

ように搭載されている機能です。JITコンパイラはす。また、DalvikVMのGCではオブジェクト回収後にではなく、ネイティブコードとして実行できます。DEX

1. DalvikVMのBレジスタ（実体はメモリ）の内容を大きな高速化を見込めますが、JITコンパイルした

図6のようにコンパクションを行わないので、オブジェク

バイトコードのフォーマットについては、AndroidのCPUレジスタに格納する。

コードの管理の実装、消費メモリの増加、JITコン

トAとオブジェクトCの間のように歯抜けの状態になりソースコードのdalvik／docs 以下に仕様があります。

2. DalvikVMのCレジスタ（実体はメモリ）の内容をパイルのオーバーヘッドなどデメリットもあります。

ます。

DEXバイトコードは16ビットのコードユニットで区切ら

CPUレジスタに格納する。

図5 Embedded CaﬀeineMark 結果

図6 Mark & Sweep GC

DEXバイトコード
add-int v0, v1, v2

0xXXXXXXXX#疑似アセンブラコード# v1の内容をr0に格納

mov (0xBBBBBBBB), r0

図4 JITコンパイル

DalvikVM

v0=0xAAAAAAAA
v1=0xBBBBBBBB
v2=0xCCCCCCCC# v2の内容をr1に格納
コンパイル

mov (0xCCCCCCCC), r1# r0とr1を加算してr2に格納
add r0, r1, r2#r2の内容をv0に格納

mov r2, (0xAAAAAAAA)

6000

Global Root

5000

ヒープ

4000
3000
2000

GC

1000
0

算
計
数
素

ープ
ル

Global Root

算
演
理
論

インタープリタ

ヒープ

JIT

図6.png12

組込みプレス Vol.16

組込みプレス Vol.16

13

特集 1

Android による組込み開発

第3章

第実際 Android Emulator 環境でGCが発生すると& Sweep GCと同様にGC停止時間が長いです。

200~500msの間処理が停止します。Google Dev

オブジェクト指向プログラミングではオブジェクトのPhone 1の場合約 100msの間処理が停止します。

寿命が短く、サイズが小さい大量のオブジェクトが生

100msの間すべてのスレッドは停止するため、結果成されます。世代別 GCでは積極的にYoung 領域で的にAndroidアプリケーションの処理が遅いように見オブジェクトを回収し、長く使うオブジェクトをOld 領

えてしまいます。GCにはいくつかのアルゴリズムがあ域に残すことでフルGCが発生するのを軽減させます。

ます。DalvikVMのGCをそれらに置き換えることで結果的にすぐ終わるGCが頻繁に発生しますが、長時

AndroidアプリケーションのGCの影響を軽減させる

間停止するフルGCを軽減することで、全体的に性能ことができます。

を上げることが可能になります。

3章

株式会社イーフロー
事業戦略本部 R&D

久納 孝治

Hisano Koji

Androidネイティブ
コードデバッグ手法

世代別GC

Incremental GC

世代別 GCは図 7のようにヒープが大きく、Young

Incremental GCはオープンソースのBoehmGC

領域とOld 領域に分かれています。生成したばかりので使われているGCです。GCとしてはMark & Sweep

インスタンスはYoung 領域のFrom 領域に作成されGCと同じオブジェクト管理方式なのですが、オブジェ

ます。From 領域がいっぱいになったら、参照されてクトがいっぱいになってからGCを開始するのではな

いるオブジェクトをTo 領域にコピーします。コピーした

く、ユーザープログラムと交互に短い間隔でGCを少昨年 Androidのソースコードが公開されました。

では、実際に"Hello, World!"と表示するシンプルな

あと、ToとFromのラベルを入れ替えます。次にオブしずつ実行します。GCの1回あたりの停止時間は短く

ユーザが日々使うA n d r o i dアプリから、下支えのネイティブアプリ（コマンドラインアプリ、以下 helloア

ジェクトを作成するとFrom 領域の参照されているオブ

なりますが、トータルのGC 時間はMark & Sweep

Linux OS／ドライバの部分まで、ほとんどすべてのプリ）を題材に開発環境を徐々に整えていきましょう。

ジェクトのあとからオブジェクトを確保していきます。こGCと同じになります。長時間停止すると不都合の生ソースコードを読めるようになりました。読者の中にはのGCをマイナーGCといいます。

じるアプリケーションが多い場合は、このGCが適し

実際にソースコードを読み進めている方も大勢いらっています。

しゃると思います。

マイナーGCの領域は小さいため、GCの停止時間域に残ったオブジェクトはOld領域に移動します。Old
領域がいっぱいになった場合は、Old 領域でMark

はじめに

リアルタイムGC& Compact GCを実行します。Mark & Compactには用いることができません。そのため、これらを開発する際には、自分自身で開発環境を整備する必要があります。

他の記事や書籍で通常のAndroidアプリの開発手は短くなります。何回かマイナーGCを実行しYoung領

makeコマンド +エディタによる開発

法は多々解説されていますので、本章ではAndroidア

一番シンプルな開発環境は、makeコマンド + エ

プリより下の層に取り組む際の開発手法について解説

ディタによる開発です。公開されているAndroidソー

したいと思います。

スコードは、すべてmakeを用いてビルドされます。しGCを実行後、コンパクショ

Mark & Sweep GCや世代別 GCなどはGC 実行

通 常 の A n d r o i d アプリの 開 発 にあたっては、たがって、新規にディレクトリを追加して適切にファインを実行してヒープの歯抜けを防ぎます。このGCをメ中にすべてのスレッドが停止してしまいます。それに対Googleより提供されているAndroid Development

ル構成を行えば、短時間でネイティブアプリを開発でジャーGCもしくはフルGCといいます。フルGCはMark

してリアルタイムGCはGC 実行中でもスレッドが止まら

Toolkit（ 以下、ADT ）を使って、Eclipse 上で効率きる環境を整えられます（開発環境の整備が短いのでない方式、またはGCの最長応答時間を保証するGC

的にコードを書くことができます。さらに先日公開されあって、開発時間が短いわけではありません）。

を指します。現在、リアルタイムGCについては実用化

たNative Development Kit（ 以下 NDK ）を用いる

helloアプリをAndroidの流儀に従って作成してまでこぎつけたケースは少ないですが、リアルタイム

ことによって、Androidアプリ内で使うネイティブライ

みましょう。まずはチェックアウトしたAndroidソース

GCの実用化に向けた研究開発は着実に進められておブラリの開発も効率的に行えるようになりました。

コードのトップディレクトリ直下（以下 MYDROID 環

GCはMark & Sweep

図7 世代別GC

From

To

り、より一層の高速化実現など今後の成果が期待されます。

Young領域

14

Androidネイティブコードデバッグ手法

組込みプレス Vol.16

Old領域ですが、Googleから公開されているADTやNDK

境変数にディレクトリパスが登録されているものとしま

は、通常のAndroidアプリの開発向けです。より下位す）に、helloディレクトリを作成して下記のファイル群

層のネイティブアプリやシステムライブラリなどの開発を作成します。

組込みプレス Vol.16

15

特集 1

Android による組込み開発$MYDROID/hello/Main.cの内容#include <stdio.h>
int main（int argc, char *argv[]）{
printf（"Hello, World!\n"）;return 0;}$MYDROID/hello/Android.mkの内容

第3章

念のため、/system/binフォルダ以下にhelloアプ
リがインストールされていることを確認しましょう。
コマンド入力$ adb shell ls -l /system/bin/hello-rwxr-xr-x rootshell
5288 2009-06-26 07:11 hello

ここまで実行するのにどれぐらい時間がかかったでこれによりエミュレータを起動した状態で、アプリを転送して試せるようになったので、時間が短縮されたはずです。

ディレクトリ単位でビルドして時間短縮
トップディレクトリでmakeすると、helloアプリとはAndroidネイティブコードデバッグ手法

コマンド入力$ mmm hello（途中の出力は略）$ adb push $MYDROID/out/target/product/generic/system/bin/hello /data
64 KB/s（5288 bytes in 0.080s）$ adb shell /data/hello
Hello, World!

上記作業の入力を別のシェルスクリプトとして書いてLOCAL̲PATH:= $（call my-dir）include $（CLEAR̲VARS）

しょうか？ PC 環境にもよりますが、ビルド + エミュ

関係のないフォルダもチェックしてビルドするので、長おくと、より短時間でビルド + 実行が行えるようになり

LOCAL̲SRC̲FILES:= \Main.cレータ起動＋アプリの起動＋結果確認とひと通り流す

い時間がかかります。次はhelloアプリ単体でビルドでます。

までに、数十分かかったかと思います。コードを変更

きるようにして時間を短縮します。

LOCAL̲MODULE:= hello

するたびに上記の時間が必要になると、開発が極めてinclude $（BUILD̲EXECUTABLE）

非効率ですので、順に改善していきます。

その後、下記のようにコマンドを入力してビルドを行います。
コマンド入力$ cd $MYDOROID$ make

ビルドが完了したら、1.5から導入されたAndroid
Virtual Diskを使わずにビルドしたイメージファイルを直接指定してエミュレータを起動します。

アプリをファイル転送
して時間短縮Androidエミュレータが起動するまでには、長い時幸いなことに、A n d r o i dソースコードにはディレクトリ単 体 でビルドするためのシェルスクリプト（$MYDROID/build/envsetup.sh ）が含まれていenvsetup.shには、説明以外にもさまざまな便利なコマンドがあります。ひと通り内容をチェックされることをお勧めします。

うに/bin/shがdashになっている場合には、下記をデバッグ環境を整備して時間短縮

sudoコマンドで実行して変更する必要があります。

h e l l oアプリは非常にシンプルなプログラムでします。このシェルスクリプトは/bin/shがbashである
ことを前提に書かれているので、最近のUbuntuのよ

間待たなければいけません。まずは、ビルドしたあとにたが、複雑なプログラムになると、デバッグのため

Androidエミュレータを毎回起動する必要がなく試せ

コマンド入力にデバッガを使いたいところです。ここでは、フリー

るようにします。

$ ln -sf /bin/bash /bin/sh

で使えるgdbを用いてデバッグ環境を整えます。前

ビルドしたアプリは、$MYDROID/out/target/

項のenvsetup.shをひと通りチェックされた方は、product/generic/system/bin/helloとして生成さ/bin/shがbashであることを確認して準備が整った

gdbclientというコマンドが入っていることに気づかれれます。エミュレータを起動している状態で、このファら、sourceコマンドで現在の実行コンテキストにコマたと思いますが、このコマンドを使ってデバッグします。

コマンド入力イルを/dataフォルダ以下に転送して実行します。/

ンド群を登録します。

まずは、デバッグを行いやすいようにhelloアプリにデ$ emulator -kernel $MYDROID/prebuilt/android-arm/kernel/kernel-qemu -sysdir $MYDROID/out/target/
product/generic -data $MYDROID/out/target/product/
generic/userdata.img &になっており、remoutコマンドを実行して書き込むこ

systemディレクトリ以下はデフォルトで書き込み禁止
とも一応可能ではありますが、ひと手間かかるので/
dataディレクトリを使っていきます。

しばらく待ってホームスクリーンが表示されたら、実際に実行してみましょう。
コマンド入力$ adb shell hello
Hello, World!

コマンド入力$ adb push $MYDROID/out/target/product/generic/system/bin/hello /data
56 KB/s（5288 bytes in 0.091s）$ adb shell /data/hello
Hello, World!

バッグ情報を付加 + 最適化をオフにしてコード順序
コマンド入力$ cd $MYDROID$ source build/envsetup.sh

コマンド群が登録されたので、指定ディレクトリ以下をビルドするmmmコマンドを用いて、helloモジューが変わらないように変更します。Android.mkの中央に、以下の行を追加してください。
追加行

LOCAL̲CFLAGS += -O0 -g

ル単体でビルドして実行してみましょう。
次に、Androidエミュレータ内でgdbserverを立ちあげてデバッグできるように準備を行います。helloア
プリからの出力をすぐに確認できると便利なので、新し
くシェルを立ちあげて下記コマンドを入力してください。

16

組込みプレス Vol.16

組込みプレス Vol.16

17

特集 1

Android による組込み開発

コマンド入力$ adb shell gdbserver :5039 /data/hello
Process /data/hello created; pid = 732
Listening on port 5039

その後、前のシェルに戻って下記コマンドを入力してデバッグを開始します。
コマンド入力$ export PATH= $PATH: $MYDROID/prebuilt/linux-x86/
toolchain/arm-eabi-4.3.1/bin$ gdbclient hello :5039 /data/hello第3章

上記の手順でgdbデバッグを行った際には、いくつか警告が表示されます。これは、gdbがデバッグ用に存在すると仮定している関数がAndroidにはなかった
り、Androidのネイティブコードがprelinkされている
ため表示されます。しかし実用上大きな問題はないた

統合開発環境で時間短縮

g d b s e r v e r を用いたリモートデバッグですが 、きました。ですが、開発をさらに効率化させるために、

gdbclientコマンドを実行してgdbのプロンプトが表示

統合開発環境でコードの編集＋デバッグを行えるようされたあとは、通常のgdbコマンドでデバッグできるよにしたいところです。

示してみましょう。
コマンド入力（gdb）b main
Breakpoint 1 at 0x8370: ﬁle hello/Main.c, line 5.
（gdb）c...
Breakpoint 1, main（argc=1, argv=0xbef52d94）at hello/
Main.c:5
5
printf（"Hello, World!\n"）;Current language: auto; currently c（gdb）p argc
$1 = 1（gdb）p argv[0]$2 = 0xbef52e5e "/data/hello"

実行を再開するともうひとつのシェルに文字列が表#!/bin/sh
cd ..
source build/envsetup.sh
mmm hello

め無視してもかまいません。

ここまでは、エディタ＋gdbを用いて開発を行ってうになります。main 文で止めてargc、argvの値を表$MYDROID/hello/build.shの内容

メニューからプロジェクトプロパティウィンドウを表示します。[C/C++ Build]ページを開いて、Builder
Settingsタブを図2のように、Behaviourタブを図3のように設定します。
それでは、自動ビルドが行われるかどうか、Main.cを以下のように変更して保存してください。

作成後、このファイルに実行権限をつけて実行してみましょう。
コマンド入力$ cd $MYDROID/hello$ chmod u+x build.sh$ ./build.sh

無事に実行できたら、プロジェクトの自動ビルド設

そこで、Eclipse 3.5のC/C++ 開発環境のCDTを定を行います。Project Explorerビューのhelloプロ

セットアップします。Eclipse 3.4＋Device Software

ジェクト上で右クリックメニューを開き、Properties

Development PlatformプロジェクトのDevice

図1 プロジェクトの作成

Debuggingプラグインでも一部可能ではありますが、Androidネイティブコードデバッグ手法$MYDROID/hello/Main.cの内容#include <stdio.h>
int main（int argc, char *argv[]）{
printf（"Hello, World!\n"）;error;
return 0}

図3

Behaviourタブの設定

バグの修正や新機能によりデバッグしやすくなっている
のでEclipse 3.5の利用を強くお勧めします。
まずは、先日リリースされたばかりのEclipse 3.5のEclipse IDE for C/C++ Developersパッケージをダウンロードして適当な場所に解凍します。
ダウンロードURL

http://www.eclipse.org/downloads/download.php?ﬁle=/technology/epp/downloads/release/galileo/R/eclipse-cppgalileo-linux-gtk.tar.gz

示されます。

図4 ビルド結果
図2

Builder Settingsタブの設定[File - New - C Project]メニューから、新規にC
コマンド入力プロジェクトを作成します。図 1のように入力を行い、（gdb）c[Next]ボタンで次のページに進み、[Finish]ボタンを押してプロジェクトを作成します。

デバッグが終わったのでgdbを終了します。
コマンド入力プロジェクトが作成できたら、下記ファイルをプロ
ジェクトルートに作成します。

（gdb）q18

組込みプレス Vol.16

組込みプレス Vol.16

19

特集 1

Android による組込み開発

第3章

Androidネイティブコードデバッグ手法

図 4のように、Consoleビューにビルド結果メッ

自動ビルドができるようになったので、次はinclude

を押して、図6のようにビルド変数を追加します。ビル

これで、コード編集中にコードアシストを使えたり、セージが表示されて、エディタ上にエラーマーカー＋

文／関数などの入力時にコードアシストが働くようにしド変数のValue 値には$MYDROIDディレクトリの絶ソースコード中の関数をたどっていくことができるよう

Problemビュー上にエラーが表示されたら成功です。

たり、F3キーを押すことにより関数の実装コードを参対パスを指定してください。

になりました。

成功したら、ソースコードを元に戻して保存します。

照できるように設定しましょう。$MYDROIDディレクト

次に[ W i n d o w - P r e f e r e n c e s ]メニューから

Eclipseから、実行／デバッグもできるようにしてみ

Builder Settingsタブで、保存時のビルド／自動ビ

リは開発者ごとに違うため、Eclipseのビルド変数／

P r e f e r e n c e sウィンドウを開いて、[ G e n e r a l -ましょう。gdbserverを用いたリモートデバッグとなる

ルド／クリーン時それぞれ別のコマンドラインオプショ

パス変数を用いて、プロジェクトとは別に設定する形にWorkspace - Linked Resources]ページを開いてため、残念ながら実行とデバッグは別々に設定する必ンが渡されるように設定しました。それぞれ別々の処します。こうすることにより、プロジェクトファイル内にください。[New...]ボタンを押して、図 7のようにパ要があります。

理を行うようにbuild.shを以下のように書き直します。

は$MYDROIDの絶対パスが含まれないようになり、ス変数を追加します。パス変数のLocation 値には$MYDROID/hello/build.shの内容#!/bin/shcase $1 in
auto | all ）echo "building..."cd ..
source build/envsetup.sh
mmm hello;;clean ）
echo "cleaning...";;esac

プロジェクトのファイル群をソースコード管理システム$MYDROIDディレクトリの絶対パスを指定してくだに入れたとしても、チェックアウト時にプロジェクト設定

さい。

を修正する手間を省けるようになります。

その後、プロジェクトプロパティウィンドウを開いて、[ W i n d o w - P r e f e r e n c e s ] メニュー から[C/C++ General - Paths and Symbols]ページ

Preferencesウィンドウを開いて、[C/C++ - Buildの[Includes - Languages - GNU C] 項目を図8のVariables]ページを開いてください。[Add...]ボタン

ように設定してください。[Includes - Languages -図6 ビルド変数の追加

Assembly] 項目と[Includes - Languages - GNU
C++]項目の内容は空にします。
最後に[File - New - Folder]メニューから、図9のまずは実行設定からです。新規に下記のファイルを追加します。
$MYDROID/hello/launch.shの内容#!/bin/sh
cd ..
adb push out/target/product/generic/system/bin/hello /data >&/dev/nulladb shell /data/hello " $@"作成後、このファイルに実行権限をつけて実行
してみましょう。

ように入力してリンクフォルダを作成します。
コマンド入力図8

では 、実 際 にクリーンを 行って 試してみます。

Includes項目の設定[Project - Build Automatically]メニューのチェッ$ cd $MYDROID/hello$ chmod u+x launch.sh$ ./launch.sh

クを外して[Build - Clean...]メニューを選択し、次のウィンドウで図5のように入力してクリーンを行います。

無事に実行できたら、このシェルスクリプトを簡単に実行できるように登録します。[Run ‒ External

図5 クリーン処理

Tools ‒ External Tools Configurations…]メ

図7 パス変数の追加

ニューを選択して、図 10のように実行設定を行います。
図9 リンクフォルダの作成

図10

実行設定

Consoleビューに"cleaning..."と表示されたら成功です。保存時にビルドが行われる方が便利なので、[Project - Build Automatically]メニューのチェックをつけて元に戻します。

20

組込みプレス Vol.16

組込みプレス Vol.16

21

特集 1

Android による組込み開発

通常の実行設定（[Run ‒ Run Conﬁgurations…]
メニュー）ではなく、外部ツールの実行設定にしていることに注意してください。CDTの通常の実行設定では、生成したバイナリでなければ実行することができないため、外部ツールとしてシェルスクリプトを登録しています。
その後、[ B u i l d ]タブに移って[ B u i l d b e f o r elaunch]チェックボックスのチェックを外します。
設定が完了したら、[Run]ボタンを押して試してみてください。
無事に実行できることを確認できたら、外部ツー

第3章

コマンド入力$ cd $MYDROID/hello$ chmod u+x prepare.sh$ ./prepare.sh

gdbserver側の実行設定は完了です。
g d b 側 の実 行 設 定は、[ R u n

実際に、[Debug hello]デバッグ設定を使ってデ‒Run

バッグ起動してみてください（[Run-Run]メニューで

Conﬁgurations…]メニューから、図13‒ 図16のようはなく[Run-Debug]メニューから起動）。main 関に設定して追加します。

数のところで止まってデバッグできるようになったは次に、このシェルスクリプトを [Run ‒ External

gdbserver 側／gdb 側両方の実行設定が整った

Tools ‒ External Tools Conﬁgurations…]メニュー

ので、図 17のようにワンクリックで起動できるようにから、図12のように外部ツールに追加します。

Launch Groupに登録します。
「GDB hello 」を追加

その後、[ B u i l d ]タブに移って[ B u i l d b e f o r e

ずです。

おわりに

する際に、Launch Modeをdebugに設定することを

launch]チェックボックスのチェックを外します。これで忘れないでください。

図12

図15

外部ツールに追加

Androidネイティブコードデバッグ手法

gdb側の設定（3）

非常に駆け足ではありましたが、C/C++の開発環境を整備する方法を解説しました。Androidのソフト

ルではなく、通 常 の実 行メニューに表 示されるよ

ウェアスタックには共有ライブラリが多く含まれていまうに設定します。[Run ‒ Run Configurations

すが、静的ライブラリとして別途ビルドし、テスト用コ…]メニューを選択して、Launch Groupツリーに

マンドラインアプリを書いて静的リンクする形にすれば、

図 11のように通常の実行設定として追加してくださ

どのようなコンポーネントであろうと効率的に開発を行い。

えるようになります。本章の手順をベースに、より良い

図11

開発環境を探ってみてください。

実行メニューにも表示させる

図13

gdb側の設定（1）図16gdb側の設定（4）column■ Android SDKに含まれているツール群

And roid の開発者ページからダウンロードできる

SDKには、Androidアプリケーションの開発に役に立つツールがいくつか含まれています。以下に、それらをリストします。各ールの詳細は、http://developer.
android.com/index.htmlを参照してください。

●Android Development Tools Plugin（Eclipse用）●Android Emulator

続けて、デバッグ設定も追加しましょう。新規に下●Android Virtual Device（AVD）

記のファイルを追加します。
$MYDROID/hello/prepare.shの内容#!/bin/sh
cd ..
adb push out/target/product/generic/system/
bin/hello /data >&/dev/nulladb forward tcp:5039 tcp:5039
adb shell gdbserver :5039 /data/hello " $@"作成後、このファイルに実行権限をつけます。

22

組込みプレス Vol.16●Hierarchy Viewer

図14gdb側の設定（2）

図17

Launch Groupへの登録●Draw 9-patch●Dalvik Debug Monitor Service（ddms）●Android Debug Bridge（adb）●Android Asset Packaging Tool（aapt）●Android Interface Description Language（aidl）●sqlite3●Traceview●mksdcard●dx●UI/Application Exerciser Monkey●android

組込みプレス Vol.16

23

特集 1

Android による組込み開発

第

第4章

4章

株式会社イーフロー
事業統括本部 海外開発部

ホームディレクトリ）に展開したものとして説明します。

緒方 聡

Ogata Satoshi

Android NDKによるJNI開発手法

ダウンロードAndroid NDKは以下のURLからダウンロードがインストールはNDKホームディレクトリでターミナルから以下のコマンドを入力します。
bash ./build/host-setup.sh

docs/INSTALL.TXTではbashは必要ないように可能です。
h t t p : / / d e v e l o p e r. a n d r o i d . c o m / s d k /記載されていますが、使用するシェルはbashを期待し

ndk/1.5̲r1/index.htmlています。最近のUbuntuでは/bin/shはbashではな

現在はAndroid 1.5向けのRelease 1がリリースされています。Android NDKはAndroid SDKと同じく

くdashにリンクされているので、明示的にbashを指定してシェルスクリプトを実行します。

Windows、Mac OS X（Intel）、Linux 32/64ビット

host-setup.shを実行すると、out/host/config.

（x86 ）のプラットフォームをサポートしています。それ

m k が 作 成されます。筆 者 の 環 境 で 作 成され た

ぞれの好みの環境のAndroid NDKをダウンロードし

conﬁg.mkは以下のとおりです。

てください。なお、Windowsの場合、別途 Cygwin
2 009 年 6 月26日 に、Android 1.5 Native

る最大のメリットは「実行処理の向上」と「既存のライ環境が必要になります。今回の例ではUbuntu 8.04

Development Kit Release 1（以下、Android

ブラリの有効活用」です。第2章の「Android 高速化

LTS上に環境を構築することにします。

NDK ）がリリースされました。ここではAndroid NDK

テクニック」で紹介されている高速化テクニックの最後を使用してJNI開発を行う手法について解説します。

の手段としてJavaコードをネイティブコードに置き換

事前準備

えるのは、実行処理の向上という側面では有効です。
ただし、ネイティブコードにしてしまうと特定のプラッ

HOST̲OS:= linux
HOST̲ARCH:= x86
HOST̲TAG:= linux-x86
HOST̲CC:= gccHOST̲CFLAGS :=HOST̲CXX:= g++
HOST̲CXXFLAGS :=HOST̲LD:= gccHOST̲LDFLAGS :=HOST̲AR:= ar
HOST̲ARFLAGS :=Android NDKとはトフォームに依存してしまうため、たとえばARM 向け

Android NDKを使用するだけなら、初期状態に作成したネイティブコードはx86では動作しないののUbuntuに必要なコマンドはすべて入っています。

作成された直後の状態では、コンパイルオプション

Android NDKはAndroidアプリ開発者向けのC

で、結果として作成したアプリはARM 専用ということ

makeのバージョンは3.81を期待しているので、ターなどが空です。ここで設定するとすべてのプロジェクトになってしまいます。

ミナルから以下のコマンドでバージョンをチェックしてのデフォルトになります。コンパイルオプションはプロ

みてください。

ジェクトごとに個別に指定することも可能で、その方法

およびC++のビルド環境です。Androidはもともと
JNIをサポートしていますが、Android NDKリリース
以前は、共有ライブラリを作成する方法が明確ではあメリットりませんでした。今後はAndroid NDKを使用するこ

実行速度の向上とで、以下のメリットが享受できます。

既存のライブラリの活用

デメリット
プラットフォームに依存・ライブラリの作成が確実／簡単になるは後述します。

make -v

GNU Make 3.81と出力されれば問題ありません。
ソースリポジトリなどを変更していなければ基本的に問サンプルのビルド・作成したライブラリの上位互換が保てる

メリットとデメリットを比較し、JNIを使うか使わ・AndroidのC/C++ APIが使用できるないかをよく考えてください。もしJ N Iを使うなら、Android NDKにはあらかじめふたつのサンプルがAndroid NDKを使用することで開発が圧倒的に容易付属しています。このうちのひとつ「hello-jni 」をビル

JNIを用いるメリット、デメリット
AndroidでJNIを利用した共有ライブラリを使用すになります。

題ないはずです。

インストール

組込みプレス Vol.16

ドしてみましょう。ビルドの方法はNDKホームディレク
トリでターミナルから以下のように入力します。

ダウンロードしたアーカイブを適当なディレクトリ
に展開します。ここではユーザーホームディレクトリ/
home/ogata/android-ndk-1.5̲r1（以下、NDK

24

Android NDKによるJNI開発手法

make APP=hello-jni

APPには、ビルドしたいアプリのプロジェクト名を指組込みプレス Vol.16

25

特集 1

Android による組込み開発

定します。プロジェクトはapps配下にプロジェクト名でディレクトリが存在していなければなりません。現在のリリースでは、以下の引数がサポートされています。
APP=<name><name>にプロジェクト名を指定（必須）V=1ビルド時に詳細な出力を行う-B

必ずリビルドを行う

ビルドが正常に行えたら、プロジェクトディレクトリ
のlibsフォルダに作成した共有ライブラリがコピーされ第4章

package com.example.android.ndk.hello;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class HelloNDK extends Activity {static {System.loadLibrary（"HelloNDK"）;}
private native String hello（）;@Override
public void onCreate（Bundle savedInstanceState）{
super.onCreate（savedInstanceState）;
TextView textView = new TextView（this）;
textView.setText（hello（））;
setContentView（textView）;}}

ます。あとはADTでパッケージングすれば共有ライブ
ラリは.apkに含まれ配布可能になります。

javah com.example.android.ndk.hello.HelloNDKん。

らを含め、以下が用意されています。
プロジェクトパスを指定（必須）ndk̲hello̲HelloNDK.hが作成されたと思います。

APP̲MODULES

モジュール名を指定（必須）

このヘッダファイルをベースにして、HelloNDK.cとい

APP̲OPTIM

debugかreleaseを指定（release
がデフォルト）APP̲CFLAGS

Cソースコンパイルフラグを指定

APP̲CXXFLAGSC++ソースコンパイルフラグを指定

APP̲CPPFLAGS

CとC++で共通のコンパイルフラグ
を指定

うソースコードを作成します。
#include <jni.h>
JNIEXPORT jstring JNICALL
Java̲com̲example̲android̲ndk̲hello̲HelloNDK̲hello（JNIEnv *env, jobject thiz）{
return（* env）->NewStringUTF（env, " こんにちは ,NDK"）;}

これらは、このアプリ共通の定義です。ひとつのアプ
作成したソースコードはどこにあっても問題ないのでリで複数のライブラリを使用する場合などで、ライブラ

すが、管理がしやすいようにNDKホームディレクトリ

リごとにコンパイルフラグを変更したい場合は後述の

ソースコードで特筆すべき点は2 個所です。ひとのsources/HelloNDK/HelloNDK.cに保存するこ

Android.mkに設定します。

サンプルがビルドできて、Android NDKのインス

つはnativeメソッドの宣言、もうひとつはSystem.

とにします。この場所に保存する理由は後述します。

トールが正常に行えていることが確認できたら、さっそ

loadLibrary（String ）メソッドによるライブラリのソースコードはUTF-8で保存することを忘れないでく

く自分でプロジェクトを作成してみましょう。今回作るロードです。Android 1.5からは、JNIから呼び出ださい。

アプリはネイティブから文字列を返して、それをJava

す共有ライブラリは . a p k の作成時に自動的にパッ側で受け取って画面に表示する、という簡単なものでケージングされ、インストール時に自動的に/data/

す。まずはEclipseで以下のようなプロジェクトを作成

data/<package>/lib に展開され、アプリ起動時に自します。
表1 コマンド一覧
Project name

HelloNDKBuild Target

Android 1.5

Application name

Hello NDK

Package namecom.example.android.ndk.hello

Create Activity

HelloNDK

以下は全ソースコードです。

res/ 配下のXMLなどはとくに変更する必要はありませ

動的に上記パスでライブラリの動的ロードが行えるよて、そこに保存しました。同じ場所に以下の内容でうになるため、Android 1.1以前のように、/system/

ここから先 は A n d r o i d N D K の 設 定 になりま

Android.mkを作成します。

libに配置したり、.apkから共有ライブラリを書き出しす。Android NDKでは新規プロジェクトのために読み込むような自前のローダー機能を準備したりしなくApplication.mkとAndroid.mkというふたつの設定てもよくなりました。また、自動的に展開された共有ラ

ファイルを作成する必要があります。

イブラリはアプリのアンインストール時に自動的に削除されます。

ネイティブコードの作成
リで、以下のコマンドをターミナルから実行します。

組込みプレス Vol.16

Android.mkの設定

Application.mkの設定

ひとつはNDKホームディレクトリ配下に以下の内容

ソースファイルは、N D Kホームディレクトリ配下にsources/HelloNDKというディレクトリを作成しLOCAL̲PATH := $（call my-dir）include $（CLEAR̲VARS）
LOCAL̲MODULE := HelloNDKLOCAL̲SRC̲FILES := HelloNDK.c
include $（BUILD̲SHARED̲LIBRARY）

でapps/HelloNDK/Application.mkというファイルを作成します。

LOCAL̲PATHは必ず最初に定義しなければなりません。ここではAndroid.mkのあるディレクトリを

APP̲PROJECT̲PATH := /home/ogata/workspace/HelloNDK
APP̲MODULES:= HelloNDK

my-dirというマクロを使用してLOCAL̲PATHに設定しています。次の“include $（CLEAR̲VARS ）”は、
LOCAL̲PATHを除くLOCAL̲xxxの定義をクリー作成した新規 Androidプロジェクトのbinディレクト

26

りません。Application.mkに使用可能な定義はこれ

APP̲PROJECT̲PATH

カレントディレクトリにcom̲example̲android̲

このソースコード以外、AndroidManifest.xmlや新規プロジェクトの作成

Android NDKによるJNI開発手法

APP̲PROJECT̲PATHは相対パスでも記述できま

ンアップします。複数のライブラリを使用する場合などす。今回の例は絶対パスですが、相対パスの記述方に、先に読み込んだAndroid.mkのLOCAL̲xxxの法も後述します。上記ふたつは必ず定義しなければな

値が不本意に使用されてしまう、という障害を防ぐた

組込みプレス Vol.16

27

特集 1

Android による組込み開発

めにも必ず定義しておきましょう。

第4章

・TARGET̲ARCH

include $（call all-subdir-makeﬁles）

L OCA L̲MOD ULEはモジュール名を指定しまターゲットCPUのアーキテクチャが定義されています。この名前はユニークでなければならず、スペースす。ARM9もARM11も“arm”であることに注意が必を含んではいけません。ビルドシステムはここで与え要です。

探さないことに注意してください。

られた名前にプレフィックスとサフィックスを自動的に・TARGET̲PLATFORM

・this-makeﬁle

付与し、今回の場合ではlibHelloNDK.soという共ターゲットプラットフォームが定義されています。現有ライブラリを生成します（もしここでlibHelloNDK

時点では“android-1.5”だけがサポートされています。

という名 前を指 定した場 合 、生 成される共 有ライ

・TARGET̲ARCH̲ABI

ブラリはliblibHelloNDK.soではなく、例外的にlibHelloNDK.soとなることに注意してください）。

Android.mkが構文解析されるターゲットのCPUとABIの名前の定義です。現在は“arm”だけがサ

LOCAL̲SRC̲FILESにはCまたはC++のソースリポートされています。これはARMv5TE 以上のsoft-

ストを指定します。ヘッダは含めません。C++ソース

ﬂoat 版浮動小数点をサポートしたCPUを意味します。

ファイルの拡張子は.cppがデフォルトです。“include

将来的には“arm”以外のABIもサポートされます。

$（BUILD̲SHARED̲LIBRARY ）”は共有ライブラ

・TARGET̲ABI

リを作成する際に指定します。
上記がAndroid.mkの最小セットで、これだけ定義すれば共有ライブラリのビルドは可能です。もっと詳しく知りたい方のために、上記を含めたAndroid.mk
で使用可能なすべての定義、マクロ、機能を以下で説明します。

●Android NDKが提供する定義

・CLEAR̲VARS“LOCAL̲”で始まる定義を未定義にします。新しいモジュールの記述前にインクルードすべきです。
・BUILD̲SHARED̲LIBRARY“LOCAL̲”で始まる定義をすべて記述したあとで“$（TA R G E T ̲ P L AT F O R M ）-$（TA R G E T ̲

この定義はサブディレクトリのサブディレクトリまでは

C++のソースファイルの拡張子を指定します。デ
フォルトの拡張子は.cppです。拡張子を.cxxに変更
したい場合は、以下のように指定します。
LOCAL̲CPP̲EXTENSION := .cxx

現在のMakeﬁleのパスを返します。
・parent-makeﬁle呼び出し元のMakeﬁleのパスを返します。
・grand-parent-makeﬁle呼び出し元の呼び出し元を返します。

●Android NDKが提供するモジュール記述変数

これらは “ i n c l u d e $（ C L E A R ̲ VA R S ）”と“include $（BUILD̲XXXXX ）”の間で定義すべき

ARCH̲ABI ）”という定義を持ちます。デフォルトはです。

“android-1.5-arm”です。

・LOCAL̲PATH
このAndroid.mkに記載されるすべてのパスのベー・LOCAL̲CFLAGS
Cソースファイルのコンパイルフラグを指定します。このフラグはC++ソースファイルのコンパイルには適用されません。
・LOCAL̲CXXFLAGSC++ソースファイルのコンパイルフラグを指定します。
このフラグは、Cソースファイルのコンパイルには適用されません。
・LOCAL̲CPPFLAGS
CソースファイルとC++ソースファイルの両方に対してコンパイルフラグを指定します。
・LOCAL̲STATIC̲LIBRARIES●Android NDKが提供するマクロスとなるパスを指定します。必ず先頭で定義しなければなりません。

でリンクしたいものをリストで指定します。この指定は、

・my-dir

・LOCAL̲MODULE

共有ライブラリを作成する場合でのみ指定可能です。

マクロは“$（call マクロ）”のように使用します。

NDKビルドシステムに、このAndroid.mkが置かれモジュール名を指定します。すべてのモジュールで

BUILD̲STATIC̲LIBRARYで指定したモジュール

・LOCAL̲SHARED̲LIBRARIES
このモジュールが実行時に参照する共有ライブラリているディレクトリのパスを返します。

ユニークな名前で、かつスペースを含まないようにし、

・all-subdir-makeﬁles

必ず定義しなければなりません。NDKビルドシステを指定します。

ムによって作成されるライブラリ名は、このモジュール

・LOCAL̲LDLIBS

このAndroid.mkのディレクトリのサブディレクトリ
にあるAndroid.mkを探します。たとえばディレクトリ

名にプレフィックスとサフィックスが付与されますが、ライブラリのビルド時に必要な追加のリンクフラグをとAndroid.mkが以下の構成になっていたとします。

モジュール間での参照の際には、プレフィックスとサ指定します。“-l<library>”でリンカに通知する方法とこの定義をインクルードします。少なくともLOCAL̲

sources/foo/Android.mk

フィックスを指定する必要がないことに注意してくださ同じです。

MODULEとLOCAL̲SRC̲FILESが事前に定義されsources/foo/lib1/Android.mk

い。

・LOCAL̲ALLOW̲UNDEFINED̲SYMBOLSていなければなりません。

sources/foo/lib2/Android.mk

・LOCAL̲SRC̲FILES・BUILD̲STATIC̲LIBRARY

デフォルトの動作として、未定義の何かを参照し

この際、sources/foo/Android.mkに以下の行がモジュールを構成するソースファイルのパスリストを指ている場合、共有ライブラリ作成時に“undefined

静的ライブラリを作成する際に指定します。静的ラ

含まれていると、sources/foo/lib1/Android.mkと定します。ソースファイルのパスはLOCAL̲PATHから

symbol”エラーが発生します。何らかの理由でエラー

イブラリはアプリのプロジェクトにコピーされませんが、

sources/foo/lib2/Android.mkも自動的にビルドにの相対パスで指定します。以下は複数指定の例です。

を発生させたくない場合は、この定義をtrueにします。

他の共有ライブラリから使用できるようになっています。

含まれます。

なお、作成される静的ライブラリのファイル名は“lib$

LOCAL̲SRC̲FILES := foo.c \toto/bar.c・LOCAL̲CPP̲EXTENSION

組込みプレス Vol.16

上記以外にAndroid.mkで独自定義を行いたい場
合、その定義名に“MY̲”というプレフィックスを用いる（LOCAL̲MODULE ）.a”となります。

28

Android NDKによるJNI開発手法

ことが推奨されています。以下のプレフィックスはNDK

組込みプレス Vol.16

29

特集 1

Android による組込み開発第5章

第ビルドシステムが予約しています。
・“LOCAL̲” で始まる定義●C++のサポート
極めて小さなC++のAPIがサポートされています。

・“PRIVATE̲”、“NDK̲”、“APP̲” で始まる定義

Android 1.5向けとして、現在は以下のヘッダだけが・小文字の定義

利用可能です。

5章<new><utility><stl̲pair.h>Android NDKを使用する際に知っておくべき情

また、これらは標 準として必 要なすべての定 義

報、CやC++のサポート範囲や制限事項、Androidを含んでいません。とくに、C++の例外とRTTIはNDKが提供する関数などをまとめます。

Android 1.5システムイメージで使用することができま●Cのサポート

山口 祐治

Yamaguchi Yuji

せん。
NDKビルドシステムはC++ライブラリを自動的にリ

はじめにTraceviewを用いた
プロファイリング

作成したプログラムの性能が悪い場合、ただやみく

TraceviewはJava言語のレベルでプロファイリング

<android/log.h>は、ネイティブコードからカーネもにプログラムを修正するのではなく、まずパフォーマを行うための方法です。本節ではその方法を順を追っていないので、自分で代替関数を用意するか、あるいルにログメッセージを送るために使用できる定義を含ンスのボトルネックになっている個所を見つけることがて説明します。参考までに、本節で説明した内容は以は別の方法を考えなければなりません。

んでいます。以下にそれらをリストします。

必要です。

下の環境で確認しています。

Cライブラリはlibcではなく、BionicというAndroid

独自のものなので、ANSI C 準拠ではありません。ビ
ルド時にANSI C 標準のヘッダファイルがなかったり、
ヘッダファイルはあるけれど定義されているはずの関数がなかったりした場合、それらはBionicには実装され

NDKビルドシステムはCライブラリを自動的にリンンクするので、“-lstdc++”をLOCAL̲LDLIBSに含める必要はありません。

●Android特有のログサポート

関数名

説明

̲̲android̲log̲write

文字列出力

LDLIBSに記述する必要はありません。NDKビルド

̲̲android̲log̲print

文字列出力（printf 相当）

システムはpthreadを標準でサポートするなので、

̲̲android̲log̲vprint

文字列出力（va̲list 版）“LOCAL̲LIBS := -lpthread”を記述する必要はあ̲̲android̲log̲assert

アサート

クするので、LOCAL̲LDLIBSに含める必要はありま
せん。<math.h>も利用可能で、“-lm”をLOCAL̲

ただしpthread̲cancelはサポートされていません。

JavaのLogクラスと同じく、プライオリティによる出またリアルタイム拡張も同様なので、“-lrt”も必要あり

力制御、タグの指定が行えます。これら関数の引数のません。

詳細は以下のヘッダファイルを参照してください。

将来的に変更される可能性があるため、これらヘッダファイルを直接インクルードすることは推奨されません。

組込みプレス Vol.16

つけるために効果的な以下の2つのプロファイリング手法を説明します。

・Android SDK
OS: Windows XP Profession SP3
SDK: Android 1.5 SDK, Release 2・Traceviewを用いたプロファイリング
Android SDKに同梱されるツールTraceviewを使数などを計測できます。

●プロファイリングのコードを追加

はじめに、プロファイリングを行いたい部分の開始と終了に一行ずつコードを書く必要があります。開始部
分ではDebug.startMethodTracingを、終了部分で・OProﬁleを用いたプロファイリング
Androidのkernelに手を加えて、Javaだけではな

ワイドキャラクタはサポートされていません。
ヘッダファイル<linux/*.h>および<asm/*.h>は本章では、Androidプログラムのボトルネックを見います。Javaのメソッドごとに実行時間や呼び出し回

りません。

30

株式会社イーフロー
事業統括本部 第１事業部

プロファイリング
手法<cstddef>

その他有用な情報

プロファイリング手法

build/platforms/android-1.5/common/include/

くネイティブのモジュールレベルでプロファイリングを行

android/log.h

います。Androidのシステム全体を開発する開発者向けの手法です。

はDebug.stopMethodTracingを呼び出すようにコー
ドを書きます。
Debug.startMethodTracing（"foo"）; // プロファイリング開始...
（プロファイリングルを行いたい処理）
Debug.stopMethodTracing（）; // プロファイリング終了...

組込みプレス Vol.16

31

特集 1

Android による組込み開発

プログラムを実行すると、プロファイリング結果ファイ
ルがSDカードに書き出されます。

第5章

す。上部はTimeline Panel 、下部はProﬁleから見た比率を表します。

Panelといいます。

・Calls+RecurCalls/Total

Timeline Panel（ 図1 ）は、実行しているJavaのメソッド呼び出し回数＋再帰メソッド呼び出し回数を●プロファイリング結果の取得

スレッドごとに時間軸の上で実行しているメソッドを図表します。

プロファイリング結果ファイルをPCにコピーします。

示するものです。この線上では、各々のメソッドは違う・Time/Call

この処理には、adbコマンドのpullアクションを使いま色で区別されます。このパネルの上でカーソルを当て

メソッド１回呼び出しあたりの実行時間をミリセカンド

す。

ると、カーソルを当てた位置で実行されているメソッドで表します。

adb pull /sdcard/foo.trace●プロファイリング結果の表示

P C にコピーしたプロファイリング結果ファイルをが上部に表示されます。
Proﬁle Panel（図2 ）は、Javaのメソッド単位で実行時間や呼び出し回数などの集計が見られる表です。
各項目の意味は以下の通りです。
・Inclusive、Incl %各メソッド行をクリックすると、メソッドの呼び出し関係が表示されます。Parentは呼び出し元を表し、Childrenは呼び出し先を表します。

OProﬁleを用いた
プロファイリングプロファイリング手法

取得します。
repo init -u git://android.git.kernel.org/platform/manifest.
git -b cupcake

また、local̲manifest.xmlは以下のように設定します。
<?xml version="1.0" encoding="UTF-8"?><manifest><remove-project name="kernel/common"/><project path="kernel" name="kernel/msm" revision="refs/heads/android-msm-2.6.27"/><project path="vendor/htc/dream" name="platform/
vendor/htc/dream" revision="capcake"/><project path="hardware/msm7k" name="platform/
hardware/msm7k" revision="capcake"/></manifest>

Traceviewツールで開いて分析します。先ほどコピー

メソッドの実行時間（そのメソッドから呼び出されたした結果ファイルを引数に指定してtraceviewコマンド

他のメソッドの呼び出し時間含む）、および全体からを起動します。

見た比率を表します。

OProfileはOSやCのライブラリなどのネイティブも・Exclusive、Excl %含めたプロファイリングを行うためのものです。本節で上記設定をしたのち、repo syncコマンドを使っメソッドの実行時間（そのメソッドから呼び出されたは、Google Android Dev Phone 1（以下ADP1 ）てソースをチェックアウトします。以後、チェックアウ

他のメソッドの呼び出し時を間含まない）、および全体向けにOProﬁleを実行した例を説明します。参考までトしたAndroidソースコードのトップディレクトリをに、本節で説明した内容は以下の環境で確認してい

MYDROID環境変数として参照します。

traceview foo.trace

Traceviewの画面は、上下２つのパネルからなりま
図1 Timeline Panelます。
・Android SDK
OS: Windows XP Profession SP3

下記コマンドを実行して$MYDROID/kernel/.

SDK: Android 1.5 SDK, Release 2

configにQualcomm MSMチップ用の設定をコピー

・Android ビルド環境
OS: Windows XP Profession SP3
VMware: VMware Server 2.0.0.2073
図2Proﬁle Panel■kernelのコンフィグレーション取得

します。
$ cd $MYDROID/kernel$ make ARCH=arm msm̲defconﬁgLinux: Ubuntu 9.04
Source: http://source.android.com（cupcake）●Androidファームウェアの更新

O P r o f i l eを有効にするためには、A n d r o i d のkernelをOProﬁle対応にする必要があります。

■ADP1用ソースセットアップ■kernelのコンフィグレーション編集
エディタで$MYDROID/kernel/.configを開いて以下のように追加／編集します。
CONFIG̲PROFILING=yCONFIG̲OPROFILE=yCONFIG̲OPROFILE̲ARMV6=y
CONFIG̲LOCALVERSION="-00392-g8312baf"# CONFIG̲LOCALVERSION̲AUTO is not set

http://source.android.com/documentation/building-for-dream に従ってADP1のソースをセッ
トアップします。ただし、ソースはcupcakeブランチで

32

組込みプレス Vol.16

組込みプレス Vol.16

33

特集 1

Android による組込み開発

最後の2行はADP1で無線 LANを有効にするためのワークアラウンドです。Androidソースツリー上に同梱されている無線 LANのモジュールwlan.koが想定しているカーネルバージョンに合わせています。

■kernelのビルド$ cd $MYDROID/kernel$ make ARCH=arm CROSS̲COMPILE=../prebuilt/linux-x86/
toolchain/arm-eabi-4.2.1/bin/arm-eabi-

第5章

アを書き換えます。
$ cd $MYDROID$ source build/envsetup.sh$ setpaths$ fastboot -w ﬂashall

この方法では、ユーザデータや設定も含めすべてのデータがクリアされることにご注意下さい。

●プロファイリング実行

OProfileによるプロファイルデータの収集は以下のmakeが正常に終了した場合、カーネルイメージが$MYDROID/kernel/arch/arm/boot/zImageに生成されます。

■Androidビルド 設定$MYDROID/build/buildspec.mk.defaultを$MYDROID/buildspec.mkにコピーし、以下を追流れに沿って行って下さい。
$ prebuilt/linux-x86/oproﬁle/bin/opreport --sessiondir=oproﬁle■OProﬁle初期化
まず、OProﬁleの初期化を行います。以下のコマン
ドを適宜使用して下さい。

加します。
TARGET̲PRODUCT:=htc̲dream
TARGET̲PREBUILT̲KERNEL=./kernel/arch/arm/boot/zImageBOARD̲WLAN̲TI̲STA̲DK̲ROOT=./system/wlan/ti/sta̲dk̲4̲0̲4̲32/
BOARD̲HAVE̲BLUETOOTH:=true

・プロファイラを初期化# opcontrol --setup

・プロファイラをリセット# opcontrol --reset■Androidのビルド$ cd $MYDROID$ make・プロファイラを設定# opcontrol --event=CPU̲CYCLES:150000

これはCPUサイクルが150000ごとに計測してカウン
makeが正常に終了した場合、$MYDROID/out/

トすることを表します。

target/product/dream ディレクトリにファームウェア
イメージが生成されます。

■ファームウェアの書き換え
ADP1の電源をオフにしたあと、PCとUSB 接続
し、Back Spaceキーを押しながら電源キーを押して
FASTBOOTモードで起動します。
起動したら、以下のコマンドを入力してファームウェ

34

組込みプレス Vol.16■OProﬁle開始／終了

・Oproﬁle開始# opcontrol --start・Oproﬁle終了●プロファイリング結果の閲覧■OProﬁle初期化

external/oproﬁle/opimport̲pullコマンドでデータを取得します。
$ cd $MYDROID$ source build/envsetup.sh$ setpaths$ external/oproﬁle/opimport̲pull oproﬁle

プロファイリング手法$ prebuilt/linux-x86/oproﬁle/bin/opreport --sessiondir=oproﬁle --image-path out/target/product/dream/symbols -l

出力結果は下記のようになります。
samples %app name
1276
10.6841 no-vmlinux
616
5.1578 libwebcore.so
552
4.6220 libdvm.so
410
3.4330 libwebcore.so
void*）…

symbol name/no-vmlinux
jscyyparse（void*）
dalvik̲inst
JSC::Lexer::lex（void*,

上記最後のoprofileオプションはoprofileフォル
ダに出力することを意味しています。変更する場合は、次節のsession-dir指定も変更してください。
kernel（no-vmlinux ）については、本章を書いた■opreportコマンドで分析
モジュールごとの実行時間を見るためには、以下の段階では関数単位に分割することができず、すべての関数がひとつのモジュールとして扱われています。

コマンドを入力して分析します。
$ prebuilt/linux-x86/oproﬁle/bin/opreport --sessiondir=oproﬁle

出力結果は下記のようになります。
samples|%|-----------------3768 31.5499 libwebcore.so
2278 19.0739 libdvm.so
1781 14.9125 libc.so
1528 12.7941 libsgl.so
1276 10.6841 no-vmlinux
254 2.1268 libcorecg.so…

おわりにAndroidのプロファイリング手法について説明しました。組込み機器のハードウェアの性能は日進月歩で向上しています。今回プロファイリングで実際に使用したADP1のCPUクロックは500MHzであり、これはひと昔前のPCに相当するレベルの性能です。しかし、組込み分野においてもソフトウェアは複雑化、巨大化し続ける傾向にあります。
ハードウェア性能の進歩とともに、ソフトウェアへの

これはブラウザで w w w. g o o g l e . c o m にアクセ

要求も高まり、扱うデータも巨大になってきています。

スして表 示 完了するまでをプロファイリングしたも結局のところ、パフォーマンスの問題はこれからも組のです。Dalvik VM（libdvm.so ）よりもWebkit

込み開発の重要なファクターであり続けるでしょう。

（libwebcore.so ）に時間がかかっていることがわかります。また、kernel（no-vmlinux ）の実行比率も今回の内容が、Android 上でのプログラム開発の際の一助になれば幸いです。

かなり高いことがわかります。
また、関数ごとの実行時間を見るためには以下のコマンドを実行します。

# opcontrol --stop

組込みプレス Vol.16

35

特集 1

Android による組込み開発

第

第6章

6章

Androidポーティング事例

株式会社 アックス

渡邊 昌之

Wtanabe Masayuki

Androidポーティング事例

zlib1g-dev

されています。
しかし、この環境ではカーネルが目的としているデバ

・repoのインストール
Androidのプロジェクトは、複数のGitプロジェクト
をrepoというツールでまとめて管理しています。ホーム

イスに対応していませんので、このままでは目的とするデバイスで動作しません。次項から最小限のデバイスについて対応を行います。

ディレクトリ下にbinディレクトリがなければbinを作成
し、PATHを通して以下のコマンドでrepo自体をダウンロードします。
$ curl http://android.git.kernel.org/repo >~/bin/repo

最小限のドライバ
Androidで要求されるデバイスの要件は、以下の通りです。

~/bin/repoに実行属性をつけます。

・128MB以上のRAM、256MB 以上のFlash・ファイルストレージ（SDカードなど）

・ソースのダウンロード
AndroidはLinuxをベースにしているので、Linux

手順の概要は以下の通りです。

が動作するデバイスであれば、さまざまな機器にポーティングすることができます。
ここで は 、特 定 のデバ イス（ 組 込 み 機 器 ）に・Ubuntuのインストール

まず、適当なディレクトリを作成し、$ mkdir mydroid$ cd mydroid

http://www.ubuntu.com/getubuntu/

Androidをポーティングする際に必要な最小限の作業

downloadと、具体的な事例として無線通信デバイス（Willcom

からUbuntu 8.04 LTS Desktopをダウンロードしイ

W-SIM ）を使用した通信を行うためのRIL（Radio

ンストールします。

定するので、マルチメディアデバイスや特定の周辺機器への対応は含んでいません。

Androidポーティングに必要なこと・最小限のキー5 個（a p p l i c a t i o n、p o w e r、
camera、volume+、volume- ）以下のコマンドで、repoの環境を構築します。
$ repo init -u git://android.git.kernel.org/platform/manifest.
git

・無線通信デバイス・デバッグ用のシリアルデバイス
これらの周辺デバイスは各機器によって異なるので、機器ごとのデバイスドライバを用意する必要があります。

・ツール類のインストール
以下が必要となるので、これらをapt-getでインス
トールします。
git-core

repoを使ってソースツリーを取得します。
$repo sync

このコマンドは、ソースツリーの更新に使用するの最近のLinuxカーネルでは一般的な周辺デバイスのドライバはカーネルソースの中に組み込まれているので、コンフィグレーションするだけで使えることがほとんどです。

gnupg,sun-java5-jdk

で、適宜必要に応じて実行することで手元のソースを以上から、最小限必要なデバイスドライバは、

ﬂex

最新に保つことができます。

・キーボード（キーマップ）

bison

途中、ネットワークのエラーやGitサーバのエラー

gperfで中断することがあるので、正しく終了していないよう・パワーマネージメントドライバ

は、SDKなどのアプリケーション開発環境はなくてもlibsdl-dev

だったら、repo syncを再実行して最後まで実行されとなります。

かまいません。開発には、LinuxやMacOS Xなどのlibesd0-dev

るのを確認します。

Unix系のOSが必要です。

libwxgtk2.6-dev

あとは、このディレクトリで makeを実行すれば、

build-essential

Android 一式がビルドされますが、LinuxカーネルやUbuntu（32ビット）ですので、新しい環境が用意でき

zip

コンパイラも含んでいるので、初回のビルドは環境にもなければなりません。Linuxの/dev/event0デバイス

る場合は、はじめからUbuntuを入れると細かな問題

curlよりますが、数時間かかることもあります。outというからの入力を使用してこれらのキーを認識します。そのにつまずかなくて済みます。

libncurses5-dev

ディレクトリが作成され、Androidのイメージが作成ため、デバイスについている特殊キーの押し下げ、解まず、Androidそのものをポーティングするために検証されているLinuxディストリビューションは、

36

チパネルつきが理想）

・ネットワークデバイス

Interface Layer ）の扱いについて説明します。
CPUは、ARM系として必要最小限の動作のみに限・QVGA、16ビットカラー以上のディスプレイ（タッ組込みプレス Vol.16

・ディスプレイドライバ●キーボードフルキーボードとは別に最小限5個のキーを用意し組込みプレス Vol.16

37

特集 1

Android による組込み開発

放などのイベントをこのデバイス経由でアプリケーショ
ンに送らなければなりません。
それ以外に、フルキーボードもサポートしますが、こちらは接続すべきキーボードのレイアウトに合わせたレ

うにしておくことが必要です。

●無線通信デバイス

Androidポーティング事例

ます。RILではこのような階層構造で、各層での処理

ティングは簡単ではありません。現在のソースツリーにを抽象化しています。

はcdma-importというブランチができていて、そちら

当然その目的は、RILで物理層の違いを吸収し、アの中には、GSMと並んでCDMAへの対応が始まって

ここでは、Wi-Fiなどの無線 LANデバイスではな

プリケーションからはデバイスの差を気にしないで操

イアウトデータを作成して、通常のキーボードデバイス

く、GSM/CDMA/W-CDMA/W-SIMなどの無線通作できることだったはずです。しかし、実際には、RIL

すでにNTTドコモが HTCの端末が発売されたのとして認識されるようにしておけば問題ありません。

信（携帯電話）デバイスのことを指しています。元々の構造がそのまま物理層（この場合は無線通信デバ

で、正式にCDMAに対応したソースも公開されるのでAndroidは無線端末（携帯電話など）のOSとして開イス）の構造に依存してしまい、アプリケーション層はないでしょうか。

発されているため、これらのデバイスを使用するためのにまでその影響が及んでいます。そのため、最初にまた、それと同時にアプリケーションやライブラリレ

仕組みやアプリケーションが組み込まれています。

Androidが搭載された端末はGSM 方式だったので、ベルで無線通信デバイスの方式に依存した部分が解RILの構造（コマンド）自体がGSMの構造に強く依存

消されると、他の通信デバイスへのポーティングも楽にしています。

なると思います。

●ディスプレイ/dev/fb0か/dev/graphics/fb0というデバイスが、フレームバッファデバイスと想定されます。
そのためこのデバイスを正しく動作させてやる必要があります。
Androidでは、以下のようなフレームバッファを想定しています。

無線通信デバイスは、CPUとシリアルで通信し、コ
マンドのやりとりを行う仕様になっていることが多いので、ここではシリアルデバイスとして接続できるものとします（昨今はUSB 経由での接続も増えてきたので、その場合はUSBドライバも必要になります）。

・RGB 5,6,5ビットの16ビットカラー

ここまでの説明では、カーネルはAndroidのツリー

・連続したメモリで直接書き込みできるに含まれているものを使うことを前提に話を進めてきまAndroidではダブルバッファで画面を描画するのしたが、実際には、カーネルは2.6.25 以上ならそれで、グラフィックメモリは1画面分のメモリの倍以上がほど問題なく動作します。したがって、カーネルとユー必要です。これらの条件がクリアできていれば、ディザランドは評価ボードメーカの用意したものをそのまま

スプレイドライバはいくつかのioctlを実装するだけで、持ってきて、最小限のデバイスドライバだけを組み込

比較的簡単に対応することができます。

む方が簡単です。
以上のドライバの中で、キーボードやフレームバッ●パワーマネージメント

ファは一般によく使用され、特別なことは何もありませ

電源を制御するために、オリジナルのパワーマネーて説明します。

Android 上のアプリケーションの動作に合わせてジメントドライバが用意されています。このドライバが「試しに動かしてみるだけ」という目的なら、ioctlやread/writeがエラーを返さない程度に動作していれ

無線デバイスを制御するためにRadio Interface

ば、この操作で実際の電源操作ができなくても問題は

Layer（RIL ）という仕組みが使われています。RILはありません。

名前の通り、無線通信デバイスの制御を行うためのイ

要があります。

●シリアルドライバ

このままでは、ほかの無線通信デバイスへのポー
図1

RIL構造

アプリケーション

アプリケーションフレームワーク

電話

SMS

Phone
/java/android/telephony
RIL/
java/android/telephony/xxx

ライブラリ

rild(Radio Daemon)/command/rild
vendor rilsystem/libs/libril-vendor.so

カーネル

Kernel IP Stack

制御コマンドPacket DriverPPP

ンタフェース層です。
上位のアプリケーションからは、アプリケーションフ

これは、Androidを動作させるために必要なわけでレームワーク経由で、rildを使って回線制御を行いまはありませんが、デバッグの際には必ず必要になります。rildは、ベンダごとに異なるvendor-rilという共有す。そのため、最小限のシリアルドライバは動作するよライブラリを使って、無線通信デバイスの制御を行い組込みプレス Vol.16

います。

ん。ここでは無線通信デバイスを使用する事例につい

RIL（Radio Interface
Layer）の構造

ポーティングすべき機器で動作するように調整する必

38

第6章

通信デバイス

通信デバイス(GSM/CDMA/W-SIM)

組込みプレス Vol.16

39

特集 1

Android による組込み開発

rildとvendor-RIL
関係

第6章

Androidポーティング事例までが追加されています。

・RIL̲UNSOL̲RESPONSE̲CALL̲STATE̲

結果を返すべきなのですが、テストなら必ず「正常」とまた、アプリケーションから要求していないレスポンス

CHANGED

返してかまいません。問答無用でRIL̲SIM̲READY

・RIL̲UNSOL̲RESPONSE̲NEW̲SMSを返してしまいましょう。

（UnsolicitedResponse ）も存在します。
当然ですが、電話なので電話がかかってくることもになります。
・RIL̲REQUEST̲GET̲CURRENT̲CALLS

rildはデーモンプロセスとして動作し、アプリケーあります。それはアプリケーション側から要求したこと

もちろん、実際の製品化にはすべてのコマンドに正しションからの制御を受けて必要な処理を行います。具ではなく、通信デバイス側から突然レスポンスが発生く対応することが必要となりますが、その部分は前述

これは現在接続している回線の情報を返すコールで体的には、rildが起動時に作成したUnix Domain

するので、それを受け止める仕組みが必要です。

のコマンドへの対応と、基本的には同様な作業の繰りす。GSMでは、複数の回線を接続したまま切り替える

Socketをアプリケーションで開き、プロセス間通信でそれにもrequest codeが割り当てられていて、返しなので、ここでは割愛します。

ということができるので、こういうコールが用意されてコマンドを送信して処理を行います。
rildの仕事は、アプリケーション側からの要求をvendor-ril.so へ渡すことです。rild 自体が何かの処理をするわけではなく、ソケットから受け取ったコ
マンドを解釈し、適当なvendor-rilの関数を呼び出します。
また、無 線 通 信デバイスの 制 御 は、C P U から見ると、多くの時 間を要するのが 普 通なので、各

R I L ̲ U N S O L ̲ R E S P O N S E ̲ R A D I O ̲ S TAT E ̲
CHANGED（1000 ）から
RIL̲UNSOL̲CALL̲RING（1018 ）までの19個あります。加えて、いるようです。

vendor-RIL（libril.so） このコマンドは、現在通話中かどうかの判定にも使われているので、つねに0を返す訳にはいきません。
作成の実際
現在通話しているかどうかを内部的に保持し、その値
vendor-rilは共有ライブラリとして作成され、rildか

R I L ̲ U N S O L ̲ R E S P O N S E ̲ S I M ̲ S TAT U S ̲ら呼び出されます。前項で説明した各コマンドの実際

CHANGED（1019 ）の処理内容を記述することになります。

からを返すようにします。
・RIL̲REQUEST̲DIAL

本来ならば、新たなライブラリを作成し、build/

単純に電話をかける処理を行います。現在通話中

リクエストはとりあえず 最 小 限 の 処 理 だけを行っ

RIL̲UNSOL̲RESTRICTED̲STATE̲CHANGED

target/board/generic/system.prop 内のrild.

の回線がなければ、無線通信デバイスに発信のコマンて 即 座 にリタ ーンし 、 処 理 が 完 了した 時 点 で（1023 ）

libpathにそのPATHを設定すべきなのですが、そのドを発行するだけです。

onRequestCompleteを呼び出し、処理の完了をアまではCDM 用に用意されているのですが、cdma-

ためにはコンパイル環境を整えたり、ファイルの追加を一般的なATコマンドが実装されていれば、単純にプリケーションに通知するという仕組みになっていま

importでは別の名前で定義されている部分があるのしたりとやらなければならないことがいろいろあります。

ATDコマンドを実行するだけです。ATコマンドを送信す。この仕組みはとくに変更する必要もないので、ここ

で、マージの際には注意が必要です。以前も、開発ブ

ここでは、 すでに用意されているreference-ril

するライブラリはすでに用意されており、GSMでも発ではvendor-rilの内容について説明します。

ランチ（cupcake ）をmasterにマージする際に大きなのソースを編 集してしまいます。h a r d w a r e / r i l /信はATDなのでとくに変更することはありません。正し

ソースツリーにはvendor-ril.soのリファレンスとして、混乱が生じました。また同じようなことが起こらないこ

reference-rilにreference-ril.cというファイルがあり、く接続できれば、内部で管理している通話中の回線数

reference-rilが用意されているので、その内容についとを祈るばかりです。

rildはデフォルトでlibreference-ril.soを読み込むよを増やします。

て見てみます。

こうしてみると、かなり多数のコマンドを処理してやらうに設定されています。
・RIL̲REQUEST̲HANGUP

なければならないように見えますが、電話の発着信、例として、WillcomのW-SIMというPHSの通信用意されているRequest codeは、

SMS（ショートメッセージ）の送受信だけなら、それほモジュールを使った通信への対応について説明しま

GSMでは、HANGUPでいったん保留する処理

RIL̲REQUEST̲GET̲SIM̲STATUS（1 ）

ど多くのコマンドに対応してやる必要はありません。

す。ただし、具体的な仕様は公開されていないので、を行うのですが、W-SIMでは保留ができないので、最小限対応しなければならないコマンドは、

詳細は記載できません。詳細な資料が必要な方は、ATHコマンドで回線を切断し、内部で管理している通RIL̲REQUEST̲SET̲LOCATION̲UPDATES・RIL̲REQUEST̲GET̲SIM̲STATUS

Willcom Core Module Forum（WCMF：http://

話中の回線数を0にします。

（76 ）・RIL̲REQUEST̲GET̲CURRENT̲CALLS

www.wcmf.jp ）に加入して資料を入手してください。

各コマンドはRequest codeで区別されます。現在

から始まって、までの76個ですが、cdma-import ブランチを見る

・RIL̲REQUEST̲DIALと、CDMA用に、・RIL̲REQUEST̲HANGUP

RIL̲REQUEST̲CDMA̲SET̲SUBSCRIPTION

・RIL̲REQUEST̲SIGNAL̲STRENGTH（77 ）・RIL̲REQUEST̲OPERATORから・RIL̲REQUEST̲SEND̲SMS

RIL̲REQUEST̲DEVICE̲IDENTITY（102 ）40

組込みプレス Vol.16

・RIL̲REQUEST̲SMS̲ACKNOWLEDGE

各コマンドでは、以下のような処理を行う必要があります。

・RIL̲REQUEST̲SIGNAL̲STRENGTH
無線通信デバイスは、信号強度を取得する必要があります。これは画面上アンテナアイコンで表示される・RIL̲REQUEST̲GET̲SIM̲STATUS
現在設定されているSIMカードの状態を返すコマンドです。本来は、SIMスロットの状態を確認してそのものです。無線通信デバイスから簡単に信号強度を取得できるのであれば、それを返せばいいのですが、ここでは必ず同じ値を返してしまいます。

組込みプレス Vol.16

41

特集 1

Android による組込み開発

・RIL̲REQUEST̲OPERATOR
現在使用している携帯電話キャリアの名称を返しま・RIL̲UNSOL̲RESPONSE̲CALL̲STATE̲CHANGED

す。本来は、無線通信デバイスにアクセスし現在選択回線状態が変化したときに発生します。無線通信デしているキャリアの名称を返す必要がありますが、複バイス側から、RING、BUSY、NO CARRIERなど

数のキャリアに対応したデバイスでなければ固定値でが帰ってきたとき、つまりダイアルしたけれど接続できかまわないので、固定値を返します。

なかったときや電話がかかってきたときに発生します。
これがないと電話の着信ができないので、サポート

・RIL̲REQUEST̲SEND̲SMS
ショートメッセージを送信します。GSMでは、ショー
トメッセージは半角英数のみにしか対応していません。

しなければなりませんが、RINGという文字列はほとん
どのデバイスで同じですので、着信を認識することだけに関してはとくに変更することはありません。

そのため、ショートメッセージの内容は1文字7ビットで着信があると、アプリケーションは前述の R I L ̲

構成し、それを8ビットに詰め込む形で送られてきます。

REQUEST̲GET̲CURRENT̲CALLSを使用してたとえば、AAAAAAAAの8 文字を送った場合 A

待ち状態の回線があることを認識するので、内部の回の文字コードはASCIIで0x41なので、16進数で、41線状態を正しく更新しておきます。アプリケーションは

41 41 41 41 41 41 41の8バイトになります。

RIL̲REQUEST̲ANSWERで電話を取ります。

しかし、実際にreference-rilに送られてくるデータ
は16進数でC1 60 30 18 0C 06 83の7バイトとなっていました。
2進数で説明すると図のようになります。
図2 コード変換

・RIL̲UNSOL̲RESPONSE̲NEW̲SMS
SMSのメッセージが到着した時実行されます。SMSの内容は前述の文字コード変換の逆変換を行ってア
プリケーションに渡します。
WilcomのW-SIMへの対応について書いてきまし
たが、これらの対応は他のキャリアでも同様に必要となると思います。とくに、W-SIMのようにGSMとは回線管理の方式自体が異なるようなキャリアに対応する
ためには、上位のアプリケーション、フレームワークを含めた対応が必要になります。
たとえば、W-SIMでは無線強度が6段階あるのです42

この変換はフレームワークで行われていました。

が、GSM方式では4段階しかありません。したがって、

rild 以下で通信方式の違いを吸収するのであれば、アンテナのアイコンが違ったり、通話中に保留ボタンがrildには変換していない文字列を送り、通信方式に依表示されていても、W-SIMでは保留して別の電話に出存したコードの変換はreference-rilで行うべきだと思ることができないなど、とくにSMSで日本語を処理するいます。しかし、SMS以外にも通信方式の違いがアプ

ためには、フレームワークの変更が必要になります。

リケーションやフレームワークに波及してしまうのは避け

今後もっと多くのデバイスに実装され、いろいろなデられないので、フレームワークで行っているのでしょう。

バイスで簡単に使えるようになれば、これまでGUIの変更点を減らすためには、reference-rilでGSM方

貧弱さゆえに敬遠されてきたUnix 系のフリーOSが、式の文字列をW-SIM 方式の文字列に変換するように

WindowsCEなどの市場に進出していくことができる

実装します。

かもしれません。

組込みプレス Vol.16