2015年1月31日土曜日

(Xperia)ブートループ化した際の復活の呪文

 散々カーネルモジュールとかいじっているのに、実はinit.dが正常に動いていませんでした(原因はGoogle PlayでダウンロードしたBusyboxがrun-parts実行中にセグメンテーションフォルトで停止していた)。
 原因が判明したのはいいんですが、その際にどこかのファイルを壊したのか再起動後にSONYのロゴ表示を繰り返す...
 という訳で備忘録を兼ねて、ブートループになった際の復活方法について記載します。

1.PC Companionをインストールする

以前は端末のアップデートのみ可能なUpdateServiceというアプリが提供されていましたが、投稿時はPC Companionがその役割(というか、その中のSupport Zone)を行います。
PC Companionはそれ以外にもそれなりに使えるアプリが詰まっていますので予めPCに入れておくことをお薦めします。

2.SupportZoneを起動する

PC Companionを起動し、ダイアログの一番左にあるSupport Zoneのボタンを押して起動します。この時点でSupport ZoneをPC内部にインストールしていない場合は自動的にインストール後に起動します。
ここから先は具体的に記載しようと思いましたが、こちらのガイドがわかりやすいのでソフトウェアアップデートに失敗した場合はどうすれば良いでしょうか?をそのまま載せちゃいます。
【5】のラジオボタンはまずは「現在の携帯電話/タブレットのソフトウェアを再インストールする」を使ってみましょう。これで修復出来ない場合は諦めて「現在の携帯電話/タブレットのソフトウェアを修復する」を試してみればよいでしょう。

後程、flashtoolでルート取り直しを行った際に思い出したのですが、SupportZoneで行っているこの修復方法って、flashtoolでの端末flashと全く同じですね。慣れればflashtoolの方が便利かもしれないですね。

あともう一つSupport Zoneを入れておくと便利なこと、自分のPCの中でflashtool向けのftfファイルを生成できます。世の中便利なものでftfファイルをインターネットダウンロード出来るサイトはありますが、アップデート公開直後にまだftfファイルが公開されていない場合は自分で作る必要があります。この時にftfファイルを作るための素がSupport Zoneのフォルダにキャッシュのように残っています。

つか、今回はrootとっている人なら誰でもわかるような知識だけど、Sony mobileやキャリアに迷惑かけないために是非知っておくべき知識でした。

2015年1月25日日曜日

smartassH3をいじってみる

AndroPlusの作者がXperia Z2・Z3むけにカーネルを作成しています。
GitHubを使用しているため、ソースコードを拝見することが出来、色々と比較してみました。

  1. AnDyXX氏が作成したsmartassH3のソースコード(今回こちらをいじっている)は、C3C0が作成したZTE skateのsmartassH3のオリジナルソースコードとほぼ変わらなかった。
  2. 次に、2chのGXスレッドで154氏が書いたソースコード(smartassV2)にはboostの設定が追加されており、システムからboost_pulseを受信するとCPU周波数を上昇させる挙動がなんとなく見えました。また、workqueueの割り当てがalloc_workqueue()に変更されていましたのでこれをマージした。
  3. AndroPlusカーネルではcpufreq_governor_smartass_h3にて全てのCPUコアに対して設定を行っているようなのでここをマージした。
  4. idle_notifier_register・idle_notifier_unregisterの記述は、AnDyXX氏のソースコードではあった(ストックカーネルのinteractiveにはある)のでそれはそのまま残した。

なお、Tunable parametersを以下の通り変更しました。原文のコメントと共に自分なりの翻訳も付けてみた(間違っているかもしれないのはご了承下さい)。

/*
* The "ideal" frequency to use when awake. The governor will ramp up faster
* towards the ideal frequency and slower after it has passed it. Similarly,
* lowering the frequency towards the ideal frequency is faster than below it.
*
* 個人的な翻訳(以下、他のパラメータも記載)
* スリープ解除時に利用する「理想的な」周波数設定。CPUガバナは理想的な周波数へ
* 素早く上昇し、それを超えた場合(オーバーシュート時)はゆっくり下降させる。
* 同様に理想的な周波数まで下げる際はそれを超えた場合より素早く下降させる。
*/
#define DEFAULT_AWAKE_IDEAL_FREQ (702*1000)
AnDyXXのソースコードの値は378000、Xperia Zは最大周波数1.5GHzのため、この半分で周波数テーブルと同じ値にした

/*
* The "ideal" frequency to use when suspended.
* When set to 0, the governor will not track the suspended state (meaning
* that practically when sleep_ideal_freq==0 the awake_ideal_freq is used
* also when suspended).
*
* サスペンド時に使用する「理想的な」周波数
* 0にセットした際、CPUガバナはサスペンド状態を監視しない(実際には
* sleep_ideal_freq==0 の際はサスペンド時にもawake_ideal_freqを使用すると
* いう意味である)。
*/
#define DEFAULT_SLEEP_IDEAL_FREQ (384*1000)
AnDyXXのソースコードの値は378000、サスペンド時は周波数テーブルの最低周波数384000とした

/*
* Freqeuncy delta when ramping up above the ideal freqeuncy.
* Zero disables and causes to always jump straight to max frequency.
* When below the ideal freqeuncy we always ramp up to the ideal freq.
*
* 理想周波数まで上昇させる際の周波数変動値
* 0の場合は一気に最高周波数まで上昇させる。
* 理想周波数より低い場合、理想周波数まで上昇させる。
*/
#define DEFAULT_RAMP_UP_STEP (216*1000)
AnDyXX氏のソースコードでは80000、この値はC3C0氏のコードでは最大周波数/10位(ZTE steakの最大周波数は800MHz)のため、当初は(108*1000)にしてみた。しかしこの値では384Mhz〜486MHz間をうろうろし、周波数が上がらない(ようだった)ので2倍に変更(AndroPlusカーネルの作者様に質問し教えていただいた)。
/*
* Freqeuncy delta when ramping down below the ideal freqeuncy.
* Zero disables and will calculate ramp down according to load heuristic.
* When above the ideal freqeuncy we always ramp down to the ideal freq.
*
* 理想周波数まで下降させる際の周波数変動値
* 0の場合はCPU負荷状態を確認し一気に所要周波数を下降させる。
* 理想周波数より高い場合、理想周波数まで下降させる。
*/
#define DEFAULT_RAMP_DOWN_STEP (216*1000)
DEFAULT_RAMP_UP_STEPと同様。

/*
* CPU freq will be increased if measured load > max_cpu_load;
*
* CPU負荷がmax_cpu_loadを越えた際、CPU周波数を上昇させる。
*/
#define DEFAULT_MAX_CPU_LOAD 85
参照したソースコードでは変更した形跡はないためそのまま

/*
* CPU freq will be decreased if measured load < min_cpu_load;
*
* CPU負荷がmin_cpu_loadを下回った際、CPU周波数を下降させる。
*/
#define DEFAULT_MIN_CPU_LOAD 70
参照したソースコードでは変更した形跡はないためそのまま

/*
* The minimum amount of time to spend at a frequency before we can ramp up.
* Notice we ignore this when we are below the ideal frequency.
*
* CPU周波数を上昇させるまでに必要な最少経過時間
* 理想周波数より低い場合はこの値は無視する。
*/
#define DEFAULT_UP_RATE_US 48000
参照したソースコードでは変更した形跡はないためそのまま

/*
* The minimum amount of time to spend at a frequency before we can ramp down.
* Notice we ignore this when we are above the ideal frequency.
*
* CPU周波数を下降させるまでに必要な最少経過時間
* 理想周波数を超えている場合はこの値は無視する。
*/
#define DEFAULT_DOWN_RATE_US 49000
参照したソースコードでは変更した形跡はないためそのまま

/*
* The frequency to set when waking up from sleep.
* When sleep_ideal_freq=0 this will have no effect.
*
* スリープ解除時に設定される周波数
* sleep_ideal_freqを0に設定した際、この値は無視される。
*/
#define DEFAULT_SLEEP_WAKEUP_FREQ 99999999
参照したソースコードでは変更した形跡はないためそのまま

/*
* Sampling rate, I highly recommend to leave it at 2。
*
* サンプリングレート、2のままにしておくことを強く推奨する。
*/
#define DEFAULT_SAMPLE_RATE_JIFFIES 2
参照したソースコードでは変更した形跡はないためそのまま
最終的には、もう少しはチューニングしてみようかと思います。

2015年1月18日日曜日

電波時計をローカルで同期させる(Android端末利用)

 最近置き時計・目覚し時計はそれなりの価格のものにも電波時計の機能を持つものが増えてます。
 私の家にも電波時計対応の置き時計は4個ほど有りますが、自宅が鉄骨鉄筋コンクリート造のため福島県の電波でも部屋の奥には届かないようです(北海道在住のため遠いというのもあるのですが)。
 電波時計用の標準電波(JJY信号と言います)を再送信する機械は販売されていますが、業務用・民生用ともに高価なため今回はAndroid端末で動作するアプリをご紹介します。
 なお、このアプリを使用した場合JJY信号を勝手に送信するため、自宅内だと問題にはなりませんが、強力なアンテナで送信した場合は電波法違反になるおそれがあります。

 ちなみにGoogle Playで"JJY"のキーワードで検索されるアプリは私の環境ではちゃんと動作しませんでした。おそらくAndroid SDKでのタイマーの使用方法が変わったためそれが影響したものだと思われます。


1.JJY信号を自宅で送信するには

本当ならば40ないし60kHzの信号をビーコンのように送信するものです。
スマホのフォーンプラグからは通常は24kHz以上の音声信号は送信できませんが、これを13.333kHzの信号を3次高調波にして39.999kHzで送信するようです。
技術的に詳細を知りたい場合はこちらを参照下さい(PCでJJY信号をサウンドカードから送信する話と、JJY信号用のアンテナ作成の話が記載されています)。

2.Android端末でJJY信号を送信するアプリ

こちらをお勧めします。
このアプリを起動し、画面右下の「同期」ボタンで事前に端末の時刻をNTPプロトコルで同期してから(NTPプロトコルを使用するため、当然ネットへの接続が必須)、画面中央の「同期開始」ボタンを押すと、端末からJJY信号の音声が出力されます。
ちなみに3Gで通常の待受状態だと、基地局との間で時刻同期されているようでNTPでの同期は不要となります。
端末のそばに電波時計を起きしばし待つと、時刻が同期されます(電波時計は手動同期ボタンを押してお待ちください)。

3.音声出力アプリ向けのJJY信号用アンテナについて

一番手ごろなのはコンポのチューナにセットされているループ型のAMアンテナを流用する方法です。
AMアンテナのチューナ接続部(多分銅線2本)に3.5mmのフォーンプラグを付けるだけです。

2015年1月17日土曜日

ソフトキーのあるAndroid 端末でナビバーを隠す(Kitkatまで動作確認)

ナビバー(ソフトキー)有

GoogleのNexusがそういう実装のため、現在発売されている大概のAndroid端末はナビーがソフトキー(画面でメニューバーの「戻る」・「ホーム」・「メニュー」アイコンが描画されている)になっています。
ソフトキーでもハードキーでも全然構わないのですが、ソフトキーが常時表示されると画面が少し狭くなってて少し損していると感じるのは私だけではないと思います。 そこで、今回はいろいろな形でソフトキーを隠す方法を記載します。

1.root化不要(動作するかは環境次第?)

GMD Full Screen Immersive Mode」が使用できます。残念ながら、動作しないとの報告もあるようですが、root取らずに隠すことが出来るなら使ってみる価値はあるかと思います。
このアプリは後述の「GMD Auto Hide Soft Keys」と同じく、通常はナビバーを隠し、画面最下部をクリックもしくはスワイプでナビバーを復旧させます(ナビバーを表示可能な最下部部分は通常赤色の線が表示される)。
また、Known issues(既知の問題)ではナビバーを隠している際にはキーボードが動作しないとあります。

2.root化が必要(以前使用していました)

GMD Auto Hide Soft Keys ★ root」が動作するかもしれません。
私はJerryBeans(V4.2)までは常用していました。
Kitkatではなぜか電話アプリで通話ボタンが隠れてしまうバグがあり使用をやめています(電話できないのではスマートフォンではないでしょう)。

3.root化が必要(タブレットでは便利)

以前使用していた中華タブレットで「full screen」を使用していました。
これの良い所は、画面の左下と右下角にうっすらと「戻る」と「ホーム」のアイコンが常時表示されており、ここをクリックすると操作可能になります。
また、「戻る」と「ホーム」ボタンは長押しで別な機能を追加可能です(たとえば右下角を長押しするとパイチャートを表示して拡張メニューを開くなど)。
唯一の問題点はメニューバーが隠れた際にキーボードを表示するとキーボードのボタンとfull screenのボタンが重なることでしょうか。

4.常にナビバーなんか要らない(別な方法で何とかする。当然root必須)

この方法は「Gravity Box」と「LMT Launcher」を併用する方法です。
私の購入した中華タブレットではGravity Boxが動作しなかったので、これが動作する端末以外では動作しませんが、この方法だと完全にナビバーが不要になります。
ナビバー(ソフトキー)なし
上記の1〜3はGoogle Playからダウンロードすれば誰でもお試し出来るかと思いますので、以下では4の方法について説明します。
1)LMT Launcherをダウンロード
 先のリンクからダウンロードし、使える状態にします。
 ナビバーを隠す場合は標準の「Pie」のみでも可能ですが、私の場合は「ISAS」も有効にしたいため、「Define feature set」を「Gestures, ISAS and Pie」にしています。
 ちなみに「ISAS」は画面の最下部に不可視のナビバーがあるように指の画面最下部から上へのスワイプで動作させる方法です。

2)LMT Launcherの設定(ISAS)
 「Set input device」を指定します。メニューの中に自分の端末名があるか探してください。ちなみにXperia Zの場合は 1.で正常動作します。
 「MIN BOUNDING BOX SIZE」に「1」を指定します。
 「ACTIVATION AREA THICKNESS」を指定します。デフォルトでは60pxですが、それより大きく・小さくしたい場合は指定数値をここに入れます。

3)ISASの動作確認
 各設定を指定して「LMT Launcher」を動かした状態で画面の最下部中央からタッチスクリーンをスワイプしてみてください。ホームに移動したらISASは正常に動作してます。
 また、画面の左端からスワイプしたらPieメニューが表示されたらこちらも動作の確認完了です。

4)Xposed Frameworkのダウンロード
 Gravity Boxを動作させるにはXposed Frameworkが必要です。XposedはAndroid本体の各ファイルを変更せずに必要な機能をアプリとしてプラグイン化することが可能なものです(ただし、競合する機能を重複させた場合は動作がおかしくなる可能性あり)。
 Xposed FrameworkはこちらからXposed Installerをダウンしてインストールして下さい。
 インストール後にXposed Installerを開き、「フレームワーク」から「インストール/更新」をクリックしてフレームワークをインストールします。インストール後は再起動が必要です。

5)Gravity Boxをインストール
 再起動後Xposed Installerを開き、「ダウンロード」から「Gravity Box」を検索します。検索方法は虫めがねのアイコンをクリックして「Gravity」と入れるだけです。
 Gravity Boxには[KK]と[JB]があるはずですので、お使いのバージョンに合わせてダウンロードしてください。
 ダウンロード後は「モジュール」からインストールした「Gravity Box」のチェックボックスをチェック済みにします。

6)Gravity Boxの設定
 「ナビバー設定」で「有効/無効の切替」をONにし、「ナビバーの有効化」をチェック、「ナビバーの高さ」を0%にします。この状態にしないとXperia Zでは通話アプリで通話用のボタンが消えてしまいました。
設定後は再起動します。

7)ナビバー消去の確認
 ナビバーが完全に消え、LMT launcherのPieとISASが正常に動作することを確認します。

Xposed Installerは他にも便利なアプリがいろいろあります。現状Lollipopには対応しておりませんが、Kitkat以前をお使いならば是非インストールしても損は無いでしょう。

あと、Android純正ブラウザで全画面を有効にした場合、ブラウザのパイチャートとLMTのそれが重なってしまいます。その場合はLMT側で設定を変更してみてください。

2015年1月15日木曜日

AndroidのV4.4(KitKat)でSELinuxをPermissiveモードに変更する。

自分が使っている限りではあまり影響に気づいていませんでしたが、KitKatではSELinuxに正式に対応(それまではインストールされていましたが、Permissiveモードで動作)したためメーカがビルドする際に作成したSELinuxのルールによりアクセス制限が掛けられる(Enforcingという)ようです。
これに気づいたきっかけとしては、先日書いたColorflyのタブレットでのroot権限でのフラッシュメモリアクセス制限の理由を調べていたためです。

SELinuxの詳細はまだ掴みきれていませんが、これを以前のバージョンのようにPermissive(ルールファイルは読込し解析を行うが、違反を発見した場合はログ出力のみでアクセス制限はしない)モードで動作させるために一番手っ取り早い方法としてはSELinux Mode Changerを紹介します。

このアプリ、当然ながらroot権限でなければ動作しません。

インストール後にアプリを起動すると、画面中央に「Enforcing」と「Permissive」の2つのボタンがあり、どちらかがグレーアウトされているかと思います(グレーアウトしている方が現在適用されているルール)。
グレーアウトしていない、操作可能なボタンを押すだけで切り替え可能です。
これだけで本当に切り替え可能かどうか、確認するためにadb shellにて端末に潜り、/system/bin/getenforce  を実行して戻り値を確認したところ、Permissiveに変更した状態では確かに「Permissive」と表示されています。

なお、このアプリは端末再起動時に自動的に起動し、端末の設定を変更するようです。

Enforcingでメーカが出荷した端末に対し、勝手にPermissiveにしてセキュリティ対策を弱める行為はくれぐれも自己責任でお願いします(ただし、Enforcingの場合はかなり端末のリソースを消費するらしいので、Permissiveにしたほうが電池持ちなどが良くなる可能性はある)。

2015年1月12日月曜日

Android 4.4(Kitkat)でのフラッシュメモリ読込・書込権限について(調査中)

先日Colorfly e708 3G Proという中華タブレットを購入しました。
中華タブレットは以前に購入したPIPO S1という機種を使用しておりましたが(一応今でも所有はしているが)、Google Playでアプリのアップデートをするだけで処理が固まる現象に悩まされていました(購入直後は画面描画がフリーズして暴走する現象に悩まされた)。

ま、本題に戻してこのタブレットの問題(本題)に入ります。
中華タブレットは内蔵フラッシュが8GBくらいあるうち、本体メモリ(/data)が1GB程度しか確保されていないものが多く、常用するためには本体メモリを増やす(今時2GBは必要でしょう)かLink2SDを使用してSDカードの第2パテーションを/dataの増量に使う必要があります。

しかしながらこのタブレット、rootの場合は内部・外部SDへの読込権限がない。というか、正確には当該ディレクトリへのアクセスは可能なのだが内部・外部SDのファイルが全くない表示になってしまう。

具体的にはadb shellで接続した場合の各ディレクトリのユーザ・グループ・パーミッションは以下の通り。


  • adb shell接続時(ユーザID2000)の各ディレクトリ情報とアクセス

shell@E708 3G Pro:/ $ ls -l /mnt
drwxr-xr-x root system 2015-01-12 20:57 asec
dr-xr-xr-x root root 2012-03-12 16:30 cd-rom
drwx------ media_rw media_rw 2015-01-12 20:57 media_rw
drwxr-xr-x root system 2015-01-12 20:57 obb
lrwxrwxrwx root root 2015-01-12 20:57 sdcard > /storage/sdcard0
lrwxrwxrwx root root 2015-01-12 20:57 sdcard2 > /storage/sdcard1
drwx------ root root 2015-01-12 20:57 secure
※ここでsdcardは内部フラッシュ、sdcard2は外部SDカードを示す。

1|shell@E708 3G Pro:/ $ ls -l /storage
drwxrwx--x root sdcard_r 1970-01-01 09:00 sdcard0
drwxrwx--x root sdcard_r 1970-01-01 09:00 sdcard1
drwx------ root root 2015-01-12 20:57 usbotg

cd /mnt/sdcard 後にlsでファイル閲覧は可能
cd /mnt/sdcard2 後にlsでファイル閲覧は可能

  • suでrootになったあとの各ディレクトリ情報とアクセス

root@E708 3G Pro:/mnt # ls -l
drwxr-xr-x root system 2015-01-12 20:57 asec
dr-xr-xr-x root root 2012-03-12 16:30 cd-rom
drwx------ media_rw media_rw 2015-01-12 20:57 media_rw
drwxr-xr-x root system 2015-01-12 20:57 obb
lrwxrwxrwx root root 2015-01-12 20:57 sdcard > /storage/sdcard0
lrwxrwxrwx root root 2015-01-12 20:57 sdcard2 > /storage/sdcard1
drwx------ root root 2015-01-12 20:57 secure

root@E708 3G Pro:/mnt # ls -l
drwx------ root root 2015-01-12 20:57 sdcard0
drwx------ root root 2015-01-12 20:57 sdcard1
drwx------ root root 2015-01-12 20:57 usbotg

cd /mnt/sdcard 後にlsでファイル閲覧不可
cd /mnt/sdcard2 後にlsでファイル閲覧不可

rootexplorerでアクセスした場合、/mnt/sdcardや/mnt/sdcard2に直接アクセスした場合はOKなのですが、一旦root権限を取ったあとでは上記のディレクトリを開いてもファイル閲覧できなくなります。

ごらんの通り、一般ユーザの場合は内・外部SDカードはsdcard_rというグループですが、rootの場合はrootのグループに変更されています。

Kitkatでは一般ユーザではSDカードに書込する権限がないという問題に関して、AndroPlusのこちらの通り/system/etc/permissions/platform.xmlWRITE_EXTERNAL_STORAGE<group gid="media_rw" />を追加する方法を見習って<group gid="root" />を追加してみましたがそれでもダメなようです。

あと中華タブレットはストックカーネルではバッテリ消費のチューニングが足りないようですが、SONY Mobileのようにカーネルソースコードを公開してくれないので、手を入れるのはかなり困難っぽいですね。

タイヤの真実について(その2)

1年ぶりにタイヤの真実について書き続けていきます。
インチアップしてもタイヤと地面の接地面積はあまり変わらない


「インチアップする場合、必ず幅広タイヤ使うってことは接地面積が増えるだろ」って思いますよね。
でも、インチアップで偏平率が上昇した際に、タイヤ幅を太くすると同時にリング剛性(タイヤの輪の部分=進行方向の強度)が上がりたわみにくくなるので「地面と接する長さが短くなる」のはご存知ですか?
逆に偏平率が低いタイヤはリング剛性が低いため、結果としてはそれだけ「たわみ量が増えて地面と接する長さが長く」なります。
箇条書きにしてみましょう。

  • 偏平率が低いタイヤ
    タイヤ幅=細い  接地長=長い
  • 偏平率が高いタイヤ
    タイヤ幅=太い  接地長=短い
接地面積は幅×長さですから「インチアップで接地面積があまり変わらない」結果になることがわかるかと思います。

それでは何故、「インチアップするとタイヤのグリップ力が向上し、乗り心地が悪くなる」のか?
次回はもっと突っ込んだ話を書きます。

BLUL不可能なAndroid端末でモジュールを作成する方法(Xperia Z  SO-02E編)

 さて、備忘録を兼ねて記録を残していきます。
 日本国内のスマホは現在販売されているものはBLUL(ブートローダの解錠)が出来ないため、端末の自由な改造が出来ません。
 私はパズドラ他スマホではゲームはほとんどしないため、そんな不自由な状態ではつかいたくないので、自分の知識を付ける目的でroot取得後にCPUガバナを移植してみることにしました。

 え、ストックのガバナが性能と省電力のバランスが最高ではないのかって?そうかもしれないけど、もしかしたらそうではないかもしれない。やってみて損はないでしょ?
 また、自分はXperiaユーザのためSONY mobile製品の話しか記載しておりませんが、他社でも同じ方法で作成することが出来るかと思います。

1)前提条件

  • 端末の管理者権限(root)取得
    大前提。root取得した時点で、故障時にドコモショップほか通信キャリアのショップへの持ち込みはしないと心に誓うこと。
  • 動作環境
    コンパイルのためのtoolchainはLinux環境でしか検証しておりません
    もしかしたらWindows・MACで動作するかもしれませんが、どちらも環境は作っていなのでわかりません。
  • android SDKをインストールしadbが動作することを事前に確認すること。
    また、"adb shell"にて端末のLinuxのシェルが普通に使えること。
  • ストックカーネルのビルド方法を理解する
    SONY mobile の Developper Worldの以下のリンクを事前に読み、ストックカーネルを自分の母艦(PC)上で作成する仕組みについてざっと理解すること。
    how-to-build-and-flash-a-linux-kernel

2)カーネルソースコードのダウンロード

SONY mobile の Developper Worldから自分の端末で使用するカーネルソースをダウンロードする。
http://developer.sonymobile.com/downloads/opensource/
 ここにあなたの端末の新しいOSイメージが出た際にOpen source archiveが公開されるのでそれをダウンロード。
 ちなみにこのドキュメントを最初に書いた時点(2015年1月)ではXperia Z(SO-02E)向けの最新ビルドは10.5.1.B.0.68(2014年11月27日に公開)。
 ダウンロードしたソースコードを自分のPC上で解凍する。ちなみにkernelフォルダ内部だけで良い。

3)クロスコンパイラのダウンロード

先に記載したリンクにあるGoogleのAndroid SDKに添付のクロスコンパイラ(toolchain)をダウンロードし、PATHを通しておく。
 このコンパイラでカーネル・モジュールをmakeする際には必ず「ARCH=arm CROSS_COMPLE=$CROSS_COMPILE」と指定する形になる。
 環境変数$CROSS_COMPILEは先にダウンロードしたtoolchainのうち、bin/arm-eabi-を指定する。この値はMakefileに記述するか、.bashrcに記述しておけば良い。もちろん環境変数を使いたくない場合はフルパスで指定すればよい。

4)ストックカーネルのビルド

私がストックカーネル向け追加モジュールをビルドした際、一番スムーズに動作したのは追加モジュールのソースコードをストックカーネルのソースコードとは別のディレクトリに配置し、make時にストックカーネルのソースディレクトリを指定する方法でした(やり方は後述)。
 という訳で、予めストックカーネルを以下の方法でビルドします。
 a)EXTRAVERSIONの一致
  adb shellで端末のシェルを動作させ、uname -rコマンドでストックカーネルのバージョン表示をします。
  また、/system/lib/modulesにある何らかのモジュールに対してmodinfo ****.ko(****にはその場所にあるモジュールを指定。どれでもいいです、例えばlcd.ko)してvermagicの記載文字列を確認してください。
  vermagicの例 
vermagic:       3.4.0-gdfbed73 SMP preempt mod_unload modversions ARMv7
次にストックカーネルのルートディレクトリにあるMakefileの先頭にEXTRAVERSIONと記載があり空欄ですがそこにunameやlsmodの記載を合わせてください。
  例えば上のvermagicの場合は「EXTRAVERSION = -gdfbed73」と指定します

 b)Configの生成
  以下のコマンドでSO-02E向けのコンフィグを複写します。
make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE fusion3_yuga_dcm_defconfig
(この時、「ARCH=arm CROSS_COMPILE=$CROSS_COMPILE」とありますが、要らない可能性が高い。)
  ここでは、「arch/arm/configs/」にある「fusion3_yuga_dcm_defconfig」をストックカーネルの.configに複写しています。
  先に紹介したSONY mobileの「how-to-build-and-flash-a-linux-kernel」ではXperia Z向けに別なコンフィグ名が指定されていましたが、SO-02Eの場合は一連の開発ボードのコードネーム=fusion3、Xperia Zの開発コードネーム=yuga、ドコモ=dcmのためこれで間違いありません。

  次にvermagicを合わせるため、先のコマンドで作成された.configファイルをエディタで開きます。CONFIG_LOCALVERSIONを探し、先に調べた"-gdfbed73"と入力して下さい。
  もしこの方法が気に入らない場合は、.configファイルの CONFIG_LOCALVERSIONは空欄にし、MakefileEXTRAVERSIONを編集して下さい。
  カスタムカーネルを作成する場合はこのあとで「make menuconfig」を実行し、カーネルの設定を色々変更しますが、ストックカーネル向けのモジュールを作成する場合は元のコンフィグを変更する必要はありません。逆に指定するとModule.symversが変更されて動作しない可能性があります(これがストックカーネルに追加モジュールを統合してメイクしない理由)。

 c)カーネルイメージ作成のための事前準備
  以下のコマンドでカーネルイメージ作成のための事前準備をします(もしかしたら不要かも)。
make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE prepare
make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE scripts/mod/

 d)ストックカーネルのビルド
  以下のコマンドでストックカーネルをビルドすると、Module.symversが作成され、外部モジュールのコンパイルが正常に動作します。
make -j8 ARCH=arm CROSS_COMPILE=$CROSS_COMPILE
要は一回カーネルをビルドし、内部モジュールのsymbol番号を確定させる処理です。
  なお、makeで指定している以下のオプションはこのような意味です。
  • -j
       同時にコンパイル出来るスレッド数
  • ARCH=
      コンパイルする際のCPUアーキテクチャー(armを指定)
  • CROSS_COMPILE=
      makeに教えるクロスコンパイラのパス(先にダウンロードしたクロスコンパイラの配置場所を環境変数で指定すれば良い)

5)ストックカーネル向けのモジュールのダウンロード

Xperia Z向けのCPUガバナのソースコードとして、以下の場所よりダウンロードしました。
  ①【ROM焼き】docomo Xperia GX/SX SO-04D/05D root1 で154氏が作成したモジュールのソースコード
http://www.mediafire.com/download/ob4clfek421bdw6/T.TX.V.4.3_kernel_modules.zip
(次項で記載のsymbol番号の件はこれで理解出来ました。感謝)
また、intellidemandやsmartassH3など最新版は以下の場所よりダウンロードしました。
  ②AnDyXXが作成したXperia Z向けのcpuガバナのソースコード
  https://github.com/AnDyXX/Xperia-devices
(ただしコチラはsymbol番号の件によりそのままではビルドできないものがある。)

6)モジュールのビルド

a)mediafireのソースコードのMakefileを加工
  自分向けの環境と違うので直してしまいましょう。
  外部のモジュールのソースコードをビルドする際、ストックカーネルでカーネルイメージを生成する際にmakeで指定したコマンドに以下のものを追加する必要があります。
  • -C
       ストックカーネルのソースディレクトリを指定
  • SUBDIRS=
      「今回ビルドするモジュールのディレクトリ」を指定
SUBDIRSを指定した場合はその後ろにmodulesを付けること。
  modulesを付けたくない場合はM=「今回ビルドするモジュールのディレクトリ」とする。
  まとめると以下の通り(/home/hogehoge配下のkernelにストックカーネルのソースコードを配置し、moduleに今回ビルド用のソースを配置した場合。)。
  make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE -C /home/hogehoge/kernel SUBDIRS=/home/hogehoge/module modules
もしくは
  make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE -C /home/hogehoge/kernel M=/home/hogehoge/module
これだけでmakeコマンド一発でモジュールのビルドは終了する。
  なお、自分の欲しいモジュールだけ指定する場合はMakefileの記載をobj += *****.oに直して複数行に分けてしまおう。
  (作成不要なモジュールの行頭に#を付けてコメント化することで生成しなくても済むため。)
 b)GitHubのソースコード修正
  GitHubでダウンロードしたソースコードはsymbol番号(要はストックカーネルのシステムコールのアドレス番地)が参照できずに警告出力される。
  この状態ではkoファイル(カーネルモジュール)が生成されるが、端末に複写してもモジュールを追加することはできない。
  そこでmediafireのソースコードにあるsymsearch.cの仕組みを利用してストックカーネルからsymbol番号を生成出来るようにする。
  • まずは一度ビルドし、phase2のWarningを出力させる。この時表示されるメッセージは以下のような感じ
    WARNING: "cpufreq_notify_utilization" [xperiaz_smartassH3.ko] undefined!
    これは"cpufreq_notify_utilization"のsymbol番号がわからないという意味。
  • 先のmediafireのソースコードではsymsearch.koを利用することでストックカーネル内部からsymbol番号を導出していたので、以下の通り処理させる。
    Warningが表示されたソースコードの先頭部分に以下のような記述を追加する
    SYMSEARCH_DECLARE_FUNCTION_STATIC(void, cpufreq_notify_utilization_s, struct cpufreq_policy *, unsigned int);
    これは、void cpufreq_notify_utilization_s(struct cpufreq_policy *, unsigned int)という関数を定義したという意味。
    先にUndefinedだった関数(この場合はcpufreq_notify_utilization)をストックカーネルのinclude/linuxからgrepで探し、当該ヘッダファイルからその関数定義を探して上記のようにマクロで記載する。
  • 次に当該ガバナの初期化処理(大概はソースファイルの最後の方にある)に以下の記述を追加
    SYMSEARCH_BIND_FUNCTION_TO(smartassH3, cpufreq_notify_utilization, cpufreq_notify_utilization_s);
    これは内部関数のcpufreq_notify_utilizationとcpufreq_notify_utilization_sを関連付けさせるという意味。
最終的にはmediafireのソースコードと双方睨めっこしてよく確認しながら行うこと。
  修正後、makeで正常にモジュールが作成されてエラーが表示されなければ終了。

7)端末へのモジュール複写と試運転

 adb push で端末にモジュールを複写する。その後、insmod でモジュールを読込させ、正常に動作することを確認する。
 当然ながらsymsearchを利用した場合は当該モジュールの読込前にsymsearch.koを読込させなければなりません。
 この時dmesgに"no symbol version for module_layout"などが表示されないか確認すること。
 追加したCPUガバナをアプリで変更(Faux Clock他)し、動作を確認してみる。
 insmodで作ったモジュールを追加した状態だけだと仮におかしくなったとしても暴走し再起動するだけなので、比較的安心してもよい。ただしIOスケジューラの場合は再起動によりSDカードの破損のおそれがあるため要注意のこと。
 正常に動作することを確認できたら、init.dにスクリプトを記載して端末のリブート時にinsmodされるようにする。
 init.dスクリプトの作成が面倒な場合やroot化したがinit.dに対応しない端末では、端末の起動後にModule Loaderアプリで自分で指定して希望のモジュールを読込するのもお勧めです。

8)移植したCPUガバナの感想

androplusの作者もお話している通り、SmartassH3が出来が良い感想を持っています。使用率の割に電池の持ちがよい感触。ただし、CPUガバナを変更可能なアプリで各コアの周波数を見ている限りでは1コア動作時は上限貼り付き(1.5GHz)にもみえるため、さらに省電力なガバナがあるかもしれません。

9)モジュールのソース・バイナリ提供

ソースコードはGitHubに置いておきました。こちら
作成したモジュールはTunableの設定が落ち着いたらアップしたいと思います。もちろん、動作保証は致しませんので。