mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-25 19:36:50 +01:00
Pebble: try to install app metadata on FW 3.x (untested)
This commit is contained in:
parent
2e3de0cd0f
commit
e28d6fa7cb
@ -70,7 +70,7 @@ public class PBWInstallHandler implements InstallHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GBDeviceApp app = mPBWReader.getGBDeviceApp();
|
GBDeviceApp app = mPBWReader.getGBDeviceApp();
|
||||||
File pbwFile = new File(mPBWReader.getUri().getPath());
|
File pbwFile = new File(mUri.getPath());
|
||||||
try {
|
try {
|
||||||
File destDir = new File(FileUtils.getExternalFilesDir() + "/pbw-cache");
|
File destDir = new File(FileUtils.getExternalFilesDir() + "/pbw-cache");
|
||||||
destDir.mkdirs();
|
destDir.mkdirs();
|
||||||
|
@ -14,6 +14,8 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -50,6 +52,10 @@ public class PBWReader {
|
|||||||
private boolean isFirmware = false;
|
private boolean isFirmware = false;
|
||||||
private boolean isValid = false;
|
private boolean isValid = false;
|
||||||
private String hwRevision = null;
|
private String hwRevision = null;
|
||||||
|
private short mSdkVersion;
|
||||||
|
private short mAppVersion;
|
||||||
|
private int mIconId;
|
||||||
|
private int mFlags;
|
||||||
|
|
||||||
public PBWReader(Uri uri, Context context, String platform) {
|
public PBWReader(Uri uri, Context context, String platform) {
|
||||||
String platformDir = "";
|
String platformDir = "";
|
||||||
@ -70,7 +76,7 @@ public class PBWReader {
|
|||||||
}
|
}
|
||||||
ZipInputStream zis = new ZipInputStream(fin);
|
ZipInputStream zis = new ZipInputStream(fin);
|
||||||
ZipEntry ze;
|
ZipEntry ze;
|
||||||
pebbleInstallables = new ArrayList<PebbleInstallable>();
|
pebbleInstallables = new ArrayList<>();
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int count;
|
int count;
|
||||||
try {
|
try {
|
||||||
@ -149,6 +155,26 @@ public class PBWReader {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (fileName.equals(platformDir + "pebble-app.bin")) {
|
||||||
|
zis.read(buffer, 0, 108);
|
||||||
|
byte[] tmp_buf = new byte[32];
|
||||||
|
ByteBuffer buf = ByteBuffer.wrap(buffer);
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.getLong(); // header, TODO: verifiy
|
||||||
|
buf.getShort(); // struct version, TODO: verify
|
||||||
|
mSdkVersion = buf.getShort();
|
||||||
|
mAppVersion = buf.getShort();
|
||||||
|
buf.getShort(); // size
|
||||||
|
buf.getInt(); // offset
|
||||||
|
buf.getInt(); // crc
|
||||||
|
buf.get(tmp_buf, 0, 32); // app name
|
||||||
|
buf.get(tmp_buf, 0, 32); // author
|
||||||
|
mIconId = buf.getInt();
|
||||||
|
LOG.info("got icon id from pebble-app.bin: " + mIconId);
|
||||||
|
buf.getInt(); // symbol table addr
|
||||||
|
mFlags = buf.getInt();
|
||||||
|
LOG.info("got flags from pebble-app.bin: " + mFlags);
|
||||||
|
// more follows but, not interesting for us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zis.close();
|
zis.close();
|
||||||
@ -206,7 +232,19 @@ public class PBWReader {
|
|||||||
return hwRevision;
|
return hwRevision;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri getUri() {
|
public short getSdkVersion() {
|
||||||
return uri;
|
return mSdkVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getAppVersion() {
|
||||||
|
return mAppVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFlags() {
|
||||||
|
return mFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconId() {
|
||||||
|
return mIconId;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,6 +26,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagem
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PBWReader;
|
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PBWReader;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleInstallable;
|
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleInstallable;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.bt.GBDeviceIoThread;
|
import nodomain.freeyourgadget.gadgetbridge.service.bt.GBDeviceIoThread;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.bt.GBDeviceProtocol;
|
import nodomain.freeyourgadget.gadgetbridge.service.bt.GBDeviceProtocol;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
@ -42,8 +43,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
private boolean mIsConnected = false;
|
private boolean mIsConnected = false;
|
||||||
private boolean mIsInstalling = false;
|
private boolean mIsInstalling = false;
|
||||||
private int mConnectionAttempts = 0;
|
private int mConnectionAttempts = 0;
|
||||||
/* app installation */
|
private boolean mForceUntested = false;
|
||||||
private Uri mInstallURI = null;
|
|
||||||
private PBWReader mPBWReader = null;
|
private PBWReader mPBWReader = null;
|
||||||
private int mAppInstallToken = -1;
|
private int mAppInstallToken = -1;
|
||||||
private ZipInputStream mZis = null;
|
private ZipInputStream mZis = null;
|
||||||
@ -84,7 +84,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
|
|
||||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
mPebbleProtocol.setForceProtocol(sharedPrefs.getBoolean("pebble_force_protocol", false));
|
mPebbleProtocol.setForceProtocol(sharedPrefs.getBoolean("pebble_force_protocol", false));
|
||||||
|
mForceUntested = sharedPrefs.getBoolean("pebble_force_untested", false);
|
||||||
gbDevice.setState(GBDevice.State.CONNECTED);
|
gbDevice.setState(GBDevice.State.CONNECTED);
|
||||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||||
|
|
||||||
@ -375,9 +375,8 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mIsInstalling = true;
|
mIsInstalling = true;
|
||||||
mInstallURI = uri;
|
|
||||||
|
|
||||||
mPBWReader = new PBWReader(mInstallURI, getContext(), gbDevice.getHardwareVersion().equals("dvt") ? "basalt" : "aplite");
|
mPBWReader = new PBWReader(uri, getContext(), gbDevice.getHardwareVersion().equals("dvt") ? "basalt" : "aplite");
|
||||||
mPebbleInstallables = mPBWReader.getPebbleInstallables();
|
mPebbleInstallables = mPBWReader.getPebbleInstallables();
|
||||||
mCurrentInstallableIndex = 0;
|
mCurrentInstallableIndex = 0;
|
||||||
|
|
||||||
@ -399,8 +398,12 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
mInstallSlot = 0;
|
mInstallSlot = 0;
|
||||||
mInstallState = PebbleAppInstallState.START_INSTALL;
|
mInstallState = PebbleAppInstallState.START_INSTALL;
|
||||||
} else {
|
} else {
|
||||||
writeInstallApp(mPebbleProtocol.encodeAppDelete(mPBWReader.getGBDeviceApp().getUUID()));
|
GBDeviceApp app = mPBWReader.getGBDeviceApp();
|
||||||
|
writeInstallApp(mPebbleProtocol.encodeAppDelete(app.getUUID()));
|
||||||
mInstallState = PebbleAppInstallState.WAIT_SLOT;
|
mInstallState = PebbleAppInstallState.WAIT_SLOT;
|
||||||
|
if (mPebbleProtocol.isFw3x && mForceUntested) {
|
||||||
|
writeInstallApp(mPebbleProtocol.encodeInstallMetadata(app.getUUID(), app.getName(), mPBWReader.getAppVersion(), mPBWReader.getSdkVersion()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,15 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
|
|
||||||
static final byte APPRUNSTATE_START = 1;
|
static final byte APPRUNSTATE_START = 1;
|
||||||
|
|
||||||
|
static final byte BLOBDB_INSERT = 1;
|
||||||
|
static final byte BLOBDB_DELETE = 4;
|
||||||
|
static final byte BLOBDB_CLEAR = 5;
|
||||||
|
|
||||||
|
static final byte BLOBDB_PIN = 1;
|
||||||
|
static final byte BLOBDB_APP = 2;
|
||||||
|
static final byte BLOBDB_REMINDER = 3;
|
||||||
|
static final byte BLOBDB_NOTIFICATION = 4;
|
||||||
|
|
||||||
static final byte NOTIFICATION_EMAIL = 0;
|
static final byte NOTIFICATION_EMAIL = 0;
|
||||||
static final byte NOTIFICATION_SMS = 1;
|
static final byte NOTIFICATION_SMS = 1;
|
||||||
static final byte NOTIFICATION_TWITTER = 2;
|
static final byte NOTIFICATION_TWITTER = 2;
|
||||||
@ -179,6 +188,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
static final short LENGTH_UPLOADCOMPLETE = 5;
|
static final short LENGTH_UPLOADCOMPLETE = 5;
|
||||||
static final short LENGTH_UPLOADCANCEL = 5;
|
static final short LENGTH_UPLOADCANCEL = 5;
|
||||||
|
|
||||||
|
static final byte LENGTH_UUID = 16;
|
||||||
|
|
||||||
private static final String[] hwRevisions = {"unknown", "ev1", "ev2", "ev2_3", "ev2_4", "v1_5", "v2_0", "evt2", "dvt"};
|
private static final String[] hwRevisions = {"unknown", "ev1", "ev2", "ev2_3", "ev2_4", "v1_5", "v2_0", "evt2", "dvt"};
|
||||||
private static Random mRandom = new Random();
|
private static Random mRandom = new Random();
|
||||||
|
|
||||||
@ -406,11 +417,11 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
// blobdb - 23 bytes
|
// blobdb - 23 bytes
|
||||||
buf.put((byte) 0x01); // insert
|
buf.put(BLOBDB_INSERT);
|
||||||
buf.putShort((short) mRandom.nextInt()); // token
|
buf.putShort((short) mRandom.nextInt()); // token
|
||||||
buf.put((byte) 0x04); // db id (0x04 = notification)
|
buf.put(BLOBDB_NOTIFICATION);
|
||||||
buf.put((byte) 16); // uuid length
|
buf.put(LENGTH_UUID); // uuid length
|
||||||
byte[] uuid_buf = new byte[16];
|
byte[] uuid_buf = new byte[LENGTH_UUID];
|
||||||
mRandom.nextBytes(uuid_buf);
|
mRandom.nextBytes(uuid_buf);
|
||||||
buf.put(uuid_buf); // random UUID
|
buf.put(uuid_buf); // random UUID
|
||||||
buf.putShort(pin_length); // length of the encapsulated data
|
buf.putShort(pin_length); // length of the encapsulated data
|
||||||
@ -458,6 +469,47 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
return buf.array();
|
return buf.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] encodeInstallMetadata(UUID uuid, String appName, short appVersion, short sdkVersion) {
|
||||||
|
// Calculate length first
|
||||||
|
final short BLOBDB_LENGTH = 23;
|
||||||
|
final short METADATA_LENGTH = 126;
|
||||||
|
|
||||||
|
final short length = (short) (BLOBDB_LENGTH + METADATA_LENGTH);
|
||||||
|
|
||||||
|
byte[] name_buf = new byte[96];
|
||||||
|
System.arraycopy(appName.getBytes(), 0, name_buf, 0, appName.length());
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(length + LENGTH_PREFIX);
|
||||||
|
|
||||||
|
// Encode Prefix
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN);
|
||||||
|
buf.putShort(length);
|
||||||
|
buf.putShort(ENDPOINT_BLOBDB);
|
||||||
|
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
// blobdb - 23 bytes
|
||||||
|
buf.put(BLOBDB_INSERT); // insert
|
||||||
|
buf.putShort((short) mRandom.nextInt()); // token
|
||||||
|
buf.put(BLOBDB_APP);
|
||||||
|
buf.put(LENGTH_UUID);
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN);
|
||||||
|
buf.putLong(uuid.getMostSignificantBits()); // watchapp uuid
|
||||||
|
buf.putLong(uuid.getLeastSignificantBits());
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.putShort(METADATA_LENGTH); // length of the encapsulated data
|
||||||
|
buf.order(ByteOrder.BIG_ENDIAN);
|
||||||
|
buf.putLong(uuid.getMostSignificantBits()); // watchapp uuid
|
||||||
|
buf.putLong(uuid.getLeastSignificantBits());
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.putInt(1); // icon_id
|
||||||
|
buf.putShort(appVersion);
|
||||||
|
buf.putShort(sdkVersion);
|
||||||
|
buf.put((byte) 0); // app_face_bgcolor
|
||||||
|
buf.put((byte) 0); // app_face_template_id
|
||||||
|
buf.put(name_buf); // 96 bytes
|
||||||
|
|
||||||
|
return buf.array();
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] encodeGetTime() {
|
public byte[] encodeGetTime() {
|
||||||
return encodeSimpleMessage(ENDPOINT_TIME, TIME_GETTIME);
|
return encodeSimpleMessage(ENDPOINT_TIME, TIME_GETTIME);
|
||||||
}
|
}
|
||||||
@ -762,7 +814,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] encodeApplicationMessagePush(short endpoint, UUID uuid, ArrayList<Pair<Integer, Object>> pairs) {
|
byte[] encodeApplicationMessagePush(short endpoint, UUID uuid, ArrayList<Pair<Integer, Object>> pairs) {
|
||||||
int length = 16 + 3; // UUID + (PUSH + id + length of dict)
|
int length = LENGTH_UUID + 3; // UUID + (PUSH + id + length of dict)
|
||||||
for (Pair<Integer, Object> pair : pairs) {
|
for (Pair<Integer, Object> pair : pairs) {
|
||||||
length += 7; // key + type + length
|
length += 7; // key + type + length
|
||||||
if (pair.second instanceof Integer) {
|
if (pair.second instanceof Integer) {
|
||||||
|
Loading…
Reference in New Issue
Block a user