2013年12月21日土曜日

データ専用SIMでCell IDをわかるようにする

日本通信などのようにSMSも音声通話もついていないデータ通信専用SIMをandroidで使うと、
  1. アンテナピクトが立たない
  2. セルスタンバイが異常に電力を消費しているように見える
  3. セルID (携帯基地局のID)がアプリにわからなくなり位置情報が不正確になる
という問題がある。android 4.4ではついに上記の問題がすべて解決されているが、今度は設定→電池→セルスタンバイで詳細を見ると、圏外時間が100%になっているように見えるという新しいバグが生じている。android 4.03から4.3ではXposed(要root)モジュールのドコモSIMパッチャーを使うと上記の1と2は解決する。3については解決しない機種もある(例えばnexus 4)。

電話アプリから *#*#4636#*#* と入力して出てくる隠しメニューで携帯電話情報→CellInfoListRateを押すとセル情報の中にセルIDが表示されている場合、携帯電話自体はセルIDを認識しているがソフトウェアのどこかがアホなのでアプリのセルIDを伝えることが出来ていない。その場合、android 4.3の場合は
GsmCellLocation mNewCellLoc = (GsmCellLocation) getObjectField(param.thisObject, "mNewCellLoc");
List<CellInfo> mLastCellInfoList = (List<CellInfo>) getObjectField(param.thisObject, "mLastCellInfoList");
if (mLastCellInfoList.size() > 0) {
    CellIdentityWcdma ci = (CellIdentityWcdma)callMethod((CellInfoWcdma)(mLastCellInfoList.get(0)), "getCellIdentity");
    if (ci.getCid() != -1) {
callMethod(mNewCellLoc, "setLacAndCid", callMethod(ci, "getLac"), callMethod(ci, "getCid"));
callMethod(mNewCellLoc, "setPsc", callMethod(ci, "getPsc"));
    }
}
というコードをドコモSIMパッチャーに追加して、セルID情報をアプリがアクセスする変数に移してあげるとandroidアプリがセルIDをわかるようになることもある。上記の変更を施したjavaソースをここに置く。コンパイルしてAPKにしたものをここに置く。注意事項:
  • 2013年12月21日にAPKを更新し、繋がっているのにcell IDが表示されないことがある問題をcom.android.internal.telephony.gsm.GSMPhone:getCellLocation()もhookすることで対応した。
  • 上に置いたAPKだけインストールしても何も起きない。まずrootを取ってxposed frameworkをインストールして使えるようにしてから、上に置いたAPKをインストールしてxposed frameworkを起動してドコモSIMパッチャーを有効にして下さい。
  • LTEと2G GSMにも対応しているはずだがテストする環境が無いからテストできていない。上記のコードはWCDMA決め打ちだが実際のソースコードとAPKは決め打ちしていない。
  • Android 4.3でしか効果はない。Android 4.4はデータ専用SIMでもセルIDがアプリに渡されるからこのxposedモジュールは不要。Android 4.2.2以下では関数名や変数名を変更しないといけないが、テストする環境が無いのでAndroid 4.2.2以下用のコードは何もいじっていない。
  • 上記のJAVAソースからAPKをコンパイルして作る場合、ドコモSIMパッチャーの2013年7月26日版のソースコードのjavaファイルを置き換えて、AndroidManifest.xmlのminSdkVersionを18に増やして下さい。

この件は作者の方に以下のようにGoogle+投稿のコメント欄にて連絡済みです。


これ以上プログラムのロジックをいじる必要は無いと思うが、ご意見ありましたら以下のコメント欄などでお知らせ下さい。