Pebble: blindly implement missing parts for app installation on FW 3.x
This is expected to fail and needs to be enable in preferences (untested features).
This commit is contained in:
parent
567f27b0f4
commit
a4f5524f6e
|
@ -10,7 +10,7 @@ public abstract class GBDeviceEvent {
|
|||
CALL_CONTROL,
|
||||
APP_INFO,
|
||||
VERSION_INFO,
|
||||
APP_MANAGEMENT_RES,
|
||||
APP_MANAGEMENT,
|
||||
SEND_BYTES,
|
||||
SLEEP_MONITOR_RES,
|
||||
SCREENSHOT,
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.deviceevents;
|
||||
|
||||
public class GBDeviceEventAppManagementResult extends GBDeviceEvent {
|
||||
public Result result = Result.UNKNOWN;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GBDeviceEventAppManagement extends GBDeviceEvent {
|
||||
public Event event = Event.UNKNOWN;
|
||||
public EventType type = EventType.UNKNOWN;
|
||||
public int token = -1;
|
||||
public UUID uuid = null;
|
||||
|
||||
public GBDeviceEventAppManagementResult() {
|
||||
eventClass = EventClass.APP_MANAGEMENT_RES;
|
||||
public GBDeviceEventAppManagement() {
|
||||
eventClass = EventClass.APP_MANAGEMENT;
|
||||
}
|
||||
|
||||
public enum EventType {
|
||||
|
@ -15,10 +18,11 @@ public class GBDeviceEventAppManagementResult extends GBDeviceEvent {
|
|||
DELETE,
|
||||
}
|
||||
|
||||
public enum Result {
|
||||
public enum Event {
|
||||
UNKNOWN,
|
||||
SUCCESS,
|
||||
ACKNOLEDGE,
|
||||
FAILURE,
|
||||
REQUEST,
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import android.preference.PreferenceManager;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -22,13 +23,14 @@ import java.util.zip.ZipInputStream;
|
|||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagementResult;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PBWReader;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleInstallable;
|
||||
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.GBDeviceProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class PebbleIoThread extends GBDeviceIoThread {
|
||||
|
@ -122,7 +124,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||
mCRC = pi.getCRC();
|
||||
mBinarySize = pi.getFileSize();
|
||||
mBytesWritten = 0;
|
||||
writeInstallApp(mPebbleProtocol.encodeUploadStart(pi.getType(), (byte) mInstallSlot, mBinarySize));
|
||||
writeInstallApp(mPebbleProtocol.encodeUploadStart(pi.getType(), mInstallSlot, mBinarySize));
|
||||
mInstallState = PebbleAppInstallState.WAIT_TOKEN;
|
||||
break;
|
||||
case WAIT_TOKEN:
|
||||
|
@ -282,12 +284,12 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||
}
|
||||
gbDevice.setState(GBDevice.State.INITIALIZED);
|
||||
return false;
|
||||
case APP_MANAGEMENT_RES:
|
||||
GBDeviceEventAppManagementResult appMgmtRes = (GBDeviceEventAppManagementResult) deviceEvent;
|
||||
switch (appMgmtRes.type) {
|
||||
case APP_MANAGEMENT:
|
||||
GBDeviceEventAppManagement appMgmt = (GBDeviceEventAppManagement) deviceEvent;
|
||||
switch (appMgmt.type) {
|
||||
case DELETE:
|
||||
// right now on the Pebble we also receive this on a failed/successful installation ;/
|
||||
switch (appMgmtRes.result) {
|
||||
switch (appMgmt.event) {
|
||||
case FAILURE:
|
||||
if (mIsInstalling) {
|
||||
if (mInstallState == PebbleAppInstallState.WAIT_SLOT) {
|
||||
|
@ -320,13 +322,21 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||
}
|
||||
break;
|
||||
case INSTALL:
|
||||
switch (appMgmtRes.result) {
|
||||
switch (appMgmt.event) {
|
||||
case FAILURE:
|
||||
LOG.info("failure installing app"); // TODO: report to Installer
|
||||
finishInstall(true);
|
||||
break;
|
||||
case SUCCESS:
|
||||
setToken(appMgmtRes.token);
|
||||
setToken(appMgmt.token);
|
||||
break;
|
||||
case REQUEST:
|
||||
LOG.info("APPFETCH request: " + appMgmt.uuid + " / " + appMgmt.token);
|
||||
try {
|
||||
installApp(Uri.fromFile(new File(FileUtils.getExternalFilesDir() + "/pbw-cache/" + appMgmt.uuid.toString() + ".pbw")), appMgmt.token);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -369,18 +379,21 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||
}
|
||||
}
|
||||
|
||||
public void installApp(Uri uri) {
|
||||
public void installApp(Uri uri, int appId) {
|
||||
if (mIsInstalling) {
|
||||
return;
|
||||
}
|
||||
mIsInstalling = true;
|
||||
|
||||
mPBWReader = new PBWReader(uri, getContext(), gbDevice.getHardwareVersion().equals("dvt") ? "basalt" : "aplite");
|
||||
mPebbleInstallables = mPBWReader.getPebbleInstallables();
|
||||
mCurrentInstallableIndex = 0;
|
||||
|
||||
if (mPBWReader.isFirmware()) {
|
||||
LOG.info("starting firmware installation");
|
||||
mIsInstalling = true;
|
||||
mInstallSlot = 0;
|
||||
writeInstallApp(mPebbleProtocol.encodeInstallFirmwareStart());
|
||||
mInstallState = PebbleAppInstallState.START_INSTALL;
|
||||
|
||||
/*
|
||||
* This is a hack for recovery mode, in which the blocking read has no timeout and the
|
||||
|
@ -392,16 +405,25 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||
*
|
||||
*/
|
||||
writeInstallApp(mPebbleProtocol.encodeGetTime());
|
||||
|
||||
LOG.info("starting firmware installation");
|
||||
mInstallSlot = 0;
|
||||
mInstallState = PebbleAppInstallState.START_INSTALL;
|
||||
} else {
|
||||
GBDeviceApp app = mPBWReader.getGBDeviceApp();
|
||||
writeInstallApp(mPebbleProtocol.encodeAppDelete(app.getUUID()));
|
||||
mInstallState = PebbleAppInstallState.WAIT_SLOT;
|
||||
if (mPebbleProtocol.isFw3x && mForceUntested) {
|
||||
writeInstallApp(mPebbleProtocol.encodeInstallMetadata(app.getUUID(), app.getName(), mPBWReader.getAppVersion(), mPBWReader.getSdkVersion()));
|
||||
if (appId == 0) {
|
||||
// only install metadata - not the binaries
|
||||
write(mPebbleProtocol.encodeInstallMetadata(app.getUUID(), app.getName(), mPBWReader.getAppVersion(), mPBWReader.getSdkVersion()));
|
||||
GB.toast("To finish installation please start the watchapp on your Pebble", 5, GB.INFO);
|
||||
} else {
|
||||
// this came from an app fetch request, so do the real stuff
|
||||
mIsInstalling = true;
|
||||
mInstallSlot = appId;
|
||||
mInstallState = PebbleAppInstallState.START_INSTALL;
|
||||
|
||||
writeInstallApp(mPebbleProtocol.encodeGetTime()); // EVIL HACK see hack above
|
||||
}
|
||||
} else {
|
||||
mIsInstalling = true;
|
||||
mInstallState = PebbleAppInstallState.WAIT_SLOT;
|
||||
writeInstallApp(mPebbleProtocol.encodeAppDelete(app.getUUID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.UUID;
|
|||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagementResult;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppManagement;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDismissNotification;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl;
|
||||
|
@ -182,7 +182,8 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
static final short LENGTH_REFRESHAPP = 5;
|
||||
static final short LENGTH_SETTIME = 5;
|
||||
static final short LENGTH_SYSTEMMESSAGE = 2;
|
||||
static final short LENGTH_UPLOADSTART = 7;
|
||||
static final short LENGTH_UPLOADSTART_2X = 7;
|
||||
static final short LENGTH_UPLOADSTART_3X = 10;
|
||||
static final short LENGTH_UPLOADCHUNK = 9;
|
||||
static final short LENGTH_UPLOADCOMMIT = 9;
|
||||
static final short LENGTH_UPLOADCOMPLETE = 5;
|
||||
|
@ -658,15 +659,27 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
}
|
||||
|
||||
/* pebble specific install methods */
|
||||
public byte[] encodeUploadStart(byte type, byte index, int size) {
|
||||
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + LENGTH_UPLOADSTART);
|
||||
public byte[] encodeUploadStart(byte type, int app_id, int size) {
|
||||
short length;
|
||||
if (isFw3x) {
|
||||
length = LENGTH_UPLOADSTART_3X;
|
||||
type |= 0b10000000;
|
||||
} else {
|
||||
length = LENGTH_UPLOADSTART_2X;
|
||||
}
|
||||
ByteBuffer buf = ByteBuffer.allocate(LENGTH_PREFIX + length);
|
||||
buf.order(ByteOrder.BIG_ENDIAN);
|
||||
buf.putShort(LENGTH_UPLOADSTART);
|
||||
buf.putShort(length);
|
||||
buf.putShort(ENDPOINT_PUTBYTES);
|
||||
buf.put(PUTBYTES_INIT);
|
||||
buf.putInt(size);
|
||||
buf.put(type);
|
||||
buf.put(index);
|
||||
if (isFw3x) {
|
||||
buf.putInt(app_id);
|
||||
} else {
|
||||
// slot
|
||||
buf.put((byte) app_id);
|
||||
}
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
|
@ -940,7 +953,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
return null;
|
||||
}
|
||||
|
||||
private GBDeviceEvent decodeAppFetch(ByteBuffer buf) {
|
||||
private GBDeviceEventAppManagement decodeAppFetch(ByteBuffer buf) {
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
byte command = buf.get();
|
||||
if (command == 0x01) {
|
||||
|
@ -948,7 +961,12 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
long uuid_low = buf.getLong();
|
||||
UUID uuid = new UUID(uuid_high, uuid_low);
|
||||
int app_id = buf.getInt();
|
||||
LOG.info("APPFETCH request: " + uuid + " / " + app_id);
|
||||
GBDeviceEventAppManagement fetchRequest = new GBDeviceEventAppManagement();
|
||||
fetchRequest.type = GBDeviceEventAppManagement.EventType.INSTALL;
|
||||
fetchRequest.event = GBDeviceEventAppManagement.Event.REQUEST;
|
||||
fetchRequest.token = app_id;
|
||||
fetchRequest.uuid = uuid;
|
||||
return fetchRequest;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1080,16 +1098,16 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
}
|
||||
break;
|
||||
case APPMANAGER_REMOVEAPP:
|
||||
GBDeviceEventAppManagementResult deleteRes = new GBDeviceEventAppManagementResult();
|
||||
deleteRes.type = GBDeviceEventAppManagementResult.EventType.DELETE;
|
||||
GBDeviceEventAppManagement deleteRes = new GBDeviceEventAppManagement();
|
||||
deleteRes.type = GBDeviceEventAppManagement.EventType.DELETE;
|
||||
|
||||
int result = buf.getInt();
|
||||
switch (result) {
|
||||
case APPMANAGER_RES_SUCCESS:
|
||||
deleteRes.result = GBDeviceEventAppManagementResult.Result.SUCCESS;
|
||||
deleteRes.event = GBDeviceEventAppManagement.Event.SUCCESS;
|
||||
break;
|
||||
default:
|
||||
deleteRes.result = GBDeviceEventAppManagementResult.Result.FAILURE;
|
||||
deleteRes.event = GBDeviceEventAppManagement.Event.FAILURE;
|
||||
break;
|
||||
}
|
||||
devEvt = deleteRes;
|
||||
|
@ -1101,16 +1119,16 @@ public class PebbleProtocol extends GBDeviceProtocol {
|
|||
break;
|
||||
case ENDPOINT_PUTBYTES:
|
||||
pebbleCmd = buf.get();
|
||||
GBDeviceEventAppManagementResult installRes = new GBDeviceEventAppManagementResult();
|
||||
installRes.type = GBDeviceEventAppManagementResult.EventType.INSTALL;
|
||||
GBDeviceEventAppManagement installRes = new GBDeviceEventAppManagement();
|
||||
installRes.type = GBDeviceEventAppManagement.EventType.INSTALL;
|
||||
switch (pebbleCmd) {
|
||||
case PUTBYTES_INIT:
|
||||
installRes.token = buf.getInt();
|
||||
installRes.result = GBDeviceEventAppManagementResult.Result.SUCCESS;
|
||||
installRes.event = GBDeviceEventAppManagement.Event.SUCCESS;
|
||||
break;
|
||||
default:
|
||||
installRes.token = buf.getInt();
|
||||
installRes.result = GBDeviceEventAppManagementResult.Result.FAILURE;
|
||||
installRes.event = GBDeviceEventAppManagement.Event.FAILURE;
|
||||
break;
|
||||
}
|
||||
devEvt = installRes;
|
||||
|
|
|
@ -34,7 +34,7 @@ public class PebbleSupport extends AbstractBTDeviceSupport {
|
|||
|
||||
@Override
|
||||
public void onInstallApp(Uri uri) {
|
||||
getDeviceIOThread().installApp(uri);
|
||||
getDeviceIOThread().installApp(uri, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue