非Deodex環境 [SO-02C] でセルスタンバイ問題を解決する


AndroidでMVNOなデータSIMを使うと電界強度(アンテナピクト)が表示されなかったり、セルスタンバイで圏外時間が100%になってしまって電池の消費が激しくなるという問題があったのだけど、それを解決する方法をブローヴちゃん: Android + b-mobile データ専用 SIM で電界強度を表示するで発見したので、試してみました。

上記のページだとdeodexされた環境で逆アセンブルして変更という手法がとられていたけど、手元にあるXperia Acroは非deodex環境だったので、deodex化せずに変更したみたので書いてみた。

注意: rooted環境じゃないとそもそもこのHackは適用できません。いつものことですが、失敗したら確実に文鎮化します。

用意するもの

手順

  1. 実機から/system/frameworkを抜いてきます。
    $ adb pull /system/framework framework
  2. framework.odexframework.jarを作業ディレクトリにコピーします
    $ mkdir workspace
    $ cp framework/framework.odex workspace/
    $ cp framework/framework.jar workspace/
  3. framework.odexを逆アセンブルします
    $ baksmali --api-level 10 -d ../framework -c:core-junit.odex -x framework.odex

    -c:オプションには逆アセンブルに必要なクラスを適宜追加します。Xperia acro(SO-02C)ではオプションを指定しなかった場合、

    $ baksmali --api-level 10 -d ../framework -x framework.odex
    Error occured while loading boot class path files. Aborting.
    org.jf.dexlib.Code.Analysis.ClassPath$ClassNotFoundException: Could not find superclass Ljunit/framework/TestCase;
    at org.jf.dexlib.Code.Analysis.ClassPath$ClassDef.loadSuperclass(ClassPath.java:830)
    at org.jf.dexlib.Code.Analysis.ClassPath$ClassDef.(ClassPath.java:683)
    at org.jf.dexlib.Code.Analysis.ClassPath.loadClassDef(ClassPath.java:280)
    at org.jf.dexlib.Code.Analysis.ClassPath.initClassPath(ClassPath.java:163)
    at org.jf.dexlib.Code.Analysis.ClassPath.InitializeClassPathFromOdex(ClassPath.java:110)
    at org.jf.baksmali.baksmali.disassembleDexFile(baksmali.java:104)
    at org.jf.baksmali.main.main(main.java:293)
    Error while loading class Landroid/test/AndroidTestCase; from file framework.odex
    Error while loading ClassPath class Landroid/test/AndroidTestCase;

    こんな感じのエラーが出ました。(この場合AndroidTestCaseが足りないのでcore-junit.odexを追加します。)

  4. アンテナピクトの扱いを変更する
    逆コンパイルしたクラスファイルを編集します。基本的にはブローヴちゃんさんの手順通りですが、展開したoutフォルダにあるcom/android/internal/telephony/gsm/GsmServiceStateTracker.smaliを編集します。
    Xperia Acroでは以下のように変更するとうまくいきました。

    :pswitch_data_22
    .packed-switch 0x0
    :pswitch_20
    :pswitch_1f
    :pswitch_1f
    :pswitch_1f
    :pswitch_20
    :pswitch_1f
    :pswitch_5
    :pswitch_5
    :pswitch_5
    :pswitch_5
    :pswitch_20
    :pswitch_5
    :pswitch_1f
    :pswitch_1f
    :pswitch_20
    .end packed-switch

    ちなみに変更後と変更前でパッチを作りました。
    http://nunnun.jp/src/so-02c/GsmServiceStateTracker.smali.patch
    パッチとGsmServiceStateTracker.smaliを同一ディレクトリにおいた状態で、

    $ patch GsmServiceStateTracker.smali < GsmServiceStateTracker.smali.patch

    で適用できます。

  5. 編集したframework.odexをアセンブルします
    先ほど逆アセンブルを実行した作業ディレクトリに戻って、smaliを実行します。

    $ smali -o classes.dex out

    うまくいくとclasses.dexが作成されているはずです

  6. framework.jarを展開します
    jarファイルはzipファイルなので展開します

    $ unzip framework.jar -d framework_jar
    Archive:  framework.jar
    creating: framework_jar/META-INF/
    inflating: framework_jar/META-INF/MANIFEST.MF
    inflating: framework_jar/preloaded-classes
  7. classes.dexを追加します
    先ほどframework.jarを展開したディレクトリにコピーします。

    $ cp classes.dex framework_jar/
    $ ls -l framework_jar/
    total 14336
    drwxr-xr-x  3 hiro  staff      102 10 10 01:44 META-INF
    -rw-r--r--  1 hiro  staff  7269368  1 12 21:40 classes.dex
    -rw-r--r--@ 1 hiro  staff    65580 10 10 01:19 preloaded-classes
  8. framework.jarを再度生成します
    先ほどの逆でzipで固めます。

    $ zip ../framework.jar.new META-INF preloaded-classes classes.dex
    adding: META-INF/ (stored 0%)
    adding: preloaded-classes (deflated 82%)
    adding: classes.dex (deflated 56%)

    これでPC側での作業はおわり。

  9. 実機に必要なファイルをコピーします
    どこでもいいのですが、/data/local/tmpとかに新しく生成したframework.jar.newとダウンロードしたdexopt-wrapperを転送して、dexopt-wrapperを実行可能にします。

    $ adb push framework.jar.new /data/local/tmp/framework.jar.new
    2047 KB/s (3185980 bytes in 1.519s)
    $ adb push dexopt-wrapper /data/local/tmp/
    609 KB/s (5512 bytes in 0.008s)
    $ adb shell chmod 755 /data/local/tmp/dexopt-wrapper
  10. dexopt-wrapperを使ってjarをodexに変換する
    $ adb shell
    $ cd /data/local/tmp
    $ ls
    dexopt-wrapper
    framework.jar.new
    $ ./dexopt-wrapper framework.jar.new framework.odex
    --- BEGIN 'framework.jar.new' (bootstrap=0) ---
    --- waiting for verify+opt, pid=7612
    --- would reduce privs here
    --- END 'framework.jar.new' (success) ---
    $
  11. 署名をコピーする
    このままだと動かないのでオリジナルのframework.odexから署名部分だけコピーしてきます。

    $ adb shell
    $ cd /data/local/tmp
    $ busybox dd if=/system/framework/framework.odex of=framework.odex bs=1 count=20 skip=52 seek=52 conv=notrunc
    20+0 records in
    20+0 records out
    20 bytes (20B) copied, 0.004334 seconds, 4.5KB/s
    $ ls -l
    -rw-r--r-- shell    shell     7384328 2012-01-12 21:53 framework.odex
    -rwxr-xr-x shell    shell        5512 2009-05-30 23:15 dexopt-wrapper
    -rw-rw-rw- shell    shell     3185980 2012-01-12 21:42 framework.jar.new

    注意 必ずbusyboxddを使ってください。間違えると、conv option disabledというエラーが返ります。

  12. framework.odexを置き換える
    これはrecoveryとかで実施した方が安全です。
    /systemをrwで再マウントして、

    # cp /data/local/tmp/framework.odex /system/framework/framework.odex.new
    # mv /system/framework/framework.odex /system/framework/framework.odex.bak
    # mv /system/framework/framework.odex.new /system/framework/framework.odex
    # sync

    とかします。

やると意外と面倒でした。
いちおう元のframework.odexとパッチを当てて署名したframework.odexの差分を取ったパッチを作りました。

  • framework.odex.patch
    元のframework.odex MD5 (framework.odex) = 7b474a8d99ab92d4286d422cd6e1d511
    パッチ適用後: MD5 (framework_new.odex) = e3ea45b180e9e71bf39d665e4ca8b1ac
    こんな感じで適用できるはずです。
    $ bspatch framework.odex.bak framework.odex.new framework.odex.patch

間違っているところとかあったら指摘よろしくお願いします。

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

One thought on “非Deodex環境 [SO-02C] でセルスタンバイ問題を解決する

  1. acron

    こんにちは。
    SO-02C+bmobileu300を使っており不具合に困っていたところこのページにたどり着きました。参考にしながら何度も試してみているのですが、差し替え後にsonyロゴループに陥ってしまっています。直書き換えの手順見直しや、条件変更、差分ファイルも利用させてもらって試してもいるのですがうまくいきません。
    大変恐縮ですが、もしよろしければ書き換えたframework.odexをお借りすることはできないでしょうか?
    よろしくお願いします。

    Reply

Leave a Reply