private int port = 5555;
private int timeoutSec = 5;
private int recordDuration;
+ private @Nullable Integer maxVolumeLevel = null;
private @Nullable Socket socket;
private @Nullable AdbConnection connection;
private @Nullable Future<String> commandFuture;
private int majorVersionNumber = 0;
private int minorVersionNumber = 0;
private int patchVersionNumber = 0;
+ /**
+ * Assumed max volume for android versions that do not expose this value.
+ */
+ private int deviceMaxVolume = 25;
+ private String volumeSettingKey = "volume_music_hdmi";
public AndroidDebugBridgeDevice(ScheduledExecutorService scheduler) {
this.scheduler = scheduler;
}
- public void configure(String ip, int port, int timeout, int recordDuration) {
+ public void configure(AndroidDebugBridgeConfiguration config) {
+ configureConnection(config.ip, config.port, config.timeout);
+ this.recordDuration = config.recordDuration;
+ this.volumeSettingKey = config.volumeSettingKey;
+ this.deviceMaxVolume = config.deviceMaxVolume;
+ }
+
+ public void configureConnection(String ip, int port, int timeout) {
this.ip = ip;
this.port = port;
this.timeoutSec = timeout;
- this.recordDuration = recordDuration;
}
public void sendKeyEvent(String eventCode)
private void setVolume(int stream, int volume)
throws AndroidDebugBridgeDeviceException, InterruptedException, TimeoutException, ExecutionException {
- runAdbShell("media", "volume", "--show", "--stream", String.valueOf(stream), "--set", String.valueOf(volume));
+ if (isAtLeastVersion(12)) {
+ runAdbShell("service", "call", "audio", "11", "i32", String.valueOf(stream), "i32", String.valueOf(volume),
+ "i32", "1");
+ } else if (isAtLeastVersion(11)) {
+ runAdbShell("service", "call", "audio", "10", "i32", String.valueOf(stream), "i32", String.valueOf(volume),
+ "i32", "1");
+ } else {
+ runAdbShell("media", "volume", "--show", "--stream", String.valueOf(stream), "--set",
+ String.valueOf(volume));
+ }
}
public String getModel() throws AndroidDebugBridgeDeviceException, InterruptedException,
private VolumeInfo getVolume(int stream) throws AndroidDebugBridgeDeviceException, InterruptedException,
AndroidDebugBridgeDeviceReadException, TimeoutException, ExecutionException {
- String volumeResp = runAdbShell("media", "volume", "--show", "--stream", String.valueOf(stream), "--get", "|",
- "grep", "volume");
- Matcher matcher = VOLUME_PATTERN.matcher(volumeResp);
- if (!matcher.find()) {
- throw new AndroidDebugBridgeDeviceReadException("Unable to get volume info");
+ if (isAtLeastVersion(11)) {
+ String volumeResp = runAdbShell("settings", "get", "system", volumeSettingKey);
+ var maxVolumeLevel = this.maxVolumeLevel;
+ if (maxVolumeLevel == null) {
+ try {
+ maxVolumeLevel = Integer.parseInt(getDeviceProp("ro.config.media_vol_steps"));
+ this.maxVolumeLevel = maxVolumeLevel;
+ } catch (NumberFormatException ignored) {
+ logger.debug("Max volume level not available, using 'deviceMaxVolume' config");
+ maxVolumeLevel = deviceMaxVolume;
+ }
+ }
+ return new VolumeInfo(Integer.parseInt(volumeResp.replace("\n", "")), 0, maxVolumeLevel);
+ } else {
+ String volumeResp = runAdbShell("media", "volume", "--show", "--stream", String.valueOf(stream), "--get",
+ "|", "grep", "volume");
+ Matcher matcher = VOLUME_PATTERN.matcher(volumeResp);
+ if (!matcher.find()) {
+ throw new AndroidDebugBridgeDeviceReadException("Unable to get volume info");
+ }
+ var volumeInfo = new VolumeInfo(Integer.parseInt(matcher.group("current")),
+ Integer.parseInt(matcher.group("min")), Integer.parseInt(matcher.group("max")));
+ logger.debug("Device {}:{} VolumeInfo: current {}, min {}, max {}", this.ip, this.port, volumeInfo.current,
+ volumeInfo.min, volumeInfo.max);
+ return volumeInfo;
}
- var volumeInfo = new VolumeInfo(Integer.parseInt(matcher.group("current")),
- Integer.parseInt(matcher.group("min")), Integer.parseInt(matcher.group("max")));
- logger.debug("Device {}:{} VolumeInfo: current {}, min {}, max {}", this.ip, this.port, volumeInfo.current,
- volumeInfo.min, volumeInfo.max);
- return volumeInfo;
}
public String recordInputEvents()
# thing types config
+thing-type.config.androiddebugbridge.android.deviceMaxVolume.label = Device Max Volume
+thing-type.config.androiddebugbridge.android.deviceMaxVolume.description = Assumed max volume for devices with android versions that do not expose this value (>=android 11).
thing-type.config.androiddebugbridge.android.ip.label = IP Address
thing-type.config.androiddebugbridge.android.ip.description = Device ip address.
thing-type.config.androiddebugbridge.android.mediaStateJSONConfig.label = Media State Config
thing-type.config.androiddebugbridge.android.refreshTime.description = Seconds between device status refreshes.
thing-type.config.androiddebugbridge.android.timeout.label = Command Timeout
thing-type.config.androiddebugbridge.android.timeout.description = Command timeout seconds.
+thing-type.config.androiddebugbridge.android.volumeSettingKey.label = Volume Setting Key
+thing-type.config.androiddebugbridge.android.volumeSettingKey.description = Settings key for android versions where the volume level is gathered using the 'settings' cli (>=android 11).
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_bluetooth_sco = volume bluetooth sco
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_music = volume music
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_music_bt_a2dp = volume music bt a2dp
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_music_hdmi = volume music hdmi
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_music_headphone = volume music headphone
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_music_headset = volume music headset
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_music_usb_headset = volume music usb headset
+thing-type.config.androiddebugbridge.android.volumeSettingKey.option.volume_system = volume system
# channel types
<description>JSON config that allows to modify the media state detection strategy for each app. Refer to the binding
documentation.</description>
</parameter>
+ <parameter name="volumeSettingKey" type="text">
+ <label>Volume Setting Key</label>
+ <description>Settings key for android versions where the volume level is gathered using the 'settings' cli
+ (>=android 11).</description>
+ <default>volume_music_hdmi</default>
+ <options>
+ <option value="volume_bluetooth_sco">volume bluetooth sco</option>
+ <option value="volume_music">volume music</option>
+ <option value="volume_music_bt_a2dp">volume music bt a2dp</option>
+ <option value="volume_music_hdmi">volume music hdmi</option>
+ <option value="volume_music_headphone">volume music headphone</option>
+ <option value="volume_music_headset">volume music headset</option>
+ <option value="volume_music_usb_headset">volume music usb headset</option>
+ <option value="volume_system">volume system</option>
+ </options>
+ <advanced>true</advanced>
+ </parameter>
+ <parameter name="deviceMaxVolume" type="integer" min="1" max="100">
+ <label>Device Max Volume</label>
+ <description>Assumed max volume for devices with android versions that do not expose this value (>=android 11).</description>
+ <default>25</default>
+ <advanced>true</advanced>
+ </parameter>
</config-description>
</thing-type>