2020年3月2日のアップデート以降Android(Pixel4)でカメラ無音化アプリが機能しない

作成: 2020年03月28日

更新: 2021年03月16日

Pixel4 の3月2日のアップデート

3月2日Pixel4がビルド番号QQ2A.200305.003にアップデートされ、目玉機能であるMotion Senseに音楽停止/再生機能が追加されるなどした。
Google製スマホ「Pixel」シリーズの新機能追加アップデート「feature drops」第2弾が配信開始
しかしその裏で既存のカメラ無音化アプリがことごとく機能しなくなっていた。

原因

既存のカメラ無音化アプリはほとんどがAudioManager.setMasterMuteという関数を用いてスマートフォンのすべての音を消し、カメラ無音化を実現していた。
setMasterMute(911行目あたり)
この関数はhiddenというアノテーションがされていて通常呼び出すことはできないがリフレクションという手法により強引に呼び出すことができていた。
しかしアップデート以降この関数を呼び出すと以下のようなエラーがでるようになった。

W/System.err: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.banatech.app.no_shutter_sound_camera.MainActivity.reflectSetMasterMute(MainActivity.kt:46)
        at com.banatech.app.no_shutter_sound_camera.MainActivity.offMuteAllVolume(MainActivity.kt:34)
        at com.banatech.app.no_shutter_sound_camera.MainActivity.access$offMuteAllVolume(MainActivity.kt:13)
        at com.banatech.app.no_shutter_sound_camera.MainActivity$onCreate$1.onCheckedChanged(MainActivity.kt:24)
        at android.widget.CompoundButton.setChecked(CompoundButton.java:180)
        at android.widget.Switch.setChecked(Switch.java:1166)
        at android.widget.Switch.toggle(Switch.java:1161)
        at android.widget.CompoundButton.performClick(CompoundButton.java:140)
        at android.view.View.performClickInternal(View.java:7236)
        at android.view.View.access$3600(View.java:801)
        at android.view.View$PerformClick.run(View.java:27892)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
    Caused by: java.lang.SecurityException: Missing MODIFY_AUDIO_ROUTING permission
        at android.os.Parcel.createException(Parcel.java:2071)
        at android.os.Parcel.readException(Parcel.java:2039)
        at android.os.Parcel.readException(Parcel.java:1987)
        at android.media.IAudioService$Stub$Proxy.setMasterMute(IAudioService.java:2208)
        at android.media.AudioManager.setMasterMute(AudioManager.java:915)
        ... 19 more
    Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.server.audio.AudioService.enforceModifyAudioRoutingPermission(AudioService.java:2074)
        at com.android.server.audio.AudioService.setMasterMute(AudioService.java:2793)
        at android.media.IAudioService$Stub.onTransact(IAudioService.java:963)
        at android.os.Binder.execTransactInternal(Binder.java:1021)
        at android.os.Binder.execTransact(Binder.java:994)

おおもとの原因はjava.lang.SecurityException: Missing MODIFY_AUDIO_ROUTING permissionでありMODIFY_AUDIO_ROUTINGの権限がないことが問題らしい。
ならばとアプリにMODIFY_AUDIO_ROUTINGの権限を与えようとすると今度は以下の警告がでる。

permission is granted only to system apps

この権限はプリインストールされるようなシステムアプリにしか与えられないらしい。これは警告なので無視することができるが、実際に実行するにはルート化してカメラ無音化アプリをシステムアプリとするしかない。
カメラ無音化アプリではなく無音カメラアプリは問題なく動作するがせっかくのPixel4なのに標準カメラアプリを使わないというのももったいない(Googleカメラのmodはあるが野良アプリなのでセキュリティがやや心配)。
また現状Pixelのみだが今後のアップデートにより他社のスマートフォンもカメラ無音化アプリが機能しなくなると思われる。

結論

ルート化または野良アプリをインストールしないと標準カメラを無音化できないようになったみたいです.