IdeaPad A1の処理能力ではAndroid 4.0.4は重すぎ、画面タップのレスポンスが遅れまくり、プチフリを繰り返すため、やはりこの機器の当初バージョンであるAndroid 2.3.4に戻すことにする。
4.0.4へのアップグレードと使い心地については、『IdeaPad A1をAndroid 4.0.4 (ICS)にアップデートした使い心地』を参照
検証環境
- 機種 : Lenovo製 IdePad A1 , 16GBytes版 2228-3DJ
- 購入価格 : 16,907円 (2012年9月 Amazon.co.jp)
- CPU : OMAP 3622, シングルコア 1GHz
- メモリー : 512 MB RAM, 内蔵SDカード 16GB, microSDスロット×1
- 画面 : 1024 x 600 pixels, 7 inch
- 質量 : 400g
OSのアップデート
OSの書き換えは2種類の方法があり、(1)OSイメージを含んだブート可能なmicroSDカードを用いる場合、(2)IdeaPad本体のアップデート機構を利用して、microSDカードのOSイメージを読み込ませる場合、という2種類。
(1)の方法については、Lenovo公式サイトに記載されている方法『How to Unbrick fix/full factory restore - IdeaTab A1 and A1107』で、同サイトからブート可能なmicroSDイメージも入手できる。
もうひとつは、Lenovo公式サイトの「OSイメージ配布場所」よりOSイメージのzipファイルを入手して、それをmicroSDカードに単純にファイルコピーして使う。
今回は、(2)の方法を試してみることとする。
OSイメージのダウンロードと、パッチ適用
Lenovo公式サイトの「OSイメージ配布場所」より次のファームウエアをダウンロードする。なお、各種言語版が配布されているの、今回は末尾がROW (= rest of world の略) のものをダウンロードする。
A107W0_A234_001_015_2643_ROW.zip 27-Feb-2012 05:27 160M
公式サイトでは、これをmicroSDカードにupdate.zipと改名して書き込んで、OTAでアップデートできるとされているが、Android 4.0.4の時に起動時に固まってしまう不具合があったため、次のサイトに示されているようにパッチを当てる必要がある。
『Update – Lenovo(R) IdeaPad A1-07 (16GB) + Android(TM) 4.0.4 (Ice Cream Sandwich)』
『Lenovo(R) IdeaPad A1-07 (16GB) + Android(TM) 4.0.4 (Ice Cream Sandwich AKA ICS)』
具体的には、上記のサイトよりダウンロードしたパッチ・ファイル updater-script.a234.patch を、OSイメージzipの中のMETA-INF/com/google/android/updater-scriptに適用して書き戻してやれば良い。コマンドラインでは次のようになり、
$ wget http://download.lenovo.com/slates/a1/OTA/A107W0_A234_001_015_2643_ROW.zip $ unzip A107W0_A234_001_015_2643_ROW.zip $ patch META-INF/com/google/android/updater-script updater-script.a234.patch $ zip -r update * -x updater-script.a234.patch update.zip
実際にパッチを当てたupdater-scriptは次のようになっている。元のファイルは2GB, 16GB版それぞれの処理が全てコメントアウトされているので、該当機種のものを生かしてやるという処理のようだ
念の為、それぞれのファイルをここに置いておく : updater-script.a234.patchをダウンロードする。 updater-scriptをダウンロードする。 元のupdater-scriptをダウンロードする。
#updater-script.a234
ui_print("");
ui_print("1. extract fuse");
assert(show_progress(0.010000, 1));
assert(package_extract_file("fuse", "/tmp/fuse"));
assert(set_perm(0, 0, 0755, "/tmp/fuse"));
assert(package_extract_file("mg_up", "/tmp/mg_up"));
assert(set_perm(0, 0, 0755, "/tmp/mg_up"));
assert(set_progress(0.010000));
# This choose which mbr to use
ui_print("2. fuse mbr.img");
assert(show_progress(0.010000, 1));
#ui_print("#. choose mbr.");
#assert(package_extract_file("mbr2GB.img", "/tmp/mbr2GB.img"));
assert(package_extract_file("mbr16GB.img", "/tmp/mbr16GB.img"));
#ifelse(is_16Ginand("/dev/block/mmcblk0"),assert(run_program("/tmp/fuse", "mbr", "/tmp/mbr16GB.img")),assert(run_program("/tmp/fuse", "mbr", "/tmp/mbr2GB.img")));
assert(run_program("/tmp/fuse", "mbr", "/tmp/mbr16GB.img"));
#ifelse(is_16Ginand("/dev/block/mmcblk0"),ui_print("fuse mbr 16GB"),ui_print("fuse mbr 2GB"));
ui_print("fuse mbr 16GB");
#delete("/tmp/mbr2GB.img");
delete("/tmp/mbr16GB.img");
#ui_print("#. out off choose mbr.");
assert(set_progress(0.020000));
#ui_print("*. **********************");
#assert(package_extract_file("Install.sh", "/tmp/Install.sh"));
#assert(run_program("/tmp/Install.sh","",""));
#delete("/tmp/Install.sh");
#ui_print("*. **********************");
ui_print("3. format partitions");
assert(show_progress(0.450000, 60));
assert(run_program("/tmp/fuse", "system", "format"));
assert(run_program("/tmp/fuse", "cache", "format"));
assert(run_program("/tmp/fuse", "userdata", "format"));
assert(run_program("/tmp/fuse", "inand-secure", "format"));
assert(run_program("/tmp/fuse", "inand-storage", "format"));
# This segment is masked when inand is invalid
ui_print("4 fuse mbr_boot");
assert(show_progress(0.010000, 1));
assert(package_extract_file("mbr_boot", "/tmp/mbr_boot"));
assert(run_program("/tmp/fuse", "mbr_boot", "/tmp/mbr_boot"));
delete("/tmp/mbr_boot");
assert(set_progress(0.030000));
ui_print("5. fuse xloader");
assert(show_progress(0.020000, 3));
assert(package_extract_file("MLO", "/tmp/MLO"));
assert(run_program("/tmp/fuse", "xloader", "/tmp/MLO"));
delete("/tmp/MLO");
assert(set_progress(0.590000));
ui_print("6. fuse u-boot.bin");
assert(show_progress(0.020000, 3));
assert(package_extract_file("u-boot.bin", "/tmp/u-boot.bin"));
assert(run_program("/tmp/fuse", "uboot", "/tmp/u-boot.bin"));
delete("/tmp/u-boot.bin");
assert(set_progress(0.590000));
ui_print("7. fuse uImage.img");
assert(show_progress(0.030000, 5));
assert(package_extract_file("uImage", "/tmp/uImage"));
assert(run_program("/tmp/fuse", "kernel", "/tmp/uImage"));
delete("/tmp/uImage");
assert(set_progress(0.620000));
ui_print("8. fuse ramdisk_mmc.img");
assert(show_progress(0.030000, 5));
assert(package_extract_file("ramdisk-uboot.img", "/tmp/ramdisk_mmc.img"));
assert(run_program("/tmp/fuse", "ramdisk", "/tmp/ramdisk_mmc.img"));
delete("/tmp/ramdisk_mmc.img");
assert(set_progress(0.650000));
ui_print("9. fuse recovery_mmc.img");
assert(show_progress(0.030000, 5));
assert(package_extract_file("recovery_mmc.img", "/tmp/recovery_mmc.img"));
assert(run_program("/tmp/fuse", "recovery", "/tmp/recovery_mmc.img"));
delete("/tmp/recovery_mmc.img");
assert(set_progress(0.680000));
ui_print("10. fuse logo.img");
assert(show_progress(0.030000, 5));
assert(package_extract_file("logo.img", "/tmp/logo.img"));
assert(run_program("/tmp/fuse", "logo", "/tmp/logo.img"));
delete("/tmp/logo.img");
assert(set_progress(0.680000));
ui_print("11. fuse system.img");
assert(show_progress(0.300000, 50));
assert(package_extract_file("system.zip", "/tmp/system.zip"));
assert(run_program("/tmp/fuse", "system", "/tmp/system.zip"));
delete("/tmp/system.zip");
assert(set_progress(0.700000));
ui_print("12. fuse data.img");
assert(show_progress(0.020000, 50));
assert(package_extract_file("data.zip", "/tmp/data.zip"));
assert(run_program("/tmp/fuse", "userdata", "/tmp/data.zip"));
delete("/tmp/data.zip");
assert(set_progress(0.800000));
#ui_print("11. upgrade CAP touch");
#assert(show_progress(0.020000, 0));
#assert(package_extract_file("pixcir_fw.pix", "/tmp/pixcir_fw.pix"));
#assert(run_program("/tmp/fuse", "pixcirfw", "/tmp/pixcir_fw.pix"));
#delete("/tmp/pixcir_fw.pix");
assert(show_progress(0.30000, 50));
ui_print("13. backup data.img");
assert(mount("ext3","/dev/block/mmcblk0p1","/tmp/system"));
assert(package_extract_file("data.zip", "/tmp/system/data.zip"));
assert(unmount("/tmp/system"));
assert(set_progress(0.850000));
assert(run_program("/tmp/fuse", "inand-storage", "format"));
ui_print("14. mg_up mga.mga");
assert(show_progress(0.002000, 50));
assert(package_extract_file("mga.mga", "/tmp/mga.mga"));
assert(run_program("/tmp/mg_up", "/tmp/mga.mga"));
delete("/tmp/mga.mga");
#assert(set_progress(0.900000));
assert(set_progress(0.900000));
delete("/tmp/fuse");
assert(set_progress(1.000000));
ui_print("15. Upgrade finish...");
このようにして出来たOSイメージファイル(update.zip)を、FAT32で普通にフォーマットしたmicroSDカードに書き込む。(dd コマンドでイメージ書込するのではなく、cp コマンドでファイルコピーする)
IdeaPad A1の電源を切り、「ボリューム・ダウン・ボタン」と「電源ボタン」を同時に押したままにして電源を入れ、“Lenovo”ロゴが出たら「電源ボタン」のみ手を離し、「ボリューム・ダウン・ボタン」はOSイメージzipが読み込まれる画面になるまで押したままにする。

ideapad A1 のファームウエア書き込み中画面
書き込みが終われば、画面中央が緑色の「チェック」印に切り替わり、電源が自動的に切れる。
Android 2.3.4インストール後の画面

アプリ・ドロワー2ページ目 (ルート権限奪取後 Superuserアプリが登録された状態)
ルート権限の奪取
『Trash 915 何か - 2643_ROW用』に掲載されているpatch-rooted_signed.zipを、フォーマットしたmicroSDカードに書き込み、OSのアップデートの時と同じく、「ボリューム・ダウン・ボタン」と「電源ボタン」を同時に押したままにして電源を入れ、“Lenovo”ロゴが出たら「電源ボタン」のみ手を離し、「ボリューム・ダウン・ボタン」はOSイメージzipが読み込まれる画面になるまで押したままにする。
アプリ・ドロワーにSuperuserアプリが登録されていれば、成功している。
不要アプリの無効化
| パッケージ名 | アプリ名 等 |
|---|---|
| cl1.fuhui | Lenovo バックアップツール |
| cl1.fuhui.com | Lenovo バックアップツール |
| cl1.sdka | Lenovo バックアップツール |
| com.amazon.kindle | Amazon Kindle |
| com.android.inputmethod.pinyin | 中国語IME |
| com.android.launcher | Lenovo ランチャー(ホームアプリ) |
| com.cooliris.media | ギャラリー |
| com.ebuddy.android | eBuddy メッセンジャー |
| com.foxconn.download.ftp | Lenovo OTAアップデート ※ |
| com.google.android.talk | Google ハングアウト |
| com.lenovo.leos.userhelp | Lenovo ユーザーガイド |
| com.mobihand.cds | |
| com.mobihand.inapppurchase | |
| com.mobihand.skylight | Lenovo App Shop |
| com.osa.android.navdroyd | NavDroyd |
| lenovo.jb.gokeyboard | Lenovo Go Keyboard IME |
※ OTAアップデートは、今後IdeaPad A1の新OSが公開されオンラインでアップデート (設定 − タブレット情報 − システムアップデート)でアップデートしないため、不要と判断。
apkファイルを削除して/systemの容量を増やしたい場合
確実に使わないとわかっているものは、パッケージの「無効化」ではなく「削除」を行える。まず、パッケージを無効化pm disable クラス名してから、通常通り削除できないか試してみる
# pm disable com.mobihand.skylight
# pm uninstall com.mobihand.skylight
Failure
通常通り削除できないのであれば、強制的にパッケージファイルを削除し、パッケージ管理のXMLファイル/data/system/packages.xmlからも痕跡を削除する。
# mount -o remount,rw /system /system ← まず読み書き可能で再マウント (起動後1回で良い)
# pm path com.mobihand.skylight
package:/system/app/LenovoAppShop.apk
# rm /system/app/LenovoAppShop.apk
パッケージファイルごと消したのは、次のファイル
| クラス名 | ファイル名 | アプリ名 等 |
|---|---|---|
| cl1.fuhui | BackupI.apk | Lenovo バックアップツール |
| cl1.fuhui.com | BackupII.apk | Lenovo バックアップツール |
| cl1.sdka | SDcard.apk | Lenovo バックアップツール |
| com.android.inputmethod.pinyin | PinyinIME.apk | 中国語IME |
| com.android.launcher | Launcher2.apk | Lenovo ランチャー(ホームアプリ) |
| com.mobihand.cds | CDS_b118.apk | |
| com.mobihand.inapppurchase | MobiHandBillingService.apk | |
| com.mobihand.skylight | LenovoAppShop.apk | Lenovo App Shop |
cl1.fuhui や cl1.sdka は、Google検索でも招待が判明しなかったが、パッケージファイルを取り出して中身を確認すると、中国語で変数名を定義したバックアップツールだった。中国語のは全部消しても大丈夫ですよね…(笑 。 Lenovo ランチャーは2メガバイトもあるため、迷わず削除。
パッケージ管理ファイルで削除するのは、<package>タグで囲まれた次のような範囲になる。
〜 略 〜
<package name="com.android.calculator2" codePath="/system/app/Calculator.apk" nativeLibraryPath="/data/data/com.android.calculator2/lib" flags="1" ft="135606f95a0" it="135606f95a0" ut="135606f95a0" version="10" userId="10029">
<sigs count="1">
<cert index="6" key="3082 ... fd04" />
</sigs>
</package>
<package name="com.mobihand.cds" codePath="/system/app/CDS_b118.apk" nativeLibraryPath="/data/data/com.mobihand.cds/lib" flags="1" ft="135606f95a0" it="135606f95a0" ut="135606f95a0" version="118" userId="10037" enabled="false">
<sigs count="1">
<cert index="1" />
</sigs>
</package>
<package name="org.mozilla.firefox" codePath="/data/app/org.mozilla.firefox-1.apk" nativeLibraryPath="/data/data/org.mozilla.firefox/lib" flags="0" ft="14c31b48380" it="14c31b4a815" ut="14c31b4a815" version="2015031400" sharedUserId="10061">
<sigs count="1">
<cert index="7" key="3082 ... 0a9ce" />
</sigs>
<perms />
</package>
〜 略 〜
/systemの空き領域がどれだけ増えたか…
Lenovo製アプリをせっせと消して、500kBytes程度だった空きが、39MBytesにまで広がりました。
# df
Filesystem Size Used Free Blksize
/dev 242M 32K 242M 4096
/mnt/asec 242M 0K 242M 4096
/mnt/obb 242M 0K 242M 4096
/system 277M 237M 39M 1024
/cache 184M 5M 179M 1024
/data 1G 394M 1G 4096
/.secure 32M 4M 27M 1024
/mnt/sdcard 12G 9M 12G 4096
画面解像度(dpi)の変更
設定ファイル /system/build.prop内にro.sf.lcd_density=240というdpi設定箇所があるので、ここを変更する。 作業の前に /system ディレクトリを読み書き可能になるよう再マウントを行う
# mount -o remount,rw /system /system
# ls -l /system/build*
-rwxrwxrwx root root 2492 2012-02-09 13:47 build.prop ← 属性は 0777
下記の変更前、元のbuild.propをダウンロードする。
〜 略 〜
# system.prop for A1_07
# This overrides settings in the products/generic/system.prop file
#
rild.libpath=/system/lib/libsierra-ril.so
rild.libargs=-d /dev/ttyUSB2
ro.sf.lcd_density=240
com.ti.omap_enhancement=true
opencore.asmd=1
keyguard.no_require_sim=1
wifi.interface=eth0
alsa.mixer.playback.master=DAC2 Analog
alsa.mixer.capture.master=Analog
#ro.media.dec.aud.wma.enabled=1
#ro.media.dec.vid.wmv.enabled=1
dalvik.vm.heapsize=64m
ro.opengles.version=131072
〜 略 〜
ちなみに、Android 4.0.4のファームウエアでは、ro.sf.lcd_density=160となっており、今回はro.sf.lcd_density=200に設定してみた。デフォルトの240dpiと、変更後の200dpiの違いは次のような感じだ
個人的には、もう少し大きめの文字の210dpiくらいかなぁ…
同期が停止しないエラー
このエラーが発生したので初期化したわけだが、この不具合は初期化しても直っていない。暫定的な対応としては、設定 − アカウント より、全てのアカウントで「同期をキャンセル」を選択すれば良い

設定 − アカウント で、メニューを表示して「同期をキャンセル」を実行する。
この状態を放っておくと、CPUビジー状態のままで急速にバッテリーが消耗することになる。
この画面で、「スリープなし」に青いバーが表示されている場合は、スリープに入っていないことになる。同期エラーが出続けているときは、スリープできないのでバッテリーが急速に消耗する。
根本的な問題解決方法は、こちら → 『(Android 2.3.4) YouTube同期が終了せずバッテリーが異常消耗する』
Xposedの導入
Android 4.0以降を対象としたXposedが、2.3.4 Gingerbread向けにバックポートされたものがある。動作保証はされていないと思うが、私が使っているモジュールでは特に問題は起こっていない
公式ページ : Xposed back-ported to Gingerbread (update to 2.6.1)
ここで配布されている XposedInstaller-2.6.1-gb-p5.apk をインストールし、さらにAndroid 2.3.4に対応したモジュール一覧は公式ページに掲載されているXMLで見ることができる。
いろいろ便利なツールがあると思うが、何分研究不足で、下記のCool Toolのみをインストールして使っている。
Cool Tool
ステータスバーにCPU負荷やバッテリー残量、ネットワーク転送量などの数値やグラフを表示するツール。公式ページとFAQ。
デバッグ接続のアイコンが被ってしまっているが、情報表示位置は自在に変更できる。(自動的に逃げてくれるということはないようだ…)











