You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
As it turns out, it is not trivial to control the audio volume of an Android device using ADB. At the time of writing, the only way appears to be using the `service` tool. Actually, the `service` command allows to "connect" to a number of services (104 on Android 6.0.1) and invoke functions. Not knowing much about this tool, I managed to completely mute all sounds and speakers of my Nexus 5, and I was stuck without any sound for quite some time. I did not find a way to unmute the sound from within the system UI, so I got to dive a little deeper into this.
If you know which service you want to use, you then need to find its interface declaration. The command
service list
gives you a list of all services with the associated interfaces, if applicable:
For me, the `audio` service was relevant, which appeared at index 32. The associated interface is `android.media.IAudioService`, so the next thing you will want to do is find the source code of that file. And, even more importantly, find the correct version of that file (this was my mistake in the first place). For 6.0.1, you can find the interface declaration [here](https://github.com/android/platform_frameworks_base/blob/marshmallow-release/media/java/android/media/IAudioService.aidl). If you select a different branch on GitHub, you will see that the file differs from release to release.
In order to call a function of the interface, we need to know its index in the interface declaration. For example, to mute all sound, I will use [`IAudioService.setMasterMute`](https://github.com/android/platform_frameworks_base/blob/marshmallow-release/media/java/android/media/IAudioService.aidl#L58). This function is the 8th method in the interface declaration. We will need this index soon, and it appears to start with 1 (so the first function has the index 1, not 0!). Additionally, we need to supply the correct arguments to the function. The declaration looks like this:
void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
We will only supply the first two arguments, which are a boolean and an integer, which are both treated as integers for now.
In the ADB shell, the command
service call audio 8 i32 1 i32 0
mutes all sounds on my Nexus 5 (6.0.1). `service call audio` is self explanatory, `8` is the function index, `i32 1` represents the boolean value `true` and `i32 0` represents the integer `0` for the flags parameter.
We can use the function [`IAudioService.isMasterMute`](https://github.com/android/platform_frameworks_base/blob/marshmallow-release/media/java/android/media/IAudioService.aidl#L56) to verify the result (or you could just try to make a call or watch a video, you should hear nothing, no matter what you set your volume to). Its signature is simple:
boolean isMasterMute();
It is the 7th function in the interface, so we can call it using
service call audio 7
After issuing the command, it should output something like
shell@hammerhead:/ $ service call audio 7
Result: Parcel(00000000 00000001 '........')
Note that the last digit is set to 1, and as `isMasterMute()` should return a boolean, we interpret this as `true`.
Unmuting is as simple as muting the device:
service call audio 8 i32 0 i32 0
Again, use `isMasterMute()` to verify the result:
shell@hammerhead:/ $ service call audio 7
Result: Parcel(00000000 00000000 '........')
All zeroes represent the value `false`, so the result is correct!
# When to avoid using `service`
Basically, whenever possible. The command and the interfaces are documented poorly and they are subject to change from release to release. You can use the command for manual debugging (and that might be the reason it was developed), but if you intend to use it in scripting, you will eventually run into problems. You need to change the command for each release, possibly even depending on the device, and I have no idea how much CyanogenMod and friends care about such compatibility. Many features are available without using `service`, and if there is a better interface to it, use it.