mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-27 12:26:48 +01:00
Huawei: Initial music upload support
This commit is contained in:
parent
86cb08c0fb
commit
48717aaf42
@ -74,6 +74,10 @@ public class HuaweiCoordinator {
|
||||
|
||||
private App.AppDeviceParams appDeviceParams;
|
||||
|
||||
private HuaweiMusicUtils.MusicCapabilities musicDeviceParams = null;
|
||||
|
||||
private HuaweiMusicUtils.MusicCapabilities musicExtendedDeviceParams = null;
|
||||
|
||||
private final HuaweiCoordinatorSupplier parent;
|
||||
|
||||
private boolean transactionCrypted=true;
|
||||
@ -492,6 +496,8 @@ public class HuaweiCoordinator {
|
||||
|
||||
public boolean supportsAppParams(){ return supportsCommandForService(0x2a, 0x06);}
|
||||
|
||||
public boolean supportsMusicUploading(){ return supportsCommandForService(0x25, 0x04);}
|
||||
|
||||
public boolean supportsWeather() {
|
||||
return supportsCommandForService(0x0f, 0x01);
|
||||
}
|
||||
@ -712,6 +718,23 @@ public class HuaweiCoordinator {
|
||||
return appDeviceParams;
|
||||
}
|
||||
|
||||
public void setExtendedMusicInfoParams(HuaweiMusicUtils.MusicCapabilities musicDeviceParams) {
|
||||
LOG.info(musicDeviceParams.toString());
|
||||
this.musicExtendedDeviceParams = musicDeviceParams;
|
||||
}
|
||||
public HuaweiMusicUtils.MusicCapabilities getExtendedMusicInfoParams() {
|
||||
return musicExtendedDeviceParams;
|
||||
}
|
||||
|
||||
public void setMusicInfoParams(HuaweiMusicUtils.MusicCapabilities musicDeviceParams) {
|
||||
LOG.info(musicDeviceParams.toString());
|
||||
this.musicDeviceParams = musicDeviceParams;
|
||||
}
|
||||
public HuaweiMusicUtils.MusicCapabilities getMusicInfoParams() {
|
||||
return musicDeviceParams;
|
||||
}
|
||||
|
||||
|
||||
public Class<? extends Activity> getAppManagerActivity() {
|
||||
return AppManagerActivity.class;
|
||||
}
|
||||
|
@ -19,9 +19,13 @@ package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.InstallActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
@ -31,6 +35,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiAppManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiFwHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiMusicManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWatchfaceManager;
|
||||
|
||||
public class HuaweiInstallHandler implements InstallHandler {
|
||||
@ -46,6 +51,59 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
this.helper = new HuaweiFwHelper(uri, context);
|
||||
}
|
||||
|
||||
private HuaweiMusicUtils.FormatRestrictions getRestriction(HuaweiMusicUtils.MusicCapabilities capabilities, String ext) {
|
||||
List<HuaweiMusicUtils.FormatRestrictions> restrictions = capabilities.formatsRestrictions;
|
||||
if(restrictions == null)
|
||||
return null;
|
||||
|
||||
for(HuaweiMusicUtils.FormatRestrictions r: restrictions) {
|
||||
if(ext.equals(r.getName())) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//TODO: add proper checks
|
||||
private boolean checkMediaCompatibility(HuaweiMusicUtils.MusicCapabilities capabilities, HuaweiMusicManager.AudioInfo currentMusicInfo) {
|
||||
if(capabilities == null) {
|
||||
LOG.error("No media info from device");
|
||||
return false;
|
||||
}
|
||||
String ext = currentMusicInfo.getExtension();
|
||||
|
||||
List<String> supportedFormats = capabilities.supportedFormats;
|
||||
if(supportedFormats == null) {
|
||||
LOG.error("Format not supported {}", ext);
|
||||
return false;
|
||||
}
|
||||
if(!supportedFormats.contains(ext)) {
|
||||
LOG.error("Format not supported {}", ext);
|
||||
return false;
|
||||
}
|
||||
|
||||
HuaweiMusicUtils.FormatRestrictions restrictions = getRestriction(capabilities, ext);
|
||||
if(restrictions == null) {
|
||||
LOG.info("no restriction for: {}", ext);
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG.info("bitrate {}", restrictions.bitrate);
|
||||
LOG.info("channels {}", restrictions.channels);
|
||||
LOG.info("musicEncode {}", restrictions.musicEncode);
|
||||
LOG.info("sampleRate {}", restrictions.sampleRate);
|
||||
LOG.info("unknownBitrate {}", restrictions.unknownBitrate);
|
||||
|
||||
if(currentMusicInfo.getChannels() > restrictions.channels) {
|
||||
LOG.error("Not supported channels couunt {} > {}", currentMusicInfo.getChannels(), restrictions.channels);
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: check other restrictions.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void validateInstallation(InstallActivity installActivity, GBDevice device) {
|
||||
@ -57,7 +115,7 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if(helper.isWatchface()) {
|
||||
if (helper.isWatchface()) {
|
||||
final HuaweiCoordinatorSupplier huaweiCoordinatorSupplier = (HuaweiCoordinatorSupplier) coordinator;
|
||||
|
||||
HuaweiWatchfaceManager.WatchfaceDescription description = helper.getWatchfaceDescription();
|
||||
@ -71,7 +129,6 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
|
||||
GenericItem installItem = new GenericItem();
|
||||
|
||||
|
||||
if (helper.getPreviewBitmap() != null) {
|
||||
installItem.setPreview(helper.getPreviewBitmap());
|
||||
}
|
||||
@ -79,16 +136,16 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
installItem.setName(description.title);
|
||||
installActivity.setInstallItem(installItem);
|
||||
if (device.isBusy()) {
|
||||
LOG.error("Firmware cannot be installed (device busy)");
|
||||
installActivity.setInfoText("Firmware cannot be installed (device busy)");
|
||||
LOG.error("Watchface cannot be installed (device busy)");
|
||||
installActivity.setInfoText("Watchface cannot be installed (device busy)");
|
||||
installActivity.setInfoText(device.getBusyTask());
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device.isConnected()) {
|
||||
LOG.error("Firmware cannot be installed (not connected or wrong device)");
|
||||
installActivity.setInfoText("Firmware cannot be installed (not connected or wrong device)");
|
||||
LOG.error("Watchface cannot be installed (not connected or wrong device)");
|
||||
installActivity.setInfoText("Watchface cannot be installed (not connected or wrong device)");
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
}
|
||||
@ -106,7 +163,7 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
installItem.setIcon(R.drawable.ic_watchface);
|
||||
installActivity.setInfoText(context.getString(R.string.watchface_install_info, installItem.getName(), description.version, description.author));
|
||||
|
||||
LOG.debug("Initialized HuaweiInstallHandler");
|
||||
LOG.debug("Initialized HuaweiInstallHandler: Watchface");
|
||||
} else if (helper.isAPP()) {
|
||||
final HuaweiAppManager.AppConfig config = helper.getAppConfig();
|
||||
|
||||
@ -123,7 +180,7 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
installItem.setName(config.bundleName);
|
||||
installActivity.setInstallItem(installItem);
|
||||
if (device.isBusy()) {
|
||||
LOG.error("Firmware cannot be installed (device busy)");
|
||||
LOG.error("App cannot be installed (device busy)");
|
||||
installActivity.setInfoText("Firmware cannot be installed (device busy)");
|
||||
installActivity.setInfoText(device.getBusyTask());
|
||||
installActivity.setInstallEnabled(false);
|
||||
@ -131,7 +188,7 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
}
|
||||
|
||||
if (!device.isConnected()) {
|
||||
LOG.error("Firmware cannot be installed (not connected or wrong device)");
|
||||
LOG.error("App cannot be installed (not connected or wrong device)");
|
||||
installActivity.setInfoText("Firmware cannot be installed (not connected or wrong device)");
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
@ -149,7 +206,55 @@ public class HuaweiInstallHandler implements InstallHandler {
|
||||
|
||||
installActivity.setInfoText(context.getString(R.string.app_install_info, installItem.getName(), config.version, config.vendor));
|
||||
|
||||
LOG.debug("Initialized HuaweiInstallHandler");
|
||||
LOG.debug("Initialized HuaweiInstallHandler: App");
|
||||
} else if (helper.isMusic()) {
|
||||
final HuaweiCoordinatorSupplier huaweiCoordinatorSupplier = (HuaweiCoordinatorSupplier) coordinator;
|
||||
|
||||
HuaweiMusicUtils.MusicCapabilities capabilities = huaweiCoordinatorSupplier.getHuaweiCoordinator().getExtendedMusicInfoParams();
|
||||
if(capabilities == null) {
|
||||
capabilities = huaweiCoordinatorSupplier.getHuaweiCoordinator().getMusicInfoParams();
|
||||
}
|
||||
HuaweiMusicManager.AudioInfo currentMusicInfo = helper.getMusicInfo();
|
||||
|
||||
boolean isMediaCompatible = checkMediaCompatibility(capabilities, currentMusicInfo);
|
||||
|
||||
this.valid = isMediaCompatible && !TextUtils.isEmpty(helper.getMusicInfo().getFileName()) && !TextUtils.isEmpty(helper.getMusicInfo().getArtist()) && !TextUtils.isEmpty(helper.getMusicInfo().getTitle());
|
||||
|
||||
installActivity.setInstallEnabled(true);
|
||||
|
||||
GenericItem installItem = new GenericItem();
|
||||
|
||||
installItem.setName(helper.getFileName());
|
||||
installActivity.setInstallItem(installItem);
|
||||
if (device.isBusy()) {
|
||||
LOG.error("Music cannot be uploaded (device busy)");
|
||||
installActivity.setInfoText("Music cannot be uploaded (device busy)");
|
||||
installActivity.setInfoText(device.getBusyTask());
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device.isConnected()) {
|
||||
LOG.error("Music cannot be uploaded (not connected or wrong device)");
|
||||
installActivity.setInfoText("Music cannot be uploaded (not connected or wrong device)");
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.valid) {
|
||||
LOG.error("Music cannot be uploaded");
|
||||
installActivity.setInfoText("Music cannot be uploaded");
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
installItem.setDetails(helper.getMusicInfo().getFileName());
|
||||
|
||||
installItem.setIcon(R.drawable.ic_music_note);
|
||||
|
||||
installActivity.setInfoText(context.getString(R.string.app_install_info, helper.getMusicInfo().getFileName(), helper.getMusicInfo().getTitle(), helper.getMusicInfo().getArtist()));
|
||||
|
||||
LOG.debug("Initialized HuaweiInstallHandler: Music");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,131 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HuaweiMusicUtils {
|
||||
|
||||
public static class PageStruct {
|
||||
public short startIndex = 0;
|
||||
public short endIndex = 0;
|
||||
public short count = 0;
|
||||
public byte[] hashCode = null;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("PageStruct{");
|
||||
sb.append("startIndex=").append(startIndex);
|
||||
sb.append(", endIndex=").append(endIndex);
|
||||
sb.append(", count=").append(count);
|
||||
sb.append(", hashCode=");
|
||||
if (hashCode == null) sb.append("null");
|
||||
else {
|
||||
sb.append('[');
|
||||
for (int i = 0; i < hashCode.length; ++i)
|
||||
sb.append(i == 0 ? "" : ", ").append(hashCode[i]);
|
||||
sb.append(']');
|
||||
}
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class FormatRestrictions {
|
||||
public byte formatIdx = -1;
|
||||
public int sampleRate = -1; // TODO: not sure
|
||||
public byte musicEncode = -1; // TODO: not sure
|
||||
public short bitrate = -1;
|
||||
public byte channels = -1;
|
||||
public short unknownBitrate = -1; // TODO: not sure
|
||||
|
||||
// TODO: I am not sure about this. Most of formats unknown for me.
|
||||
private static final String[] formats = {"mp3", "wav", "aac", "sbc", "msbc", "hwa", "cvsd", "pcm", "ape", "m4a", "flac", "opus", "ogg", "butt", "amr", "imy"};
|
||||
|
||||
public String getName() {
|
||||
return (formatIdx >= 0 && formatIdx < formats.length)?formats[formatIdx]:null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("FormatRestrictions{");
|
||||
sb.append("formatIdx=").append(formatIdx);
|
||||
sb.append(", sampleRate=").append(sampleRate);
|
||||
sb.append(", musicEncode=").append(musicEncode);
|
||||
sb.append(", bitrate=").append(bitrate);
|
||||
sb.append(", channels=").append(channels);
|
||||
sb.append(", unknownBitrate=").append(unknownBitrate);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MusicCapabilities {
|
||||
public short availableSpace = 0;
|
||||
public List<String> supportedFormats = null;
|
||||
public short maxMusicCount = 0;
|
||||
public short maxPlaylistCount = 0;
|
||||
public short currentMusicCount = 0; // TODO: not sure
|
||||
public byte unknown = 0; // TODO: not sure
|
||||
public List<FormatRestrictions> formatsRestrictions = null;
|
||||
public List<PageStruct> pageStruct = null;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("MusicCapabilities{");
|
||||
sb.append("availableSpace=").append(availableSpace);
|
||||
sb.append(", supportedFormats=").append(supportedFormats);
|
||||
sb.append(", maxMusicCount=").append(maxMusicCount);
|
||||
sb.append(", maxPlaylistCount=").append(maxPlaylistCount);
|
||||
sb.append(", currentMusicCount=").append(currentMusicCount);
|
||||
sb.append(", unknown=").append(unknown);
|
||||
sb.append(", formatsRestrictions=").append(formatsRestrictions);
|
||||
sb.append(", pageStruct=").append(pageStruct);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: I am not sure about this. Most of formats unknown for me.
|
||||
private static final String[] formatsByte0 = {"mp3", "wav", "aac", "sbc", "msbc", "hwa", "cvsd"};
|
||||
private static final String[] formatsByte1 = {"pcm", "ape", "m4a", "flac", "opus", "ogg", "butt"};
|
||||
private static final String[] formatsByte2 = {"amr", "imy"};
|
||||
|
||||
public static void parseNext(int dt, String[] info, List<String> res) {
|
||||
for (byte k = 0; k < info.length; k++) {
|
||||
if ((dt & (1 << k)) != 0) {
|
||||
res.add(info[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> parseFormats(List<Integer> data) {
|
||||
List<String> res = new ArrayList<>();
|
||||
|
||||
if (data.size() >= 1) {
|
||||
parseNext(data.get(0), formatsByte0, res);
|
||||
}
|
||||
|
||||
if (data.size() >= 2) {
|
||||
parseNext(data.get(1), formatsByte1, res);
|
||||
}
|
||||
|
||||
if (data.size() >= 3) {
|
||||
parseNext(data.get(2), formatsByte2, res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static List<String> parseFormatBits(byte[] formatBits) {
|
||||
if (formatBits.length == 0)
|
||||
return null;
|
||||
List<Integer> toDecode = new ArrayList<>();
|
||||
for (byte formatBit : formatBits) {
|
||||
int dt = formatBit & 0xFF;
|
||||
toDecode.add(dt);
|
||||
if ((dt & 128) == 0) break;
|
||||
}
|
||||
return parseFormats(toDecode);
|
||||
}
|
||||
}
|
@ -594,6 +594,12 @@ public class HuaweiPacket {
|
||||
return new MusicControl.MusicInfo.Response(paramsProvider).fromPacket(this);
|
||||
case MusicControl.Control.id:
|
||||
return new MusicControl.Control.Response(paramsProvider).fromPacket(this);
|
||||
case MusicControl.MusicInfoParams.id:
|
||||
return new MusicControl.MusicInfoParams.Response(paramsProvider).fromPacket(this);
|
||||
case MusicControl.UploadMusicFileInfo.id:
|
||||
return new MusicControl.UploadMusicFileInfo.UploadMusicFileInfoRequest(paramsProvider).fromPacket(this);
|
||||
case MusicControl.ExtendedMusicInfoParams.id:
|
||||
return new MusicControl.ExtendedMusicInfoParams.Response(paramsProvider).fromPacket(this);
|
||||
default:
|
||||
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||
return this;
|
||||
|
@ -16,12 +16,22 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiMusicUtils.parseFormatBits;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiMusicUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
|
||||
public class MusicControl {
|
||||
public static final byte id = 0x25;
|
||||
|
||||
|
||||
// TODO: should this be in HuaweiConstants?
|
||||
public static final int successValue = 0x000186A0;
|
||||
|
||||
@ -189,4 +199,167 @@ public class MusicControl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class UploadMusicFileInfo {
|
||||
public static final int id = 0x09;
|
||||
|
||||
public static class UploadMusicFileInfoRequest extends HuaweiPacket {
|
||||
public short songIndex;
|
||||
public String songFileName;
|
||||
|
||||
public UploadMusicFileInfoRequest(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
this.songIndex = this.tlv.getShort(0x01);
|
||||
this.songFileName = this.tlv.getString(0x02);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UploadMusicFileInfoResponse extends HuaweiPacket {
|
||||
public UploadMusicFileInfoResponse(ParamsProvider paramsProvider, short songIndex, String songName, String songArtist) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = MusicControl.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV().put(0x01, songIndex).put(0x03, songName).put(0x04, songArtist);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MusicInfoParams {
|
||||
public static final byte id = 0x04;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
|
||||
public Request(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = MusicControl.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01)
|
||||
.put(0x02)
|
||||
.put(0x03);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public HuaweiMusicUtils.MusicCapabilities params = new HuaweiMusicUtils.MusicCapabilities();
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
|
||||
//TODO: unknown TLV
|
||||
// if (this.tlv.contains(0x01))
|
||||
// LOG.info("Unknown: " + this.tlv.getShort(0x01));
|
||||
|
||||
if (this.tlv.contains(0x02))
|
||||
params.availableSpace = this.tlv.getShort(0x02);
|
||||
if (this.tlv.contains(0x03)) {
|
||||
byte[] formatBits = this.tlv.getBytes(0x03);
|
||||
params.supportedFormats = parseFormatBits(formatBits);
|
||||
}
|
||||
if (this.tlv.contains(0x04))
|
||||
params.maxMusicCount = this.tlv.getShort(0x04);
|
||||
if (this.tlv.contains(0x05))
|
||||
params.currentMusicCount = this.tlv.getByte(0x05);
|
||||
|
||||
if (this.tlv.contains(0x86)) {
|
||||
params.pageStruct = new ArrayList<>();
|
||||
List<HuaweiTLV> subTlvs = this.tlv.getObject(0x86).getObjects(0x87);
|
||||
for (HuaweiTLV subTlv : subTlvs) {
|
||||
HuaweiMusicUtils.PageStruct pageStruct = new HuaweiMusicUtils.PageStruct();
|
||||
if (subTlv.contains(0x08))
|
||||
pageStruct.startIndex = subTlv.getShort(0x08);
|
||||
if (subTlv.contains(0x09))
|
||||
pageStruct.endIndex = subTlv.getShort(0x09);
|
||||
if (subTlv.contains(0x0a))
|
||||
pageStruct.count = subTlv.getShort(0x0a);
|
||||
if (subTlv.contains(0x0b))
|
||||
pageStruct.hashCode = subTlv.getBytes(0x0b);
|
||||
params.pageStruct.add(pageStruct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExtendedMusicInfoParams {
|
||||
public static final byte id = 0x0d;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
|
||||
public Request(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
this.serviceId = MusicControl.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01)
|
||||
.put(0x02)
|
||||
.put(0x03)
|
||||
.put(0x04)
|
||||
.put(0x05);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public HuaweiMusicUtils.MusicCapabilities params = new HuaweiMusicUtils.MusicCapabilities();
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
if (this.tlv.contains(0x01))
|
||||
params.availableSpace = this.tlv.getShort(0x01);
|
||||
if (this.tlv.contains(0x02)) {
|
||||
byte[] formatBits = this.tlv.getBytes(0x02);
|
||||
params.supportedFormats = parseFormatBits(formatBits);
|
||||
}
|
||||
if (this.tlv.contains(0x03))
|
||||
params.maxMusicCount = this.tlv.getShort(0x03);
|
||||
if (this.tlv.contains(0x04))
|
||||
params.maxPlaylistCount = this.tlv.getShort(0x04);
|
||||
if (this.tlv.contains(0x05))
|
||||
params.unknown = this.tlv.getByte(0x05);
|
||||
|
||||
if (this.tlv.contains(0x86)) {
|
||||
params.formatsRestrictions = new ArrayList<>();
|
||||
List<HuaweiTLV> subTlvs = this.tlv.getObject(0x86).getObjects(0x87);
|
||||
for (HuaweiTLV subTlv : subTlvs) {
|
||||
HuaweiMusicUtils.FormatRestrictions restriction = new HuaweiMusicUtils.FormatRestrictions();
|
||||
if (subTlv.contains(0x08))
|
||||
restriction.formatIdx = subTlv.getByte(0x08);
|
||||
if (subTlv.contains(0x09))
|
||||
restriction.sampleRate = subTlv.getInteger(0x09);
|
||||
if (subTlv.contains(0x0a))
|
||||
restriction.musicEncode = subTlv.getByte(0x0a);
|
||||
if (subTlv.contains(0x0b))
|
||||
restriction.bitrate = subTlv.getShort(0x0b);
|
||||
if (subTlv.contains(0x0c))
|
||||
restriction.channels = subTlv.getByte(0x0c);
|
||||
if (subTlv.contains(0x0d))
|
||||
restriction.unknownBitrate = subTlv.getShort(0x0b);
|
||||
params.formatsRestrictions.add(restriction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +343,12 @@ public class AsynchronousResponse {
|
||||
this.support.sendSetMusic();
|
||||
}, 100);
|
||||
}
|
||||
} else if (response.commandId == MusicControl.UploadMusicFileInfo.id) {
|
||||
if (!(response instanceof MusicControl.UploadMusicFileInfo.UploadMusicFileInfoRequest))
|
||||
throw new Request.ResponseTypeMismatchException(response, MusicControl.UploadMusicFileInfo.UploadMusicFileInfoRequest.class);
|
||||
|
||||
MusicControl.UploadMusicFileInfo.UploadMusicFileInfoRequest resp = (MusicControl.UploadMusicFileInfo.UploadMusicFileInfoRequest) response;
|
||||
support.getHuaweiMusicManager().uploadMusicInfo(resp.songIndex, resp.songFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,17 @@
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.MediaExtractor;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.media.MediaFormat;
|
||||
import android.net.Uri;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -51,8 +58,11 @@ public class HuaweiFwHelper {
|
||||
Bitmap previewBitmap;
|
||||
HuaweiWatchfaceManager.WatchfaceDescription watchfaceDescription;
|
||||
HuaweiAppManager.AppConfig appConfig;
|
||||
HuaweiMusicManager.AudioInfo musicInfo;
|
||||
Context mContext;
|
||||
|
||||
|
||||
|
||||
public HuaweiFwHelper(final Uri uri, final Context context) {
|
||||
|
||||
this.uri = uri;
|
||||
@ -69,7 +79,9 @@ public class HuaweiFwHelper {
|
||||
}
|
||||
|
||||
private void parseFile() {
|
||||
if(parseAsApp()) {
|
||||
if (parseAsMusic()) {
|
||||
fileType = FileUpload.Filetype.music;
|
||||
} else if (parseAsApp()) {
|
||||
assert appConfig.bundleName != null;
|
||||
fileType = FileUpload.Filetype.app;
|
||||
} else if (parseAsWatchFace()) {
|
||||
@ -79,31 +91,136 @@ public class HuaweiFwHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private String getNameWithoutExtension(String fileName) {
|
||||
return fileName.indexOf(".") > 0?fileName.substring(0, fileName.lastIndexOf(".")): fileName;
|
||||
}
|
||||
|
||||
private String getExtension(String fileName) {
|
||||
if (TextUtils.isEmpty(fileName)) {
|
||||
return null;
|
||||
}
|
||||
int lastIndexOf = fileName.lastIndexOf(".");
|
||||
if (lastIndexOf >= 0 && lastIndexOf + 1 < fileName.length()) {
|
||||
return fileName.substring(lastIndexOf + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private HuaweiMusicManager.AudioInfo getAudioInfo(Uri selectedUri) throws IOException {
|
||||
ContentResolver contentResolver = mContext.getContentResolver();
|
||||
String[] filePathColumn = {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
|
||||
|
||||
Cursor cursor = contentResolver.query(selectedUri, filePathColumn, null, null, null);
|
||||
if(cursor == null)
|
||||
return null;
|
||||
cursor.moveToFirst();
|
||||
|
||||
int fileNameIndex = cursor.getColumnIndex(filePathColumn[0]);
|
||||
String fileName = cursor.getString(fileNameIndex);
|
||||
int fileSizeIndex = cursor.getColumnIndex(filePathColumn[1]);
|
||||
long fileSize = cursor.getLong(fileSizeIndex);
|
||||
cursor.close();
|
||||
|
||||
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
|
||||
mmr.setDataSource(mContext, selectedUri);
|
||||
|
||||
String title = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
|
||||
String artist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
|
||||
|
||||
if(TextUtils.isEmpty(title)) {
|
||||
title = getNameWithoutExtension(fileName);
|
||||
}
|
||||
if(TextUtils.isEmpty(artist)) {
|
||||
artist = "Unknown";
|
||||
}
|
||||
|
||||
MediaExtractor mex = new MediaExtractor();
|
||||
mex.setDataSource(mContext, selectedUri, null);
|
||||
|
||||
|
||||
MediaFormat mf = mex.getTrackFormat(0);
|
||||
|
||||
int bitrate = -1; // TODO: calculate or get bitrate
|
||||
int sampleRate = mf.getInteger(MediaFormat.KEY_SAMPLE_RATE);
|
||||
int channels = mf.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
|
||||
long duration = mf.getLong(MediaFormat.KEY_DURATION);
|
||||
|
||||
LOG.info("bitRate: " + bitrate);
|
||||
LOG.info("sampleRate: " + sampleRate);
|
||||
LOG.info("channelCount: " + channels);
|
||||
LOG.info("duration: " + duration);
|
||||
|
||||
String extension = getExtension(fileName);
|
||||
if(!TextUtils.isEmpty(extension)) {
|
||||
extension = extension.toLowerCase();
|
||||
}
|
||||
|
||||
HuaweiMusicManager.AudioInfo audioInfo = new HuaweiMusicManager.AudioInfo(fileName, fileSize, title, artist, extension);
|
||||
audioInfo.setCharacteristics(duration, sampleRate, bitrate, (byte) channels);
|
||||
|
||||
return audioInfo;
|
||||
}
|
||||
|
||||
private byte[] getFileData(UriHelper uriHelper) throws IOException {
|
||||
InputStream inputStream = uriHelper.openInputStream();
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
int nRead;
|
||||
byte[] data = new byte[1000];
|
||||
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
buffer.flush();
|
||||
inputStream.close();
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
boolean parseAsMusic() {
|
||||
try {
|
||||
final UriHelper uriHelper = UriHelper.get(uri, this.mContext);
|
||||
|
||||
String mimeType = mContext.getContentResolver().getType(uri);
|
||||
LOG.info("File mime type: {}", mimeType);
|
||||
|
||||
if(mimeType == null || !mimeType.startsWith("audio/"))
|
||||
return false;
|
||||
|
||||
musicInfo = getAudioInfo(uri);
|
||||
if(musicInfo == null)
|
||||
return false;
|
||||
|
||||
musicInfo.setMimeType(mimeType);
|
||||
|
||||
byte[] musicData = getFileData(uriHelper);
|
||||
|
||||
fileName = musicInfo.getFileName();
|
||||
fw = musicData;
|
||||
fileSize = fw.length;
|
||||
|
||||
return true;
|
||||
} catch (FileNotFoundException e) {
|
||||
LOG.error("Music: File was not found {}", e.getMessage());
|
||||
} catch (IOException e) {
|
||||
LOG.error("Music: General IO error occurred {}", e.getMessage());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Music: Unknown error occurred", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
boolean parseAsApp() {
|
||||
|
||||
try {
|
||||
final UriHelper uriHelper = UriHelper.get(uri, this.mContext);
|
||||
InputStream inputStream = uriHelper.openInputStream();
|
||||
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
int nRead;
|
||||
byte[] data = new byte[4];
|
||||
|
||||
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
|
||||
buffer.flush();
|
||||
byte[] appData = buffer.toByteArray();
|
||||
|
||||
inputStream.close();
|
||||
byte[] appData = getFileData(uriHelper);
|
||||
|
||||
HuaweiBinAppParser app = new HuaweiBinAppParser();
|
||||
app.parseData(appData);
|
||||
|
||||
byte[] config = app.getEntryContent("config.json");
|
||||
if(config == null)
|
||||
if (config == null)
|
||||
return false;
|
||||
appConfig = new HuaweiAppManager.AppConfig(new String(config));
|
||||
fileName = app.getPackageName() + "_INSTALL"; //TODO: INSTALL or UPDATE suffix
|
||||
@ -112,22 +229,21 @@ public class HuaweiFwHelper {
|
||||
fileSize = fw.length;
|
||||
|
||||
byte[] icon = app.getEntryContent("icon_small.png");
|
||||
if(icon != null) {
|
||||
if (icon != null) {
|
||||
previewBitmap = BitmapFactory.decodeByteArray(icon, 0, icon.length);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
LOG.error("The app file was not found.", e);
|
||||
LOG.error("App: File was not found{}", e.getMessage());
|
||||
} catch (IOException e) {
|
||||
LOG.error("General IO error occurred.", e);
|
||||
LOG.error("App: General IO error occurred {}", e.getMessage());
|
||||
} catch (HuaweiBinAppParser.HuaweiBinAppParseError e) {
|
||||
LOG.error("Error parsing app File", e);
|
||||
LOG.error("App: Error parsing app File {}", e.getMessage());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Unknown error occurred.", e);
|
||||
LOG.error("App: Unknown error occurred", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -172,7 +288,7 @@ public class HuaweiFwHelper {
|
||||
|
||||
byte[] watchfaceZip = watchfacePackage.getFileFromZip("com.huawei.watchface");
|
||||
try {
|
||||
GBZipFile watchfaceBinZip = new GBZipFile(watchfaceZip);
|
||||
GBZipFile watchfaceBinZip = new GBZipFile(watchfaceZip);
|
||||
fw = watchfaceBinZip.getFileFromZip("watchface.bin");
|
||||
} catch (ZipFileException e) {
|
||||
LOG.error("Unable to get watchfaceZip, it seems older already watchface.bin");
|
||||
@ -182,13 +298,13 @@ public class HuaweiFwHelper {
|
||||
isWatchface = true;
|
||||
|
||||
} catch (ZipFileException e) {
|
||||
LOG.error("Unable to read watchface file.", e);
|
||||
LOG.error("Watchface: Unable to read file {}", e.getMessage());
|
||||
} catch (FileNotFoundException e) {
|
||||
LOG.error("The watchface file was not found.", e);
|
||||
LOG.error("Watchface: File was not found {}", e.getMessage());
|
||||
} catch (IOException e) {
|
||||
LOG.error("General IO error occurred.", e);
|
||||
LOG.error("Watchface: General IO error occurred {}", e.getMessage());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Unknown error occurred.", e);
|
||||
LOG.error("Watchface: Unknown error occurred", e);
|
||||
}
|
||||
|
||||
return isWatchface;
|
||||
@ -202,8 +318,12 @@ public class HuaweiFwHelper {
|
||||
return fileType == FileUpload.Filetype.app;
|
||||
}
|
||||
|
||||
public boolean isMusic() {
|
||||
return fileType == FileUpload.Filetype.music;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return isWatchface() || isAPP();
|
||||
return isWatchface() || isAPP() || isMusic();
|
||||
}
|
||||
|
||||
public Bitmap getPreviewBitmap() {
|
||||
@ -218,6 +338,10 @@ public class HuaweiFwHelper {
|
||||
return appConfig;
|
||||
}
|
||||
|
||||
public HuaweiMusicManager.AudioInfo getMusicInfo() {
|
||||
return musicInfo;
|
||||
}
|
||||
|
||||
public byte getFileType() {
|
||||
return fileType;
|
||||
}
|
||||
|
@ -0,0 +1,128 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendUploadMusicFileInfoResponse;
|
||||
|
||||
public class HuaweiMusicManager {
|
||||
static Logger LOG = LoggerFactory.getLogger(HuaweiMusicManager.class);
|
||||
|
||||
public static class AudioInfo {
|
||||
private final String fileName;
|
||||
private final long fileSize;
|
||||
private final String title;
|
||||
private final String artist;
|
||||
private final String extension;
|
||||
|
||||
private String mimeType;
|
||||
|
||||
private long duration;
|
||||
private int sampleRate;
|
||||
private int bitrate;
|
||||
private byte channels;
|
||||
|
||||
//public byte musicEncode = -1; // TODO: not sure
|
||||
//public short unknownBitrate = -1; // TODO: not sure
|
||||
|
||||
public AudioInfo(String fileName, long fileSize, String title, String artist, String extension) {
|
||||
this.fileName = fileName;
|
||||
this.fileSize = fileSize;
|
||||
this.title = title;
|
||||
this.artist = artist;
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public long getFileSize() { return fileSize;}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
public void setMimeType(String mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
public void setCharacteristics(long duration, int sampleRate, int bitrate, byte channels) {
|
||||
this.duration = duration;
|
||||
this.sampleRate = sampleRate;
|
||||
this.bitrate = bitrate;
|
||||
this.channels = channels;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public int getSampleRate() {
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
public int getBitrate() {
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
public byte getChannels() {
|
||||
return channels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("AudioInfo{");
|
||||
sb.append("fileName='").append(fileName).append('\'');
|
||||
sb.append("fileSize='").append(fileSize).append('\'');
|
||||
sb.append(", title='").append(title).append('\'');
|
||||
sb.append(", artist='").append(artist).append('\'');
|
||||
sb.append(", mimeType='").append(mimeType).append('\'');
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private final HuaweiSupportProvider support;
|
||||
|
||||
private AudioInfo currentMusicInfo;
|
||||
|
||||
|
||||
public HuaweiMusicManager(HuaweiSupportProvider support) {
|
||||
this.support = support;
|
||||
}
|
||||
|
||||
|
||||
public void addUploadMusic(AudioInfo audioInfo) {
|
||||
currentMusicInfo = audioInfo;
|
||||
}
|
||||
|
||||
public void uploadMusicInfo(short songIndex, String fileName) {
|
||||
AudioInfo current = currentMusicInfo;
|
||||
if(current == null || (!current.getFileName().equals(fileName))) {
|
||||
LOG.error("Upload file info does not exist.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SendUploadMusicFileInfoResponse sendUploadMusicFileInfoResponse = new SendUploadMusicFileInfoResponse(support,
|
||||
songIndex, current.getTitle(), current.getArtist());
|
||||
sendUploadMusicFileInfoResponse.doPerform();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Could not send sendUploadMusicFileInfoResponse", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -105,6 +105,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetA
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetContactsCount;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetEventAlarmList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetGpsParameterRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetExtendedMusicInfoParams;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetMusicInfoParams;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetNotificationConstraintsRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetSmartAlarmList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfaceParams;
|
||||
@ -268,6 +270,8 @@ public class HuaweiSupportProvider {
|
||||
|
||||
protected HuaweiEphemerisManager huaweiEphemerisManager = new HuaweiEphemerisManager(this);
|
||||
|
||||
protected HuaweiMusicManager huaweiMusicManager = new HuaweiMusicManager(this);
|
||||
|
||||
//TODO: we need only one instance of manager and all it services.
|
||||
protected HuaweiP2PManager huaweiP2PManager = new HuaweiP2PManager(this);
|
||||
|
||||
@ -299,6 +303,10 @@ public class HuaweiSupportProvider {
|
||||
return huaweiEphemerisManager;
|
||||
}
|
||||
|
||||
public HuaweiMusicManager getHuaweiMusicManager() {
|
||||
return huaweiMusicManager;
|
||||
}
|
||||
|
||||
public HuaweiSupportProvider(HuaweiBRSupport support) {
|
||||
this.brSupport = support;
|
||||
}
|
||||
@ -824,6 +832,8 @@ public class HuaweiSupportProvider {
|
||||
initRequestQueue.add(new GetWatchfaceParams(this));
|
||||
initRequestQueue.add(new SendCameraRemoteSetupEvent(this, CameraRemote.CameraRemoteSetup.Request.Event.ENABLE_CAMERA));
|
||||
initRequestQueue.add(new GetAppInfoParams(this));
|
||||
initRequestQueue.add(new GetMusicInfoParams(this));
|
||||
initRequestQueue.add(new GetExtendedMusicInfoParams(this));
|
||||
initRequestQueue.add(new SetActivateOnLiftRequest(this));
|
||||
initRequestQueue.add(new SetWearLocationRequest(this));
|
||||
initRequestQueue.add(new SetNavigateOnRotateRequest(this));
|
||||
@ -1959,6 +1969,10 @@ public class HuaweiSupportProvider {
|
||||
|
||||
HuaweiUploadManager.FileUploadInfo fileInfo = new HuaweiUploadManager.FileUploadInfo();
|
||||
|
||||
if(huaweiFwHelper.isMusic()) {
|
||||
getHuaweiMusicManager().addUploadMusic(huaweiFwHelper.getMusicInfo());
|
||||
}
|
||||
|
||||
fileInfo.setFileType(huaweiFwHelper.getFileType());
|
||||
if (huaweiFwHelper.isWatchface()) {
|
||||
fileInfo.setFileName(huaweiWatchfaceManager.getRandomName());
|
||||
@ -1989,10 +2003,14 @@ public class HuaweiSupportProvider {
|
||||
if (code == 140004) {
|
||||
LOG.error("Too many watchfaces installed");
|
||||
HuaweiSupportProvider.this.handleGBDeviceEvent(new GBDeviceEventDisplayMessage(HuaweiSupportProvider.this.getContext().getString(R.string.cannot_upload_watchface_too_many_watchfaces_installed), Toast.LENGTH_LONG, GB.ERROR));
|
||||
} else if (code == 140008) {
|
||||
LOG.error("File already exists");
|
||||
HuaweiSupportProvider.this.handleGBDeviceEvent(new GBDeviceEventDisplayMessage("File already exists", Toast.LENGTH_LONG, GB.ERROR)); //TODO: localization
|
||||
} else if (code == 140009) {
|
||||
LOG.error("Insufficient space for upload");
|
||||
HuaweiSupportProvider.this.handleGBDeviceEvent(new GBDeviceEventDisplayMessage(HuaweiSupportProvider.this.getContext().getString(R.string.insufficient_space_for_upload), Toast.LENGTH_LONG, GB.ERROR));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.MusicControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetExtendedMusicInfoParams extends Request {
|
||||
private final Logger LOG = LoggerFactory.getLogger(GetExtendedMusicInfoParams.class);
|
||||
public GetExtendedMusicInfoParams(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = MusicControl.id;
|
||||
this.commandId = MusicControl.ExtendedMusicInfoParams.id;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestSupported() {
|
||||
return supportProvider.getHuaweiCoordinator().supportsMusicUploading();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws Request.RequestCreationException {
|
||||
try {
|
||||
return new MusicControl.ExtendedMusicInfoParams.Request(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new Request.RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws Request.ResponseParseException {
|
||||
LOG.info("MusicControl.ExtendedMusicInfoParams processResponse");
|
||||
if (!(receivedPacket instanceof MusicControl.ExtendedMusicInfoParams.Response))
|
||||
throw new Request.ResponseTypeMismatchException(receivedPacket, MusicControl.ExtendedMusicInfoParams.Response.class);
|
||||
|
||||
MusicControl.ExtendedMusicInfoParams.Response resp = (MusicControl.ExtendedMusicInfoParams.Response)(receivedPacket);
|
||||
supportProvider.getHuaweiCoordinator().setExtendedMusicInfoParams(resp.params);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.MusicControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetMusicInfoParams extends Request {
|
||||
private final Logger LOG = LoggerFactory.getLogger(GetMusicInfoParams.class);
|
||||
public GetMusicInfoParams(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = MusicControl.id;
|
||||
this.commandId = MusicControl.MusicInfoParams.id;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestSupported() {
|
||||
return supportProvider.getHuaweiCoordinator().supportsMusicUploading();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws Request.RequestCreationException {
|
||||
try {
|
||||
return new MusicControl.MusicInfoParams.Request(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new Request.RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws Request.ResponseParseException {
|
||||
LOG.info("MusicControl.MusicInfoParams processResponse");
|
||||
if (!(receivedPacket instanceof MusicControl.MusicInfoParams.Response))
|
||||
throw new Request.ResponseTypeMismatchException(receivedPacket, MusicControl.MusicInfoParams.Response.class);
|
||||
|
||||
MusicControl.MusicInfoParams.Response resp = (MusicControl.MusicInfoParams.Response)(receivedPacket);
|
||||
supportProvider.getHuaweiCoordinator().setMusicInfoParams(resp.params);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.MusicControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SendUploadMusicFileInfoResponse extends Request {
|
||||
short songIndex;
|
||||
String songName;
|
||||
String songArtist;
|
||||
|
||||
|
||||
public SendUploadMusicFileInfoResponse(HuaweiSupportProvider support, short songIndex, String songName, String songArtist) {
|
||||
super(support);
|
||||
this.serviceId = MusicControl.id;
|
||||
this.commandId = MusicControl.UploadMusicFileInfo.id;
|
||||
this.songIndex = songIndex;
|
||||
this.songName = songName;
|
||||
this.songArtist = songArtist;
|
||||
this.addToResponse = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws Request.RequestCreationException {
|
||||
try {
|
||||
return new MusicControl.UploadMusicFileInfo.UploadMusicFileInfoResponse(this.paramsProvider, this.songIndex, this.songName, this.songArtist).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new Request.RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user