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。
デバッグ接続のアイコンが被ってしまっているが、情報表示位置は自在に変更できる。(自動的に逃げてくれるということはないようだ…)