⚡️Power Struggle
USB-Cで繋いだ相手とゲームをプレイし、勝ったほうが充電を奪える綱引きゲーム
終電間際にお互いにバッテリーが残り10%でこのままだと両方帰れない状況、せめてどちらかでも確実に帰れるように相手の充電を奪いたいと思ったことありますよね。Power Struggleは、勝ったほうが相手の充電を奪えるミニゲームです。

USB Power Deliveryの給電仕様を悪用し、USB Type-Cケーブルでつないだ2台のスマートフォン間で物理的に電力を奪い合えるようにしました。アプリを開いて対戦を開始。画面をタップ連打すると、より多くタップしているほうが相手から充電を奪えます。連打でリードを奪うと、USB-PDのSource(給電)とSink(受電)のロールがスワップします。
ちなみに実際使うと給電側は1500mAぐらいの勢いで消費されるのに対し、受電側は400mA程度でしか受け取れません。(ゲームの処理に消えてるのでしょう。)
仕組み
スマホのUSB-Cポートは、給電する側にも受電する側にもなれます。2台をケーブルでつなぐと、USB Power Deliveryという規格でどちらが給電するかを決めます。この規格には、給電と受電の役割を入れ替える仕組みもあります。Androidの設定にある「接続したデバイスを充電」は、まさにこの機能です。
Power Struggleは、この入れ替えをゲームの中から行います。本来は特別な権限がないとできない操作なので、開発者のデバッグ接続と同じ権限をほかのアプリに与えるShizukuというアプリを使い、システムコマンド(dumpsys usb set-port-roles)を実行しています。rootは不要です。入れ替えは2台の間のやりとりで、もう片方は要求を受け入れるだけなので、この準備が必要なのは片方のスマホだけです。入れ替えは約0.5秒で終わり、その後は約4.5Wの電力が逆向きに流れます。
またゲームのデータも同じケーブルで送っています。ゲームを動かす側のスマホがUSBの「ホスト」になり、相手をAndroid Open Accessoryモードに切り替えます。もともとカーナビやドック向けに作られたプロトコルで、これで2台の間にタップやゲームの状態をやりとりする通信路ができます。USBでは電力の向きとデータの向きが独立しているので、給電の向きが入れ替わっても通信は切れません。

