2013年1月3日木曜日

【Xperia AX SO-01E】電源ボタン長押しメニューに「CWMで再起動」追加

AXのカスタムをやっていると、再起動してCWMに入る機会が頻繁にあります。その度に音量小ボタンを長押しするのは非常に面倒。
そこで今回、電源メニューに「CWMで再起動」を追加してみます。
再起動の理由を"recovery"にし、/cache/recoveryに「boot」という空ファイルを作って再起動すれば、再起動後CWMで立ち上がるという仕組みです。どのタイミングかは未検証ですが、その後/cache/recovery/bootは自動的に削除されるようです。

イチから手順を書こうと思いましたが面倒なので、電源メニューに「再起動」を追加するこの記事この記事、および外部リソースを追加するこの記事はすでにやっているものとし、追加修正部分だけを紹介します。

前提は以下です。
・rootとってあること
・作業PCはadbコマンドが使える環境であること
・作業PCにjavaが入っていること
・端末のビルド番号は9.0.G.0.247
・CWMを導入してあること
・母艦はWindows 7
・トラブっても自力で復旧できること(つまり自己責任)

いじるファイルは、以下になります。
/system/framework/external-res.apk
/system/framework/framework.odex
/system/framework/android.policy.odex

■external-res.apk
external-res.apkの作業フォルダ内、「res」フォルダ以下のxmlにリソース追加します。
まずres\values\public.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <public type="drawable" name="ic_lock_reboot" id="0x7f020000" />
    <public type="string" name="global_action_reboot" id="0x7f030000" />
    <public type="string" name="global_action_recovery" id="0x7f030001" />
</resources>

次にres\values\strings.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="global_action_reboot">Reboot</string>
    <string name="global_action_recovery">CWM Reboot</string>
</resources>

続きましてres\values-ja\strings.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="global_action_reboot">再起動</string>
    <string name="global_action_recovery">CWMで再起動</string>
</resources>

CWMで再起動のアイコンは、通常再起動のアイコン(ic_lock_reboot.png)を使い回しすることにします。
別にしたい場合は、drawable-xhdpiに画像を追加した上でpublic.xmlにもdrawableを追加、リソースIDを振って、android.policy.odexの方でそのIDを指定するようにしてください。その際レジスタを増やしたりする必要があると思いますが、分からなくて怖い人は我慢しましょう。

新規でexternal-res.apkをこしらえる場合は、この記事のようにaaptで作成して署名とかしないといけませんが、すでに作っている場合はapktoolで展開、編集、再ビルドで署名のし直しは不要です。

■framework.odex
framework.odexをbaksmaliした展開先の中で、以下のファイルを探してテキストエディタで開きます。
com\android\internal\app\ShutdownThread.smali

「.method public static rebootOrShutdown(ZLjava/lang/String;)V」を検索。
その7行くらい下の「if-eqz p0, :cond_31」の下、「const-string v2, "ShutdownThread"」の直前に、処理を追加します。

.method public static rebootOrShutdown(ZLjava/lang/String;)V
    .registers 7
    .parameter "reboot"
    .parameter "reason"

    .prologue
    .line 487
    if-eqz p0, :cond_31

    .line 488
    const-string v1, "recovery"  #この行から追加

    invoke-virtual {p1, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v1

    if-eqz v1, :cond_01

    :try_start_01
    new-instance v1, Ljava/io/File;

    const-string v2, "/cache/recovery/boot"

    invoke-direct {v1, v2}, Ljava/io/File;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/io/File;->exists()Z

    move-result v2

    if-nez v2, :cond_01

    invoke-virtual {v1}, Ljava/io/File;->createNewFile()Z
    :try_end_02
    .catch Ljava/io/IOException; {:try_start_01 .. :try_end_02} :catch_01

    :catch_01
    :cond_01  #この行まで追加
    const-string v2, "ShutdownThread"

    new-instance v3, Ljava/lang/StringBuilder;

ここはまさに再起動する直前の部分になるのですが、再起動の理由が"recovery"だったときに/cache/recoveryに「boot」が存在すればスルー、無ければ作るという処理です。
以上、編集が済んだら上書き保存。

■android.policy.odex
android.policy.odexをbaksmaliした展開先の中で、以下のフォルダを探して開きます。
com\android\internal\policy\impl

電源メニューに「再起動」を追加した時に「GlobalActions$9.smali」を作ったと思いますが、さらにそれを複製して「GlobalActions$10.smali」にリネーム。テキストエディタで書き換えます。
ソース内に「GlobalActions$9」が3か所くらい存在していますが、それらをすべて「GlobalActions$10」 に書き換えます。

次に「.method public onPress()V」を検索(39行目あたり)
その11行くらい下(50行目あたり)の「const-string v1, "now"」を「const-string v1, "recovery"」に書き換えます。

    move-result-object v0

    const-string v1, "now"

    const/4 v2, 0x1

    invoke-static {v0, v1, v2}, Lcom/android/internal/app/ShutdownThread;->reboot(Landroid/content/Context;Ljava/lang/String;Z)V
↓↓↓
    move-result-object v0

    const-string v1, "recovery"  #変更

    const/4 v2, 0x1

    invoke-static {v0, v1, v2}, Lcom/android/internal/app/ShutdownThread;->reboot(Landroid/content/Context;Ljava/lang/String;Z)V

以上、書き換えたら上書き保存。

続きまして「GlobalActions.smali」に処理の追加です。
「.method private createDialog()Landroid/app/AlertDialog;」を検索。(394行目あたり)
その58行くらい下(452行目~458行目あたり)に、以前追加した、

    new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$9;

    const v2, 0x7f030000

    invoke-direct {v1, p0, v13, v2}, Lcom/android/internal/policy/impl/GlobalActions$9;-><init>(Lcom/android/internal/policy/impl/GlobalActions;II)V

    invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z

という部分があります。
この下に同じような感じで数行記述を追加し、以下のようにします。

    new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$9;

    const v2, 0x7f030000

    invoke-direct {v1, p0, v13, v2}, Lcom/android/internal/policy/impl/GlobalActions$9;-><init>(Lcom/android/internal/policy/impl/GlobalActions;II)V

    invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z

    new-instance v1, Lcom/android/internal/policy/impl/GlobalActions$10;  #追加

    const v2, 0x7f030001  #追加

    invoke-direct {v1, p0, v13, v2}, Lcom/android/internal/policy/impl/GlobalActions$10;-><init>(Lcom/android/internal/policy/impl/GlobalActions;II)V  #追加

    invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z  #追加

    .line 193
    iget-object v0, p0, Lcom/android/internal/policy/impl/GlobalActions;->mItems:Ljava/util/ArrayList;

これが電源メニューの「再起動」の下に「CWMで再起動」を追加する部分になります。

これも書き換えたら上書き保存。

■仕上げ
上記変更後、deodex_framework.jarとdeodex_android.policy.jarを生成し、external-res.apkも含めCWMモードで端末に送信、dexopt-wrapper等の作業を行いつつ、/system/frameworkのexternal-res.apkとframework.odexとandroid.policy.odexを置き換えてください。
reboot後、電源メニューに「CWMで再起動」が追加され、実行したら再起動後CWMが立ち上がることを確認してください。

0 件のコメント:

コメントを投稿