mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-27 22:10:40 +02:00
Merge pull request 'huawei: Add missing features in HUAWEI FreeClip 2' (#6451)
Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/6451
This commit is contained in:
+4
@@ -390,6 +390,10 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_HUAWEI_FREEBUDS_ANC_MODE = "pref_freebuds_anc_mode";
|
||||
public static final String PREF_HUAWEI_FREEBUDS_VOICE_BOOST = "pref_freebuds_voice_boost";
|
||||
public static final String PREF_HUAWEI_FREEBUDS_BETTER_AUDIO_QUALITY = "pref_freebuds_better_audio_quality";
|
||||
public static final String PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME = "pref_freebuds_adaptive_volume_mode";
|
||||
public static final String PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME_APPLIED = "pref_freebuds_adaptive_volume_mode_applied";
|
||||
public static final String PREF_HUAWEI_FREEBUDS_EXTRA_MEDIA_VOLUME = "pref_freebuds_extra_media_volume";
|
||||
public static final String PREF_HUAWEI_FREEBUDS_FIND_HEADPHONES = "pref_freebuds_find_headphones";
|
||||
|
||||
public static final String PREF_GALAXY_BUDS_AMBIENT_MODE = "pref_galaxy_buds_ambient_mode";
|
||||
public static final String PREF_GALAXY_BUDS_AMBIENT_VOICE_FOCUS = "pref_galaxy_buds_ambient_voice_focus";
|
||||
|
||||
+3
@@ -869,6 +869,9 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
|
||||
addPreferenceHandlerFor(PREF_HUAWEI_FREEBUDS_ANC_MODE);
|
||||
addPreferenceHandlerFor(PREF_HUAWEI_FREEBUDS_VOICE_BOOST);
|
||||
addPreferenceHandlerFor(PREF_HUAWEI_FREEBUDS_BETTER_AUDIO_QUALITY);
|
||||
addPreferenceHandlerFor(PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME);
|
||||
addPreferenceHandlerFor(PREF_HUAWEI_FREEBUDS_EXTRA_MEDIA_VOLUME);
|
||||
addPreferenceHandlerFor(PREF_HUAWEI_FREEBUDS_FIND_HEADPHONES);
|
||||
|
||||
|
||||
addPreferenceHandlerFor(PREF_GALAXY_BUDS_AMBIENT_VOICE_FOCUS);
|
||||
|
||||
+12
@@ -122,6 +122,18 @@ public abstract class HuaweiFreebudsCoordinator extends HuaweiBRCoordinator {
|
||||
if (supports(device, HuaweiHeadphonesCapabilities.BetterAudioQuality)) {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_huawei_headphones_better_audio_quality);
|
||||
}
|
||||
if (supports(device, HuaweiHeadphonesCapabilities.AdaptiveVolume)) {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_huawei_headphones_adaptive_volume);
|
||||
}
|
||||
if (supports(device, HuaweiHeadphonesCapabilities.ExtraMediaVolume)) {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_huawei_headphones_extra_media_volume);
|
||||
}
|
||||
if (supports(device, HuaweiHeadphonesCapabilities.FindHeadphones)) {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_huawei_headphones_find_headphones);
|
||||
}
|
||||
if (supports(device, HuaweiHeadphonesCapabilities.LowLatency)) {
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_headphones_low_latency);
|
||||
}
|
||||
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_headphones);
|
||||
return deviceSpecificSettings;
|
||||
}
|
||||
|
||||
+5
-1
@@ -22,5 +22,9 @@ public enum HuaweiHeadphonesCapabilities {
|
||||
AudioModes,
|
||||
NoiseCancellationModes,
|
||||
VoiceBoost,
|
||||
BetterAudioQuality
|
||||
BetterAudioQuality,
|
||||
AdaptiveVolume,
|
||||
ExtraMediaVolume,
|
||||
FindHeadphones,
|
||||
LowLatency
|
||||
}
|
||||
|
||||
+12
@@ -706,6 +706,18 @@ public class HuaweiPacket {
|
||||
return new Earphones.SetBetterAudioQuality.Response(paramsProvider).fromPacket(this);
|
||||
case Earphones.GetBetterAudioQuality.id:
|
||||
return new Earphones.GetBetterAudioQuality.Response(paramsProvider).fromPacket(this);
|
||||
case Earphones.AdaptiveVolume.id:
|
||||
return new Earphones.AdaptiveVolume.Response(paramsProvider).fromPacket(this);
|
||||
case Earphones.FindHeadphones.id:
|
||||
return new Earphones.FindHeadphones.Response(paramsProvider, Earphones.FindHeadphones.id).fromPacket(this);
|
||||
case Earphones.FindHeadphones.stateId:
|
||||
return new Earphones.FindHeadphones.Response(paramsProvider, Earphones.FindHeadphones.stateId).fromPacket(this);
|
||||
case Earphones.SetLowLatency.id:
|
||||
return new Earphones.SetLowLatency.Response(paramsProvider).fromPacket(this);
|
||||
case Earphones.SetExtraMediaVolume.id:
|
||||
return new Earphones.SetExtraMediaVolume.Response(paramsProvider).fromPacket(this);
|
||||
case Earphones.GetExtraMediaVolume.id:
|
||||
return new Earphones.GetExtraMediaVolume.Response(paramsProvider).fromPacket(this);
|
||||
}
|
||||
case FileDownloadService2C.id:
|
||||
switch (this.commandId) {
|
||||
|
||||
+7
-2
@@ -19,7 +19,6 @@ package nodomain.freeyourgadget.gadgetbridge.devices.huawei.freeclip;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -39,7 +38,13 @@ public class HuaweiFreeClip2Coordinator extends HuaweiFreebudsCoordinator {
|
||||
|
||||
@Override
|
||||
public Set<HuaweiHeadphonesCapabilities> getCapabilities() {
|
||||
return Collections.singleton(HuaweiHeadphonesCapabilities.InEarDetection);
|
||||
return Set.of(
|
||||
HuaweiHeadphonesCapabilities.InEarDetection,
|
||||
HuaweiHeadphonesCapabilities.AdaptiveVolume,
|
||||
HuaweiHeadphonesCapabilities.ExtraMediaVolume,
|
||||
HuaweiHeadphonesCapabilities.FindHeadphones,
|
||||
HuaweiHeadphonesCapabilities.LowLatency
|
||||
);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+174
@@ -121,6 +121,180 @@ public class Earphones {
|
||||
// TODO: get long tap action 0x17
|
||||
// TODO: Audio mode cycle 0x19
|
||||
|
||||
public static class AdaptiveVolume {
|
||||
public static final byte id = (byte) 0xb4;
|
||||
public static final byte FEATURE_ID = 0x02;
|
||||
|
||||
public static class SetRequest extends HuaweiPacket {
|
||||
public SetRequest(ParamsProvider paramsProvider, boolean enabled) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, FEATURE_ID)
|
||||
.put(0x02, enabled ? (byte) 0x01 : (byte) 0x00);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetSensitivityRequest extends HuaweiPacket {
|
||||
public SetSensitivityRequest(ParamsProvider paramsProvider, byte sensitivity) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, FEATURE_ID)
|
||||
.put(0x03, sensitivity);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GetRequest extends HuaweiPacket {
|
||||
public GetRequest(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, FEATURE_ID);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public boolean enabled;
|
||||
public byte sensitivity;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
this.enabled = this.tlv.getByte(0x02, (byte) 0) == 0x01;
|
||||
this.sensitivity = this.tlv.getByte(0x03, (byte) 0x01);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FindHeadphones {
|
||||
public static final byte id = 0x5d;
|
||||
public static final byte stateId = 0x5e;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, byte side, boolean stop) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.tlv = new HuaweiTLV().put(0x01, new byte[]{side, stop ? (byte) 0x01 : (byte) 0x00});
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public byte side;
|
||||
public boolean stopped;
|
||||
|
||||
public Response(ParamsProvider paramsProvider, byte commandId) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = commandId;
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
byte[] state = this.tlv.getBytes(0x02);
|
||||
this.side = state[0];
|
||||
this.stopped = state[1] == 0x01;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetLowLatency {
|
||||
public static final byte id = 0x6c;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, boolean enabled) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.tlv = new HuaweiTLV().put(0x01, enabled);
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SetExtraMediaVolume {
|
||||
public static final byte id = (byte) 0x87;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, boolean enabled) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.tlv = new HuaweiTLV().put(0x01, enabled);
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class GetExtraMediaVolume {
|
||||
public static final byte id = (byte) 0x88;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.tlv = new HuaweiTLV().put(0x01);
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public boolean enabled;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = id;
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
this.enabled = this.tlv.getByte(0x01) == 0x01;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class GetAudioModeRequest {
|
||||
public static final byte id = 0x2a;
|
||||
|
||||
|
||||
+16
@@ -53,6 +53,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DataSync;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.DeviceConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Ephemeris;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.EphemerisFileUpload;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FileDownloadService2C;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FindPhone;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
|
||||
@@ -137,12 +138,27 @@ public class AsynchronousResponse {
|
||||
handleDataSyncCommands(response);
|
||||
handleOTA(response);
|
||||
handleFileDownload(response);
|
||||
handleExtraMediaVolume(response);
|
||||
|
||||
} catch (Request.ResponseParseException e) {
|
||||
LOG.error("Response parse exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleExtraMediaVolume(HuaweiPacket response) throws Request.ResponseParseException {
|
||||
if (response.serviceId != Earphones.id || response.commandId != Earphones.GetExtraMediaVolume.id) {
|
||||
return;
|
||||
}
|
||||
if (!(response instanceof Earphones.GetExtraMediaVolume.Response)) {
|
||||
throw new Request.ResponseTypeMismatchException(response, Earphones.GetExtraMediaVolume.Response.class);
|
||||
}
|
||||
|
||||
boolean enabled = ((Earphones.GetExtraMediaVolume.Response) response).enabled;
|
||||
GBApplication.getDeviceSpecificSharedPrefs(support.getDeviceMac()).edit()
|
||||
.putBoolean(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_EXTRA_MEDIA_VOLUME, enabled)
|
||||
.apply();
|
||||
}
|
||||
|
||||
private void handleFindPhone(HuaweiPacket response) throws Request.ResponseParseException {
|
||||
if (response.serviceId == FindPhone.id && response.commandId == FindPhone.Response.id) {
|
||||
if (!(response instanceof FindPhone.Response))
|
||||
|
||||
+30
@@ -37,12 +37,18 @@ import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.HeadphoneHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetAdaptiveVolumeRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetBetterAudioQualityRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetExtraMediaVolumeRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetProductInformationRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetANCModeRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetAudioModeRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetBetterAudioQualityRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetAdaptiveVolumeRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetExtraMediaVolumeRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetFindHeadphonesRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetLowLatencyRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetVoiceBoostRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetPauseWhenRemovedFromEarRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
@@ -71,6 +77,18 @@ public class HuaweiFreebudsSupport extends HuaweiBRSupport implements HeadphoneH
|
||||
GetBetterAudioQualityRequest req = new GetBetterAudioQualityRequest(super.getSupportProvider());
|
||||
req.doPerform();
|
||||
}
|
||||
if (coordinator.supports(this.gbDevice, HuaweiHeadphonesCapabilities.AdaptiveVolume)) {
|
||||
GetAdaptiveVolumeRequest req = new GetAdaptiveVolumeRequest(super.getSupportProvider());
|
||||
req.doPerform();
|
||||
}
|
||||
if (coordinator.supports(this.gbDevice, HuaweiHeadphonesCapabilities.ExtraMediaVolume)) {
|
||||
new GetExtraMediaVolumeRequest(super.getSupportProvider()).doPerform();
|
||||
}
|
||||
if (coordinator.supports(this.gbDevice, HuaweiHeadphonesCapabilities.FindHeadphones)) {
|
||||
GBApplication.getDeviceSpecificSharedPrefs(this.gbDevice.getAddress()).edit()
|
||||
.putString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_FIND_HEADPHONES, "0")
|
||||
.apply();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
GB.toast(this.getContext(), "Final initialization of Huawei device failed", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||
@@ -154,6 +172,18 @@ public class HuaweiFreebudsSupport extends HuaweiBRSupport implements HeadphoneH
|
||||
case DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_BETTER_AUDIO_QUALITY:
|
||||
new SetBetterAudioQualityRequest(getSupportProvider()).doPerform();
|
||||
break;
|
||||
case DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME:
|
||||
new SetAdaptiveVolumeRequest(getSupportProvider()).doPerform();
|
||||
break;
|
||||
case DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_EXTRA_MEDIA_VOLUME:
|
||||
new SetExtraMediaVolumeRequest(getSupportProvider()).doPerform();
|
||||
break;
|
||||
case DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_FIND_HEADPHONES:
|
||||
new SetFindHeadphonesRequest(getSupportProvider()).doPerform();
|
||||
break;
|
||||
case DeviceSettingsPreferenceConst.PREF_HEADPHONES_LOW_LATENCY:
|
||||
new SetLowLatencyRequest(getSupportProvider()).doPerform();
|
||||
break;
|
||||
case DeviceSettingsPreferenceConst.PREF_BATTERY_POLLING_ENABLE:
|
||||
if (!GBApplication.getDevicePrefs(gbDevice).getBatteryPollingEnabled()) {
|
||||
getSupportProvider().stopBatteryRunnerDelayed();
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2026
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetAdaptiveVolumeRequest extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GetAdaptiveVolumeRequest.class);
|
||||
|
||||
public GetAdaptiveVolumeRequest(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = Earphones.AdaptiveVolume.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws Request.RequestCreationException {
|
||||
try {
|
||||
return new Earphones.AdaptiveVolume.GetRequest(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new Request.RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws Request.ResponseParseException {
|
||||
LOG.debug("handle GetAdaptiveVolume");
|
||||
|
||||
if (!(receivedPacket instanceof Earphones.AdaptiveVolume.Response))
|
||||
throw new Request.ResponseTypeMismatchException(receivedPacket, Earphones.AdaptiveVolume.Response.class);
|
||||
|
||||
Earphones.AdaptiveVolume.Response packet = (Earphones.AdaptiveVolume.Response) receivedPacket;
|
||||
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(this.getDevice().getAddress());
|
||||
String mode = SetAdaptiveVolumeRequest.Mode.fromResponse(packet).toPreference();
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME, mode);
|
||||
editor.putString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME_APPLIED, mode);
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 2026
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetExtraMediaVolumeRequest extends Request {
|
||||
public GetExtraMediaVolumeRequest(HuaweiSupportProvider supportProvider) {
|
||||
super(supportProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = Earphones.GetExtraMediaVolume.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new Earphones.GetExtraMediaVolume.Request(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
if (!(receivedPacket instanceof Earphones.GetExtraMediaVolume.Response)) {
|
||||
throw new ResponseTypeMismatchException(receivedPacket, Earphones.GetExtraMediaVolume.Response.class);
|
||||
}
|
||||
|
||||
boolean enabled = ((Earphones.GetExtraMediaVolume.Response) receivedPacket).enabled;
|
||||
GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress()).edit()
|
||||
.putBoolean(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_EXTRA_MEDIA_VOLUME, enabled)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 2026
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SetAdaptiveVolumeRequest extends Request {
|
||||
public enum Mode {
|
||||
OFF((byte) -1),
|
||||
LOW((byte) 0x00),
|
||||
DEFAULT((byte) 0x01),
|
||||
HIGH((byte) 0x02);
|
||||
|
||||
private final byte sensitivity;
|
||||
|
||||
Mode(byte sensitivity) {
|
||||
this.sensitivity = sensitivity;
|
||||
}
|
||||
|
||||
public static Mode fromPreference(String value) {
|
||||
try {
|
||||
return valueOf(value.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return OFF;
|
||||
}
|
||||
}
|
||||
|
||||
public static Mode fromResponse(Earphones.AdaptiveVolume.Response response) {
|
||||
if (!response.enabled) {
|
||||
return OFF;
|
||||
}
|
||||
switch (response.sensitivity) {
|
||||
case 0x00:
|
||||
return LOW;
|
||||
case 0x02:
|
||||
return HIGH;
|
||||
default:
|
||||
return DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
public String toPreference() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public SetAdaptiveVolumeRequest(HuaweiSupportProvider supportProvider) {
|
||||
super(supportProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = Earphones.AdaptiveVolume.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(this.getDevice().getAddress());
|
||||
Mode mode = Mode.fromPreference(prefs.getString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME, "off"));
|
||||
Mode appliedMode = Mode.fromPreference(prefs.getString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME_APPLIED, "off"));
|
||||
List<byte[]> requests = new ArrayList<>();
|
||||
|
||||
if (mode == Mode.OFF) {
|
||||
requests.addAll(new Earphones.AdaptiveVolume.SetRequest(this.paramsProvider, false).serialize());
|
||||
} else {
|
||||
if (appliedMode == Mode.OFF) {
|
||||
requests.addAll(new Earphones.AdaptiveVolume.SetRequest(this.paramsProvider, true).serialize());
|
||||
}
|
||||
requests.addAll(new Earphones.AdaptiveVolume.SetSensitivityRequest(this.paramsProvider, mode.sensitivity).serialize());
|
||||
}
|
||||
|
||||
prefs.edit().putString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_ADAPTIVE_VOLUME_APPLIED, mode.toPreference()).apply();
|
||||
return requests;
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* Copyright (C) 2026
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SetExtraMediaVolumeRequest extends Request {
|
||||
public SetExtraMediaVolumeRequest(HuaweiSupportProvider supportProvider) {
|
||||
super(supportProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = Earphones.SetExtraMediaVolume.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
boolean enabled = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress())
|
||||
.getBoolean(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_EXTRA_MEDIA_VOLUME, false);
|
||||
return new Earphones.SetExtraMediaVolume.Request(paramsProvider, enabled).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/* Copyright (C) 2026
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SetFindHeadphonesRequest extends Request {
|
||||
public SetFindHeadphonesRequest(HuaweiSupportProvider supportProvider) {
|
||||
super(supportProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = Earphones.FindHeadphones.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
int mode = Integer.parseInt(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress())
|
||||
.getString(DeviceSettingsPreferenceConst.PREF_HUAWEI_FREEBUDS_FIND_HEADPHONES, "0"));
|
||||
List<byte[]> requests = new ArrayList<>();
|
||||
requests.addAll(new Earphones.FindHeadphones.Request(paramsProvider, (byte) 0x00, (mode & 0x01) == 0).serialize());
|
||||
requests.addAll(new Earphones.FindHeadphones.Request(paramsProvider, (byte) 0x01, (mode & 0x02) == 0).serialize());
|
||||
return requests;
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* Copyright (C) 2026
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SetLowLatencyRequest extends Request {
|
||||
public SetLowLatencyRequest(HuaweiSupportProvider supportProvider) {
|
||||
super(supportProvider);
|
||||
this.serviceId = Earphones.id;
|
||||
this.commandId = Earphones.SetLowLatency.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
boolean enabled = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress())
|
||||
.getBoolean(DeviceSettingsPreferenceConst.PREF_HEADPHONES_LOW_LATENCY, false);
|
||||
return new Earphones.SetLowLatency.Request(paramsProvider, enabled).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5403,6 +5403,32 @@
|
||||
<item>calories_segmented</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="huawei_find_headphones_names">
|
||||
<item>@string/off</item>
|
||||
<item>@string/left_earbud</item>
|
||||
<item>@string/right_earbud</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="huawei_find_headphones_values">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="huawei_adaptive_volume_names">
|
||||
<item>@string/off</item>
|
||||
<item>@string/low</item>
|
||||
<item>@string/pref_default</item>
|
||||
<item>@string/high</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="huawei_adaptive_volume_values">
|
||||
<item>off</item>
|
||||
<item>low</item>
|
||||
<item>default</item>
|
||||
<item>high</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="huawei_freebuds_audio_mode_names">
|
||||
<item>@string/prefs_active_noise_cancelling</item>
|
||||
<item>@string/prefs_active_noise_cancelling_transparency</item>
|
||||
|
||||
@@ -4656,6 +4656,10 @@
|
||||
<string name="huawei_voice_boost">Voice Boost</string>
|
||||
<string name="huawei_better_audio_quality_title">Prioritise better audio quality.</string>
|
||||
<string name="huawei_better_audio_quality_summary">Enable better audio codecs (LDAC). This should improve sound quality, but it increases power consumption and can cause delays.</string>
|
||||
<string name="huawei_adaptive_volume_title">Adaptive Volume</string>
|
||||
<string name="huawei_adaptive_volume_summary">Automatically adjust volume based on your environment. (Increases power usage)</string>
|
||||
<string name="huawei_extra_media_volume_title">Extra media volume</string>
|
||||
<string name="huawei_extra_media_volume_summary">Increase the maximum media volume. This may affect audio quality. May damage hearing.</string>
|
||||
<string name="maps">Maps</string>
|
||||
<string name="workout_charts">Workout Charts</string>
|
||||
<string name="maps_settings">Maps settings</string>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<ListPreference
|
||||
android:defaultValue="off"
|
||||
android:entries="@array/huawei_adaptive_volume_names"
|
||||
android:entryValues="@array/huawei_adaptive_volume_values"
|
||||
android:icon="@drawable/ic_noise_control_on"
|
||||
android:key="pref_freebuds_adaptive_volume_mode"
|
||||
android:title="@string/huawei_adaptive_volume_title"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_volume_up"
|
||||
android:key="pref_freebuds_extra_media_volume"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="@string/huawei_extra_media_volume_summary"
|
||||
android:title="@string/huawei_extra_media_volume_title" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<ListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/huawei_find_headphones_names"
|
||||
android:entryValues="@array/huawei_find_headphones_values"
|
||||
android:icon="@drawable/ic_action_find_lost_device"
|
||||
android:key="pref_freebuds_find_headphones"
|
||||
android:title="@string/earfun_find_headphones"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
<Preference
|
||||
android:key="pref_freebuds_find_headphones_hint"
|
||||
android:selectable="false"
|
||||
android:summary="@string/earfun_find_headphones_hint" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
+101
@@ -22,6 +22,7 @@ import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Earphones;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FindPhone;
|
||||
|
||||
public class TestHuaweiPacket {
|
||||
@@ -216,6 +217,106 @@ public class TestHuaweiPacket {
|
||||
Assert.assertArrayEquals(expected, output.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdaptiveVolumeSerialize() throws HuaweiPacket.CryptoException {
|
||||
byte[] expectedEnabled = {(byte) 0x5a, 0x00, 0x09, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, (byte) 0xc0};
|
||||
byte[] expectedDisabled = {(byte) 0x5a, 0x00, 0x09, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x13, (byte) 0xe1};
|
||||
byte[] expectedLow = {(byte) 0x5a, 0x00, 0x09, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x24, (byte) 0xd1};
|
||||
byte[] expectedDefault = {(byte) 0x5a, 0x00, 0x09, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x34, (byte) 0xf0};
|
||||
byte[] expectedHigh = {(byte) 0x5a, 0x00, 0x09, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x03, 0x01, 0x02, 0x04, (byte) 0x93};
|
||||
|
||||
Assert.assertArrayEquals(expectedEnabled, new Earphones.AdaptiveVolume.SetRequest(paramsProvider, true).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedDisabled, new Earphones.AdaptiveVolume.SetRequest(paramsProvider, false).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedLow, new Earphones.AdaptiveVolume.SetSensitivityRequest(paramsProvider, (byte) 0x00).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedDefault, new Earphones.AdaptiveVolume.SetSensitivityRequest(paramsProvider, (byte) 0x01).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedHigh, new Earphones.AdaptiveVolume.SetSensitivityRequest(paramsProvider, (byte) 0x02).serialize().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdaptiveVolumeResponseParse() throws HuaweiPacket.ParseException {
|
||||
byte[] enabled = {(byte) 0x5a, 0x00, 0x0c, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x75, (byte) 0x8a};
|
||||
byte[] disabled = {(byte) 0x5a, 0x00, 0x0c, 0x00, 0x2b, (byte) 0xb4, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x01, 0x01, 0x03, 0x3e};
|
||||
|
||||
Earphones.AdaptiveVolume.Response enabledResponse = (Earphones.AdaptiveVolume.Response) new HuaweiPacket(paramsProvider).parse(enabled);
|
||||
enabledResponse.parseTlv();
|
||||
Assert.assertTrue(enabledResponse.enabled);
|
||||
Assert.assertEquals(0x01, enabledResponse.sensitivity);
|
||||
|
||||
Earphones.AdaptiveVolume.Response disabledResponse = (Earphones.AdaptiveVolume.Response) new HuaweiPacket(paramsProvider).parse(disabled);
|
||||
disabledResponse.parseTlv();
|
||||
Assert.assertFalse(disabledResponse.enabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtraMediaVolumeSerialize() throws HuaweiPacket.CryptoException {
|
||||
byte[] expectedEnabled = {(byte) 0x5a, 0x00, 0x06, 0x00, 0x2b, (byte) 0x87, 0x01, 0x01, 0x01, 0x3e, (byte) 0xe4};
|
||||
byte[] expectedDisabled = {(byte) 0x5a, 0x00, 0x06, 0x00, 0x2b, (byte) 0x87, 0x01, 0x01, 0x00, 0x2e, (byte) 0xc5};
|
||||
byte[] expectedGet = {(byte) 0x5a, 0x00, 0x05, 0x00, 0x2b, (byte) 0x88, 0x01, 0x00, (byte) 0x91, (byte) 0x82};
|
||||
|
||||
Assert.assertArrayEquals(expectedEnabled, new Earphones.SetExtraMediaVolume.Request(paramsProvider, true).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedDisabled, new Earphones.SetExtraMediaVolume.Request(paramsProvider, false).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedGet, new Earphones.GetExtraMediaVolume.Request(paramsProvider).serialize().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtraMediaVolumeResponseParse() throws HuaweiPacket.ParseException {
|
||||
byte[] enabled = {(byte) 0x5a, 0x00, 0x06, 0x00, 0x2b, (byte) 0x88, 0x01, 0x01, 0x01, (byte) 0xea, 0x0a};
|
||||
byte[] disabled = {(byte) 0x5a, 0x00, 0x06, 0x00, 0x2b, (byte) 0x88, 0x01, 0x01, 0x00, (byte) 0xfa, 0x2b};
|
||||
|
||||
Earphones.GetExtraMediaVolume.Response enabledResponse = (Earphones.GetExtraMediaVolume.Response) new HuaweiPacket(paramsProvider).parse(enabled);
|
||||
enabledResponse.parseTlv();
|
||||
Assert.assertTrue(enabledResponse.enabled);
|
||||
|
||||
Earphones.GetExtraMediaVolume.Response disabledResponse = (Earphones.GetExtraMediaVolume.Response) new HuaweiPacket(paramsProvider).parse(disabled);
|
||||
disabledResponse.parseTlv();
|
||||
Assert.assertFalse(disabledResponse.enabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindHeadphonesSerialize() throws HuaweiPacket.CryptoException {
|
||||
byte[] leftStart = {(byte) 0x5a, 0x00, 0x07, 0x00, 0x2b, 0x5d, 0x01, 0x02, 0x00, 0x00, 0x6f, 0x63};
|
||||
byte[] leftStop = {(byte) 0x5a, 0x00, 0x07, 0x00, 0x2b, 0x5d, 0x01, 0x02, 0x00, 0x01, 0x7f, 0x42};
|
||||
byte[] rightStart = {(byte) 0x5a, 0x00, 0x07, 0x00, 0x2b, 0x5d, 0x01, 0x02, 0x01, 0x00, 0x5c, 0x52};
|
||||
byte[] rightStop = {(byte) 0x5a, 0x00, 0x07, 0x00, 0x2b, 0x5d, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x73};
|
||||
|
||||
Assert.assertArrayEquals(leftStart, new Earphones.FindHeadphones.Request(paramsProvider, (byte) 0x00, false).serialize().get(0));
|
||||
Assert.assertArrayEquals(leftStop, new Earphones.FindHeadphones.Request(paramsProvider, (byte) 0x00, true).serialize().get(0));
|
||||
Assert.assertArrayEquals(rightStart, new Earphones.FindHeadphones.Request(paramsProvider, (byte) 0x01, false).serialize().get(0));
|
||||
Assert.assertArrayEquals(rightStop, new Earphones.FindHeadphones.Request(paramsProvider, (byte) 0x01, true).serialize().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindHeadphonesResponseParse() throws HuaweiPacket.ParseException {
|
||||
byte[] acknowledgement = {(byte) 0x5a, 0x00, 0x07, 0x00, 0x2b, 0x5d, 0x02, 0x02, 0x00, 0x00, (byte) 0xf4, (byte) 0xbf};
|
||||
byte[] notification = {(byte) 0x5a, 0x00, 0x07, 0x00, 0x2b, 0x5e, 0x02, 0x02, 0x01, 0x01, 0x39, 0x7d};
|
||||
|
||||
Earphones.FindHeadphones.Response acknowledgementResponse = (Earphones.FindHeadphones.Response) new HuaweiPacket(paramsProvider).parse(acknowledgement);
|
||||
acknowledgementResponse.parseTlv();
|
||||
Assert.assertEquals(0x00, acknowledgementResponse.side);
|
||||
Assert.assertFalse(acknowledgementResponse.stopped);
|
||||
|
||||
Earphones.FindHeadphones.Response notificationResponse = (Earphones.FindHeadphones.Response) new HuaweiPacket(paramsProvider).parse(notification);
|
||||
notificationResponse.parseTlv();
|
||||
Assert.assertEquals(0x01, notificationResponse.side);
|
||||
Assert.assertTrue(notificationResponse.stopped);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowLatencySerialize() throws HuaweiPacket.CryptoException {
|
||||
byte[] expectedEnabled = {(byte) 0x5a, 0x00, 0x06, 0x00, 0x2b, 0x6c, 0x01, 0x01, 0x01, (byte) 0xa4, 0x11};
|
||||
byte[] expectedDisabled = {(byte) 0x5a, 0x00, 0x06, 0x00, 0x2b, 0x6c, 0x01, 0x01, 0x00, (byte) 0xb4, 0x30};
|
||||
|
||||
Assert.assertArrayEquals(expectedEnabled, new Earphones.SetLowLatency.Request(paramsProvider, true).serialize().get(0));
|
||||
Assert.assertArrayEquals(expectedDisabled, new Earphones.SetLowLatency.Request(paramsProvider, false).serialize().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowLatencyResponseParse() throws HuaweiPacket.ParseException {
|
||||
byte[] response = {(byte) 0x5a, 0x00, 0x09, 0x00, 0x2b, 0x6c, 0x7f, 0x04, 0x00, 0x01, (byte) 0x86, (byte) 0xa0, (byte) 0xa4, (byte) 0x97};
|
||||
|
||||
Assert.assertEquals(Earphones.SetLowLatency.Response.class, new HuaweiPacket(paramsProvider).parse(response).getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryptedUnslicedSerialize() throws HuaweiPacket.CryptoException {
|
||||
byte serviceId = 0x01;
|
||||
|
||||
Reference in New Issue
Block a user