2011年4月24日日曜日

XOOMが我が家にやってきた

仕事帰りに秋葉原へ行ったら、まだやってましたね。
XOOM+Pocket Wifiのセット販売

画像


Data05は要らないですが、Pocket Wifiとのセットならお得(25,100円)でポイントが10%付くので良いかなと思って買っちゃいました(^^;)
最後までOptimasPadと迷ったんですが、OptimasPadはサイズ的に中途半端な感じです。
通信もデータ通信が出来てテザリング出来るのは魅力的なのですが、Wifiルータ代わりに持ち歩くのはちょっと...
USBがホストモードに対応していて、キーボードとか繋げて遊べるのでいいのですが、そこはBTで良いかなと
ということで、最終的にはXOOMにしました。
今までWifeルータ持ってなかった(NexusOneで代用)ので、Pocket Wifi単独で使えるのも良いですね。

REGZAタブレットも6月末に予定されていますが、ちょっとそこまで待てない、そこまで購買意欲が続かない。
一応まがりにもAndroid関連の仕事することになったので、1台くらい3.0の現物持っておきたいなと。

待てる方は、夏以降の国産品を待った方が良いでしょう。
NexusTabletが出るという噂もありますし。

●開封の儀

外箱はこんな感じ
画像


ぱかっ
画像


アクセサリ
画像


サイズ比較
B5Vaioより少し小さめ
画像

XOOMのデバイスドライバーインストール

XOOMをPCに接続してみましょう。

接続後にPCのウイザードに従って、AndroidSDK配下のフォルダ(android-sdk-windows\extras\google\usb_driver)を指定してもインストールできません。

XOOM用のデバイスドライバは以下のサイトからダウンロードしてインストールします。
http://www.motorola.com/Support/US-EN/Support-Homepage/Software_and_Drivers/USB-and-PC-Charging-Drivers

画像



現在のバージョンは4.9.0

インストーラを起動します。
画像


ライセンス
画像


インストール
画像


インストール完了
画像


PCから見えるようになります。
EclipseからもDDMSで中身が見えるようになります。

XOOMでBluetoothキーボード接続

前に買ったBTキーボードがころがってたのでXOOMとつなげてみました。

設定⇒無線とネットワーク⇒Bluetooth設定
でScanして、ぺリングしてやれば、あっさり繋がりました。

画像


こんな感じ
ノートPCに比べれば軽いので、勉強会の時のメモとかネット接続とか、これで良いかも
ただ、入力が英語配列になってしまうのが難点
画像

2011年4月22日金曜日

第16回 V7から始めるUNIX講座 復習とまとめ(システムコール落穂拾い)

第16回 V7から始めるUNIX講座(システムコール落穂拾い)

今回で16回目になります、早いものです。
ずいぶん続きましたが、諸事情により、第16回でいったん区切りとさせて頂く事になりました。
私自身も非常に勉強になりました、まごろくさん及び聴いていただいた方々に感謝いたします。

●前回の補足

exit
339行目:FDは全てクローズ
⇒UNIXでのポイント
ここで必ずクローズするので、exitするならFDをCloseする必要はありません。
342行目:inodeのリファレンスカウントをデクリメント。inodeのリファレンスカウントが1ならinodeを開放してパイプをアンロック
⇒ここもポイント。プロセス毎にカレントディレクトリを握っています。そのためここで参照を外しています。
348行目:acctでアカウンティングファイル?に書き込みをしている
⇒acct()が課金情報の書き込み。大昔のコンピュータは高価だったので、CPUの使用時間で従量制の料金を払ったそうなので、その元になる情報を書き込んでいます。

wait
waitはゾンビになったプロセスの後始末をします。
413行目:u_procp(アドレス)を指定してスリープします。
誰かがwakeupするまで、ずっとここで寝ています。

413 sleep((caddr_t)u.u_procp, PWAIT);

バックグラウンド”&” で起動したプロセスの終了はSIGCHILDのsignalが来るのでその時にwaitすることで、後処理をします。



「システムコール番号の歴史」
@oracchaさんのまとめられた、システムコール番号の歴史を元に振り返ってみます。
http://tiki.is.os-omicron.org/tiki.cgi?c=v&p=%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB%C8%D6%B9%E6%A4%CE%CE%F2%BB%CB

表の見方、
UNIX v7、MINIX 1.0、Linux 2.4.18、FreeBSD 4.5の1から100番まで
空欄はUNIX v7と同じという意味です。
番号が若いものは昔からあるシステムコール

ざっとですので、説明が抜けているところもありますが、ご容赦下さい。

exit 第15回プロセスの停止でやりました。
fork 第1回でやりました。
read ファイルシステムの辺りで軽くやりました。★
write ファイルシステムの辺りで軽くやりました。★
open ファイルシステムの辺りで軽くやりました。★
close ファイルシステムの辺りで軽くやりました。★
wait 第15回プロセスの停止でやりました。
creat ファイルシステムの辺りで軽くやりました。★
link ファイルシステムの辺りで軽くやりました。★
unlink ファイルの削除
exec 第2回でやりました。
chdir カレントディレクトリの変更
time プロセスの実行時間
mknod 特殊ファイルや通常のファイルを作成する
chmod パーミッションの変更
chown オーナーの変更
break BSSの下の端を下げます。メモリの使用領域の境界を下げる(だけ。)その当時malloc 自分で作るモノだったようです。
stat スーパーブロックの情報です(du, dfはボリューム全体の情報を示す)
seek File構造体のoffsetの値を変更する
getpid プロセスIDの取得
mount ファイルシステムでやりました。
umount ファイルシステムのアンマウント
setuid プロセス生成時にファイルの所有者(通常はroot)の権限を得られる
getuid ユーザIDを取得
stime
ptrace デバッガで使います
alarm
fstat 現在オープンしているファイルの情報を表示します
pause
utime
stty sttyシステムコールの実体、機能の多くはioctlに吸収されました。
gtty
access
nice プロセスの優先度の重み付けに使います。
ftime
sync ダーティなキャッシュをディスクに書き出します。sync;sync;syncで電源ブチが正式な作法(^^;)
kill 第13回シグナルでやりました
switch
tell
dup 第14回パイプでやりました
pipe 第14回パイプでやりました
times
prof
setgid
getgid
sig 第13回シグナルでやりました
acct アカウント
phys ?
lock ファイルロック
ioctl
mxpchan
exece
umask デフォルトでのファイル作成時のパーミッションを指定
chroot 特定のディレクトリをROOTと見なす

★ファイルシステムは排他が細かくて読むのが大変

補足
V7にはmkdirがありません、mknodとlinkを組み合わせていたが問題がありました。
mknod とlinkの間でシステムがダウンあるいはCtrl+Cするとでは不整合が起き得るので後にアトミックなmkdir が用意されました。

UNIX以前(ジュラ紀)はファイルひとつ作るのも大変でした。UNIXはファイル名ひとつでファイルを生成できます。
ジュラ紀のファイルシステムはバイトストリームではありませんでした。
⇒ISAMファイルに近い(構造を持つ)形式だったようです。

ファイルシステムの違い
「UNIX以前のファイルは構造を持つのが普通。UNIXは構造を待たないバイトストリーム。」

この「構造を持つ必要のあるファイル」はデータベースに進化しました。

すでに絶版の名著、「UNIXシステムコールプログラミング」と「UNIXプログラミング環境」などを写経するのが、昔ながらの学習方法のようです。

主要な内容はV7で学ぶUNIX講座で取り上げており、これを元に細かく見たりあるいはLinuxの実装を確認したりするには十分な内容だった(システムを俯瞰するという意味で)と思います。

2011年4月21日木曜日

ACTION_BOOT_COMPLETEDによるアプリケーションの自動起動

この前、中文の記事を翻訳しました。
http://xiangcai.at.webry.info/201104/article_4.html

Androidの起動の手順に関してです。
以下の記述がありました。

ブート後に自動起動されるアプリケーション
ActivityManagerService内でアクティビティのアイドルが決定したとき、ActivityManagerServiceは最初にACTION_BOOT_COMPLETEDインテントをブロードキャストします。

なので、これでブート後にアプリケーション(Androidアプリ)を自動的に起動できるんだろうなと思っていたら、今日TL上で話題に上がっていたのでメモしておきます。

BroadCastReceiverでACTION_BOOT_COMPLETEDインテントを受けとれば良いようです。
ただし、onReceiveの実行には時間制限があるので、ここで処理はせずに目的の処理を起動するようにした方が良いようです。
http://developer.android.com/guide/practices/design/responsiveness.html

@itogさんのブログに詳細が書いてあります。
http://d.hatena.ne.jp/itog/20100611/1276218418

amコマンドを使ったIntentの投げ方も参考になります。
http://d.hatena.ne.jp/itog/20100622/1277174913

2011年4月18日月曜日

[翻訳] Androidの起動工程

twitterでAndroidの起動に関する文章が紹介されていました。
http://www.huomo.cn/developer/article-b95a.html(中文)

なかなか良い資料だったのでざっくり翻訳してみました。
中文と途中から英文でしたが、何とか大意は取れました。
↓以下は中国語で火魔网の記事を翻訳しましたという説明(念のため)
--------------------中文--------------------------
你好,这个文件不是我写的,翻译成而已。
原文是火魔网(www.huomo.cn)的[android启动流程]
http://www.huomo.cn/developer/article-b95a.html
这个文件的内容很好,我想给日本朋友介绍一下。
所以翻译成日语。
--------------------------------------------------



Androidの起動工程

●SystemServerの起動
frameworks/base/services/java/com/android/server/SystemServer.java: run()
その中で、ActivityManagerService.installSystemProviders()を使用します。
最後には、frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/配下の
各content providersのonCreate()関数を使用して、データベースの内容を初期化します。
画像


other ref:http://www.cnblogs.com/jacktu/archive/2010/07/02/1769939.html

AndroidはLinuxシステム起動の4つの手順からなります。

(1) initの起動

(2) Nativeサービスの起動

(3) System Server,Androidサービスの起動

(4) Homeの起動

全体の起動の枠組みは図のようになります。

画像


・第一歩:initial工程(system\core\init)
initを実行します。initはカーネルが起動するユーザプログラムの1つです。
カーネルが自分で起動(既に搭載されたメモリ、運行開始、さらに既に初期化された全てのプログラム、データベースなど)の後、1つのユーザプログラムinitの起動を通じて、工程の完了を導きます。initは第一番目の工程です。

Init.rc

Init.marvell.rc
画像


Initはinit.rcとinit.xxx.rcスクリプトにより、いくつかの基本的なサービスを起動します。

servicemanamger
zygote
。。。

最後にInitは終了しないだけでなく、さらにproperty serviceの機能を担当します。

1.1スクリプトファイル
init@System/Core/Init

Init.c: parse_config_file(Init.rc)

@parse_config_file(Init.marvel.rc)

スクリプトファイルの解析:Init.rcとInit.xxxx.rc(ハードウエアプラットフォームに応じて)

Init.rcはAndroidが自分で規定した初期化スクリプトです(Android Init Language, System/Core/Init/readme.txt)

そのスクリプトは4つのタイプがあります。

Actions
Commands
Services
Options.

1.2 サービス起動のメカニズム
Initがどのようにrcファイルを解析してサービスを始めるのか見てみましょう。

(1)rcファイルをオープンして、ファイルの内容を解析@ system\core\init\init.c

serviceの情報をservice_listに格納します。@ system\core\init parser.c

(2)restart_service()@ system\core\init\init.c

service_start

execve(…).serviceプログラムの起動。

・第二歩 Zygote
ServicemanagerとzygoteはAndroidの基礎を決定します。Zygoteこのプログラムによって、真のAndroid実行空間を獲得します。
初期化されたサービスは全てNavtive serviceでrcスクリプトファイル中のzygoteの記述です。

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

そのため、Zygoteはmain(…)@frameworks\base\cmds\app_process\app_main.cppから開始します。

(1) main(…)@frameworks\base\cmds\app_process\app_main.cpp

Java Runtimeの開始
runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);
(2) runtime.start@frameworks/base/core/jni/AndroidRuntime.cpp

仮想マシンの起動:startVM(...)
com.android.internal.os.ZygoteInit:main関数の実行
(3)main()@com.android.internal.os.ZygoteInit//本当のZygote。

registerZygoteSocket();//Listenソケットの登録
startSystemServer();
Zygoteサービスフレームワークに入ります。
このいくつかの手順を通して、Zygoteの起動がうまくいけば、Socket通信を利用してActivityManangerServiceの要求を受け取って、アプリケーションプログラムをForkします。

・第三歩 System Server
1つのプログラムのforkにおいて:com.android.server.SystemServer.つまりSystemServer@(SystemServer.java)が実行されます。
Androidの全てのサービス、循環フレームワーク?はSystemServer@(SystemServer.java)上で実行されます。
SystemServer.javaにおいて循環構造は見えません、init2の実現関数のみが見えます、サービスを実行し、さらにAddServiceによってservice Managerにアクセスします。

main() @ com/android/server/SystemServer

init1();

Init1()はNative空間で実現されています(com_andoird_server_systemServer.cpp)。この関数は見ればすぐ分かります。init1->system_init() @System_init.cpp

system_init()において、循環を閉じるための管理フレームワークを見ることが出来ます。

Call "com/android/server/SystemServer", "init2"

…..

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

init2()@SystemServer.javaの中でAndroidの全ての必要とするサービスを実行します。

このinit2()はNew ServiceとAddServiceによってサービスを起動します。

・第4歩 Home起動
後半において、システムが全てのAndroidサービスの起動が完了するところを見ることが出来ます、このような一連の動作によって

(1)xxx.systemReady()を使用して各サービスに準備完了を通知

(2)ActivityManagerService.systemReadyに対しては特別です

Widget.wallpaper,imm(インプットメソッド)等のready通知。

HomeはActivityManagerService.systemReady()の通知の過程で実行します。下のActivityManagerService.systemReady()の仮ソースコードです。

systemReady()@ActivityManagerService.java

resumeTopActivityLocked()

startHomeActivityLocked();//もし第1の起動がHomeActivityであれば

startActivityLocked(。。。)CATEGORY_HOME android起動の工程
このトピックにおいて、Androidのプロセス管理に関してのいくつかの情報を学ぶことが出来る。最初にAndroidのブートを通じてプロセスの起動を見てみましょう。

USER PID PPID VSIZE RSS WCHAN PC NAME

root 1 0 264 176 c00acc6c 0000c36c S /init

root 28 1 724 308 c0051354 afe0c4cc S /system/bin/sh

system 30 1 796 248 c026516c afe0b74c S /system/bin/servicemanager

root 31 1 1824 316 ffffffff afe0b50c S /system/bin/mountd

root 32 1 652 248 c02976e0 afe0c0bc S /system/bin/debuggerd

radio 33 1 5344 664 ffffffff afe0bdbc S /system/bin/rild

root 34 1 71028 18828 c00ad308 afe0b874 S zygote

media 37 1 16812 3456 ffffffff afe0b74c S /system/bin/mediaserver

root 39 1 788 288 c02f9ae4 afe0b50c S /system/bin/installd

system 86 34 187756 21836 ffffffff afe0b74c S system_server

radio 118 34 103476 13896 ffffffff afe0c824 S com.android.phone

app_4 124 34 117848 19248 ffffffff afe0c824 S android.process.acore

app_5 139 34 98672 11516 ffffffff afe0c824 S com.android.mms

app_3 151 34 92096 10976 ffffffff afe0c824 S com.android.alarmclock

app_6 161 34 94436 12616 ffffffff afe0c824 S com.android.calendar

app_9 173 34 93248 11728 ffffffff afe0c824 S android.process.media

app_15 182 34 91848 9764 ffffffff afe0c824 S com.android.voicedialer

app_16 190 34 94524 10812 ffffffff afe0c824 S android.process.im

これらは3種類に分けることが出来ます。

(1)Root Process
initはカーネルがブートした後の最初のプロセスです。主な仕事は以下を実行することです。

・init.rcとinit.%hardware%.rcを解析して実行する
・/dev配下のデバイスノードを自動的に生成する
・ログサービス、プロパティサービスを開始する
・デバイスのためにプロパティを設定する、そして子プロセスの終了イベントを監視する

(2)Native Application Process
init.rcにより、initは以下のネイティブアプリケーションプロセスをforkする

console: シェルをスタートする

servicemanager: binder IPC service managerを起動する

mountd: もし起動後、いずれかのファイルシステムへローカルソケットを通じてコマンドを受信したら、/system/etc/mountd.confで定義された全てのファイルシステムをマウントする。

debuggerd: debug systemを開始する

rild: radio interface layer daemonを開始する

zygote: Android Java VM Runtimeとsystem serverを開始する. これらは最も重要なプロセスです

mediaserver: AudioFlinger, MediaPlayerService, CameraServiceを開始する.

installd: install package daemonを開始する

(3)JAVA Application Process
全てのJavaアプリケーションプロセスはzygoteプロセスからForkされます。system_serverは特別なJavaプロセスで、zygoteから直接Forkされます。
その他のJavaプロセスはActivityManagerService(system_serverプロセス上で実行)から生成されます。例えばこのように

int pid = Process.start("android.app.ActivityThread",

mSimpleProcessManagement ? app.processName : null, uid, uid,

gids, ((app.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0), null);

Process.javaがzygoteと通信する間はUNIXドメインソケットを使用します。全体像を以下の図に示します。

画像


System Server
zygoteによって起動される最初のJavaアプリケーションです。System Serverは、コアとなるAndroidサービスを開始します、例えばActivityManager, WindowManager, PackageManagerなどなど。System ServerはAndroidのコアエンジンです。

Persistent Application(永続的アプリケーション)
ブート中にActivityManagerService.systemReadyは、全ての永続的アプリケーションを開始します。


List apps = ActivityThread.getPackageManager().getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);

if (apps != null) {
int N = apps.size();
int i;

for (i = 0; i < N; i++) {

ApplicationInfo info = (ApplicationInfo)apps.get(i);

if (info != null && !info.packageName.equals("android")) {

addAppLocked(info);

}
}
}


現在では、Phone applicationのみが永続的アプリケーションとしてAndroidManifest.xmlに以下のように登録されています。

<application android:name="PhoneApp"

android:persistent="true"

android:label="@string/dialerIconLabel"

android:icon="@drawable/ic_launcher_phone">

そのため、ブート中はphone applicationのみが自動的に起動されます。それは"com.android.phone”プロセスです。

The First Activity
最初のアクティビティはActivityManagerServiceからIntent.CATEGORY_HOMEインテントを送信することで起動されます。

Intent intent = new Intent(mTopAction,mTopData != null ? Uri.parse(mTopData) : null);

intent.setComponent(mTopComponent);

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}

ActivityInfo aInfo = intent.resolveActivityInfo(mContext.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);

if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));

// Don't do this if the home app is currently being

// instrumented.

ProcessRecord app = getProcessRecordLocked(aInfo.processName,

aInfo.applicationInfo.uid);

if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);

startActivityLocked(null, intent, null, null, 0, aInfo,null, null, 0, 0, 0, false);

}
}

それは、“android.process.acore”プロセスです。(プロセス名は、AndroidManifest.xmlに定義されています)

ブート後に自動起動されるアプリケーション
ActivityManagerService内でアクティビティのアイドルが決定したとき、ActivityManagerServiceは最初にACTION_BOOT_COMPLETEDインテントをブロードキャストします。


if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

// Tell anyone interested that we are done booting!

synchronized (this) {

broadcastIntentLocked(null, null, new Intent(Intent.ACTION_BOOT_COMPLETED, null), null, null, 0, null, null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, false, false, MY_PID, Process.SYSTEM_UID);
}
}


現在、MMS, AlarmClock, Calendar, MediaProvider, VoiceDialer と IMがACTION_BOOT_COMPLETEDインテントのレシーバとしてAndroidManifest.xmlに登録されています。そのため、それらのは自動的に起動されます。(これはJavaプロセスが残ることを意味します)

EmailもACTION_BOOT_COMPLETEDのレシーバとしてAndroidManifest.xmlに登録されています。しかし、android:enable=”false”と定義されているので起動しません。


<receiver android:name=".service.BootReceiver" android:enabled="false">

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.DEVICE_STORAGE_OK" />

</intent-filter>

</receiver>


DownloadProviderもACTION_BOOT_COMPLETEDのレシーバとしてAndroidManifest.xmlに登録されています。しかし、android:enable=”false”と定義されているので起動しません。


<receiver android:name=".DownloadReceiver" android:enable="false">

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

</intent-filter>

</receiver>


Javaプロセスの背後
system_serverは特別な事例です。system_serverはActivityThread.javaのsystemMain static functionを呼び出します、それはActivityThreadのインスタンスを生成します。
ActivityThreadはそれから、アプリケーションスレッド、アプリケーション、アプリケーションコンテキストのインスタンスを生成します、

その他の全てのJavaプロセスは、異なった方法で動作します。それはzygoteにより、Forkされたsystem_serverによって制御されます。
system_server以外のいずれかのJavaプロセスがzygoteからForkされた時、そのJavaプロセスは、自動的にActivityThread.javaのmain static functionを呼び出します(Process.javaと以下のコードの切れ端を見てください)

try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {

logAndPrintError (newStderr, "Error starting. ", ex);

}


ActivityThread.javaのmain関数は、ActivityThreadのインスタンスを生成します。ActivityThreadはそれから、ApplicationThreadのインスタンスを生成します。
ApplicationThreadはsystem_server内のActivityManagerServiceと共に情報を交換するためのIBinder objectとして動作します。
新しいプロセスは、この時は、system_serverからのIPCコールの待ちうけ以外何もしません。
アプリケーションとアプリケーションコンテキストは、この段階では生成されません。事実、プロセスが本当に動作するときまで延期されます、
例えば、アクティビティの開始、インテントの受信あるいはサービスの開始などなど

例えば、アクティビティが開始するとき、ActivityManagerServiceはどのプロセスが開始するべきか知っています、
そのためRPCはそのプロセス内で新しいアクティビティを起動するために、ApplicationThreadのscheduleLaunchActivityを呼び出します。
ApplicationThreadはそれから、ActivityThreadに対してアクティビティを起動する必要があることを知らせるためにメッセージを送信します。
ActivityThreadはそれからアプリケーションとアプリケーションコンテキストを生成します。その後、Instrumentationを呼び出します。
Instrumentationはそれから、最後に、本当にアクティビティのJavaオブジェクトを生成するためにJAVA dalvik VMを呼び出します。

2011年4月14日木曜日

Multiple substitutions specified in non-positional

Androidの開発本を見ながら、ぼちぼちと

ソースも公開されているので、ダウンロードしてプロジェクトにインポートしたら
大量のエラーが!!
プロジェクトのクリアをしても解決せず。
R.javaが生成されていないためでした。

経験的にこういう場合はリソース系のレイアウトとかStringとかに間違いがあって生成されないですね。
ということで見てみると、「string.xml」でエラーが発生していました。

Multiple substitutions specified in non-positional format
という良く分からないエラー
ぐぐって見ると
http://blogs.yahoo.co.jp/bearrolling/23838548.html

同じですね。
%でフォーマットしていますが、引数が2つのところがエラーに
なので%の後ろに「順番$」と追記したら消えました。

何とも解せない話ですが、まずは解決したのでよしとしますか