たくさんの自由帳

NewRadioSupporter でキャリアアグリゲーションを表示する実験

投稿日 : | 0 日前

文字数(だいたい) : 6760

どうもこんにちは、
モックし忘れたテストコードをGitHub Actionsで動かした結果、固まって4時間動いてたので流石に止めました。いつもは数分。

Imgur

あぶね~従量課金だったら泣いてた。

本題

4G/5G キャリアアグリゲーションEN-DC アンカーバンド情報を表示するアプリをオープンテスト版に公開しています、
期待通りに動けばこうなります。

Imgur

Imgur

Imgur

Imgur

年末 2023 まとめの記事で一瞬触れたあれです。
この時点で既にキャリアアグリゲーションに関連するAPIを突き止めていて、、、ただこれは維持するのが厳しいなあって、代替案を探していた頃です。
オープンテスト版があるってことはギリギリ許容できる代替案があったという事ですね(自分で言うのか・・・)

ダウンロードと使い方

https://play.google.com/store/apps/details?id=io.github.takusan23.newradiosupporter

NewRadioSupporterのオープンテスト版のをダウンロードしてみてください。
多分一部の端末でしか動かないのでとりあえずはオープンテスト版として公開しました。誰でも参加できるはずです。

が、が、が
端末によっては動きません。し、動いた所で正しい情報が表示されているかも怪しいです。
割に合わないと思います。転用5G / sub6 / mmWaveの判定やNSA/SAの判定ができれば良い場合は何もしなくて良いと思います。

オープンテスト版をインストールしたら、パソコンを用意してADBコマンドを利用できる環境を揃えてください。
これは、普通のサードパーティアプリでは4G/5G キャリアアグリゲーション情報にはアクセス出来ないため、特殊な権限を利用します。
これにはADBコマンドを入力しないと付与できないためです(普通にダイアログで許可するとかではない)。。

これが打ち込むべきコマンドです。
NewRadioSupporter(アプリケーションID)へ、READ_LOGS権限を付与(grant)しろ。というコマンドになります。

adb shell pm grant io.github.takusan23.newradiosupporter android.permission.READ_LOGS

コマンドを入力した後、アプリを起動すると、「デバイスログへのアクセスを許可しますか?」と聞かれるので「一回限りのアクセスを許可」を選んでください。
これで、冒頭の通り、端末が対応していれば表示されるかもしれません。

ADB コマンドを実行できる環境がない場合は、
MuntashirAkon/AppManagerのアプリ(ADB モードワイヤレスデバッグ)や、
aShell YouShizuku)を使えばパソコンなしでも権限を付与できるかもしれません。

Imgur

Imgur

長年の夢?

どうやら5Gでもキャリアアグリゲーション出来るらしい。複数の5Gのバンドに接続するとかそういう話らしい?
cellmappersubredditとかを見ている限り確かに、n257が複数見えてるスクショがある。

どうにかroot 無し環境下で見れないか調べていたところ、
*#*#4636#*#*した時の画面の物理チャンネル構成に表示されている情報が、4G/5G キャリアアグリゲーション情報っぽいところまで突き止めました。

他にも関連しそうなAPIがあるのですが、
信頼度がなかったり(CellInfo#getCellConnectionStatus)(これを正しく実装してない会社あり)、
欲しい情報がなかったりで(ServiceInfo#getBandwidths)(帯域幅でバンドが取れない)

物理チャンネル構成もサードパーティアプリは取得できない

ちなみに今のオープンテスト版ではこれを無理やり取得してます。
だからよくわからないADB コマンドを叩く必要があったのです。

物理チャンネル構成の表示に使われているのが、PhysicalChannelConfig APIですが、これは正攻法では取得できません。
なぜならプリインストールアプリ限定権限で保護されているからです。サードパーティアプリでは利用できません。
ただAPIが隠されているだけならまだしも、権限で保護されてると厳しいです。

サードパーティでも取得する2つのルート

サードパーティでも取得できる手段、探した限り2つありそう。
ただ、どっちも険しい道。 代替案があるだけマシ、、、

ログを傍聴して取得する

PhysicalChannelConfig、どうにか抜け道がないかCode SearchAOSPを読んでいたところ、取得したらLogcat流している(出力している)ことを見つけました。
普通のLogcatではなく、無線に関係するlogcat -b radioの方です!!

https://cs.android.com/android/platform/superproject/main/+/main:frameworks/opt/telephony/src/java/com/android/internal/telephony/NetworkTypeController.java;drc=0a5870fa06c7144c950ec906f5b4acfc6f2ff165;l=1452

Logcatに流してるから何だよという話ですが、
Logcatを読み取る権限はサードパーティアプリでも ADB コマンドを使えば付与することが出来ます。
これです。

<uses-permission android:name="android.permission.READ_LOGS" />

冒頭のようなADB コマンドを叩けば、サードパーティアプリでもLogcatを取得することが出来るので、
PhysicalChannelConfigの結果が流れてくるのを待ち受けることが出来るようになったわけです。

今のオープンテスト版ではこれを採用しています。メリットとしては。

  • 使う側
    • ADB コマンドを一度打ち込めば良い
  • 開発側
    • 標準ライブラリだけで作れる
      • logcat読み出すのはexec()すればいい

デメリットとしては

  • 使う側
    • 毎回ダイアログを許可しないといけない
      • サードパーティアプリの宿命
  • 開発側
    • 正規表現でログから取り出す必要がある
      • AIに聞けばなんとかなる
    • ログから消えたら詰む

Shizuku を使う

Shizukuという一部のプリインストールアプリ権限で保護されている API を代わりに叩いてくれるアプリがあります。
どういうことかというと、adbコマンドって結構いろんな事が出来るわけですが。

有名どころではプリインストールアプリの無効化なんてサードパーティでは出来ませんが、adbコマンドを叩けば出来ます。
冒頭で話した特殊な権限の有効化だってadbなら出来る場合があります。

Shizukuはこのadbにある強力な権限をアプリ開発者にもたらしてくれました。
どういう事かというと、adbが代わりにAPIを叩いてくれます。先述の通りadbコマンドには強力な権限があるため、
プリインストールアプリ限定のAPIをサードパーティアプリから(adbを経由することで)叩くことが出来ます。

ちなみにadbに付与されている権限はこれです。
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/Shell/AndroidManifest.xml

android/dataだってShizukuを経由すれば見ることが出来るし、
中華スマホとかを追いかけている方ならワンちゃん知ってるかもですが、root 無しVoLTE有効化するアプリも、このShizukuを使っています。 (というかサードパーティじゃそんな事できんやろって思って見てたらShizuku知った)

Shizukuを使ってPhysicalChannelConfigを取得してみるアプリも試しに作ったり(ソースコードからビルドする必要がありますが)
https://github.com/takusan23/ThirdpartyPhysicalChannelConfig

このメリットですが、

  • 使う側
    • 毎回ダイアログが出ない(ログを見ているわけじゃないので)
  • 開発側
    • 正規表現で文字列を処理しなくて済む

デメリットとしては

  • 使う側
    • 端末を再起動するとShizukuを再度有効化しないといけない
      • 仕方ない
      • Wi-Fi かパソコンのどっちかが必要で、電波測定は屋外で使うはず。
      • 外出た後に有効化し損ねたらかなしい
  • 開発側
    • 後述

ただ、開発的に前者のほうが良いかなあって、(プリインストールアプリ API を叩けるのに文句を言うなという話ではあるのですが

まずはAOSPと同じようにAPIを叩く必要があります。AOSPのコードを読む必要があるということです。
https://github.com/RikkaApps/Shizuku-APIREADMEにもありますが、
getSystemService()で取得したManagerにある関数呼び出しをShizuku経由にしたい場合、その関数の中身のコードを読んで、Shizukuを使うように作る必要があります。

Shizukuを経由したAndroid API呼び出しはこんな感じになります。
これらは電波関連の APIですが、本来であればTelephonyManagerが内部でよしなにやってくます。
が、呼び出しをShizuku経由にするため、TelephonyManagerが代わりにやってくれた処理を、AOSPを元に読み進める必要があります。READMEの通りですね。
狙いの関数の中身を読んで、Serviceを呼び出している部分をShizukuのものに差し替える。

本来は内部でよしなにやってくれるので、このコードは隠し API扱いです。よってAndroid Studioからは見つけることが出来ません。
これが次の理由になります。

val telephony: ITelephony
    get() = ITelephony.Stub.asInterface(
        ShizukuBinderWrapper(ServiceManager.getService("phone"))
    )
 
val telephonyRegistry: ITelephonyRegistry
    get() = ITelephonyRegistry.Stub.asInterface(
        ShizukuBinderWrapper(ServiceManager.getService("telephony.registry"))
    )
 
val subscription: ISub
    get() = ISub.Stub.asInterface(
        ShizukuBinderWrapper(ServiceManager.getService("isub"))
    )

次に、Android Studioからダウンロードするandroid.jarAndroid SDK)は、隠しAPIが削除された状態になっています。
が、Shizukuを利用して隠し APIを叩きたいので、隠し APIが残っているandroid.jarに差し替える必要があります。
もしテストを、GitHub Actionsとかでやっている場合は、CI/CD 環境android.jarも差し替える必要があり、とても大変。

優しいことに既にビルド済みのandroid.jarがあるので、それに差し替えることで、隠し APIAndroid Studioのコード補完に表示されるようになります。
https://github.com/Reginer/aosp-android-jar


最後、いくつかライブラリを入れる必要があります。
隠し APIを叩くためのライブラリと、Shizuku APIですね、これは特に言うこと無いです、文字通りです。

Android一部の隠し APIをリフレクションを使って叩こうとしても、メソッドが存在しない例外をスローするように対策されてしまいました。
確かにAOSPには存在するのに、実行すると落ちてしまう。

この制限はライブラリを入れることで、回避することが出来ます。
https://github.com/LSPosed/AndroidHiddenApiBypass

それはそれとして

Shizukuは手間を掛けてもなおプリインストールアプリ権限が必要な API を叩くことが出来るので、やる価値はバッチリあります。夢がある話です。

だってこの辺面白そうじゃん、
https://github.com/timschneeb/awesome-shizuku

いつかShizukuを使ってアプリを作りたいですね。その時は記事にでも!

ログから取り出している部分

experimentalブランチのこの辺、オープンテスト版なんで特にテストとかは書いてないです。
https://github.com/takusan23/NewRadioSupporter/blob/experimental/app/src/main/java/io/github/takusan23/newradiosupporter/tool/LogcatPhysicalChannelConfig.kt

おわりに

UIも少し変わってます。
eSIM / 物理 SIMどっちなのか、が取得できるので表示できるようにしてみました。

これが採用版の下書き、Material 3というか、リストの頭とおしりは角が丸くて、
リストの間というかセパレーターの角は控えめな丸にするやつ、やってみたかった。

Imgur

あ、没 Figma デザイン案、置いておきます

Imgur

おわりに2

なんでオープンテスト版から始めたかというと、READ_LOGS権限をいきなり投入したら、GooglePlayになにか言われるんじゃないかとか、怪しまれそうとか、で、
(全然動かない等で)不評ならさっさと撤退しようと思って。

Imgur

手持ちの端末でもGoogle Pixelぐらいしか動いてなさそう雰囲気、、、

おわりに3

  • Sub6-CA
  • NR-DC

これなにが違うの...
NSA/SAの違いってこと?

おわりに4

ちなみにPhysicalChannelConfig APIをサードパーティアプリに開放してくれってIssue Trackerに投げてみましたがダメでした。
ん~~~どうにかしてほしいなあ

年に1度(2回になるけど)のAndroidアップデートのAPI 差分を、ダメ元で開放されてないか更新の度に見る生活を続けますかね。