Change the way how device commands or replys to information requests are passed back to the App

This was necessary to pack more complex and more specific information regarding apps etc.
master
Andreas Shimokawa 2015-03-26 12:06:26 +01:00
parent 0ccb818f58
commit 67a5917597
11 changed files with 143 additions and 69 deletions

View File

@ -29,6 +29,13 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommand;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandAppInfo;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandCallControl;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandMusicControl;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.protocol.PebbleProtocol;
public class BluetoothCommunicationService extends Service {
public static final String ACTION_START
= "nodomain.freeyourgadget.gadgetbride.bluetoothcommunicationservice.action.start";
@ -117,18 +124,20 @@ public class BluetoothCommunicationService extends Service {
nm.notify(NOTIFICATION_ID, notification);
}
private void evaluateGBCommandBundle(GBCommandBundle cmdBundle) {
switch (cmdBundle.commandClass) {
private void evaluateGBCommandBundle(GBDeviceCommand deviceCmd) {
switch (deviceCmd.commandClass) {
case MUSIC_CONTROL:
Log.i(TAG, "Got command for MUSIC_CONTROL");
GBDeviceCommandMusicControl musicCmd = (GBDeviceCommandMusicControl)deviceCmd;
Intent musicIntent = new Intent(GBMusicControlReceiver.ACTION_MUSICCONTROL);
musicIntent.putExtra("command", cmdBundle.command.ordinal());
musicIntent.putExtra("command", musicCmd.command.ordinal());
sendBroadcast(musicIntent);
break;
case CALL_CONTROL:
Log.i(TAG, "Got command for CALL_CONTROL");
GBDeviceCommandCallControl callCmd = (GBDeviceCommandCallControl)deviceCmd;
Intent callIntent = new Intent(GBCallControlReceiver.ACTION_CALLCONTROL);
callIntent.putExtra("command", cmdBundle.command.ordinal());
callIntent.putExtra("command", callCmd.command.ordinal());
sendBroadcast(callIntent);
break;
case VERSION_INFO:
@ -136,17 +145,19 @@ public class BluetoothCommunicationService extends Service {
if (gbdevice == null) {
return;
}
gbdevice.setFirmwareVersion(cmdBundle.info[0]);
GBDeviceCommandVersionInfo infoCmd = (GBDeviceCommandVersionInfo)deviceCmd;
gbdevice.setFirmwareVersion(infoCmd.fwVersion);
sendDeviceUpdateIntent();
break;
case APP_INFO:
Log.i(TAG, "Got command for APP_INFO");
GBDeviceCommandAppInfo appInfoCmd = (GBDeviceCommandAppInfo)deviceCmd;
Intent appInfoIntent = new Intent(AppManagerActivity.ACTION_REFRESH_APPLIST);
int appCount = cmdBundle.info.length / 2;
int appCount = appInfoCmd.apps.length;
appInfoIntent.putExtra("app_count", appCount);
for (Integer i = 0; i < appCount; i++) {
appInfoIntent.putExtra("app_name" + i.toString(), cmdBundle.info[i * 2]);
appInfoIntent.putExtra("app_creator" + i.toString(), cmdBundle.info[i * 2 + 1]);
appInfoIntent.putExtra("app_name" + i.toString(), appInfoCmd.apps[i].getName());
appInfoIntent.putExtra("app_creator" + i.toString(), appInfoCmd.apps[i].getCreator());
}
sendBroadcast(appInfoIntent);
break;
@ -399,11 +410,11 @@ public class BluetoothCommunicationService extends Service {
write(PebbleProtocol.encodePhoneVersion(PebbleProtocol.PHONEVERSION_REMOTE_OS_ANDROID));
write(PebbleProtocol.encodeFirmwareVersionReq());
} else if (endpoint != PebbleProtocol.ENDPOINT_DATALOG) {
GBCommandBundle cmdBundle = PebbleProtocol.decodeResponse(buffer);
if (cmdBundle == null) {
GBDeviceCommand deviceCmd = PebbleProtocol.decodeResponse(buffer);
if (deviceCmd == null) {
Log.i(TAG, "unhandled message to endpoint " + endpoint + " (" + bytes + " bytes)");
} else {
evaluateGBCommandBundle(cmdBundle);
evaluateGBCommandBundle(deviceCmd);
}
}
try {

View File

@ -10,25 +10,25 @@ import com.android.internal.telephony.ITelephony;
import java.lang.reflect.Method;
public class GBCallControlReceiver extends BroadcastReceiver {
private final String TAG = this.getClass().getSimpleName();
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandCallControl;
public class GBCallControlReceiver extends BroadcastReceiver {
public static final String ACTION_CALLCONTROL = "nodomain.freeyourgadget.gadgetbridge.callcontrol";
private final String TAG = this.getClass().getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
GBCommand command = GBCommand.values()[intent.getIntExtra("command", 0)];
int keyCode;
switch (command) {
case CALL_END:
case CALL_START:
GBDeviceCommandCallControl.Command callCmd = GBDeviceCommandCallControl.Command.values()[intent.getIntExtra("command", 0)];
switch (callCmd) {
case END:
case START:
try {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(telephonyManager.getClass().getName());
Method method = clazz.getDeclaredMethod("getITelephony");
method.setAccessible(true);
ITelephony telephonyService = (ITelephony) method.invoke(telephonyManager);
if (command == GBCommand.CALL_END) {
if (callCmd == GBDeviceCommandCallControl.Command.END) {
telephonyService.endCall();
} else {
telephonyService.answerRingingCall();

View File

@ -1,8 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge;
public class GBCommandBundle {
public GBCommandClass commandClass;
public GBCommand command;
public String[] info;
}

View File

@ -1,8 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge;
public enum GBCommandClass {
MUSIC_CONTROL,
CALL_CONTROL,
APP_INFO,
VERSION_INFO
}

View File

@ -6,6 +6,8 @@ import android.content.Intent;
import android.os.SystemClock;
import android.view.KeyEvent;
import nodomain.freeyourgadget.gadgetbridge.protocol.GBDeviceCommandMusicControl;
public class GBMusicControlReceiver extends BroadcastReceiver {
private final String TAG = this.getClass().getSimpleName();
@ -13,22 +15,22 @@ public class GBMusicControlReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
GBCommand command = GBCommand.values()[intent.getIntExtra("command", 0)];
GBDeviceCommandMusicControl.Command musicCmd = GBDeviceCommandMusicControl.Command.values()[intent.getIntExtra("command", 0)];
int keyCode;
switch (command) {
case MUSIC_NEXT:
switch (musicCmd) {
case NEXT:
keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
break;
case MUSIC_PREVIOUS:
case PREVIOUS:
keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
break;
case MUSIC_PLAY:
case PLAY:
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
break;
case MUSIC_PAUSE:
case PAUSE:
keyCode = KeyEvent.KEYCODE_MEDIA_PAUSE;
break;
case MUSIC_PLAYPAUSE:
case PLAYPAUSE:
keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
break;
default:

View File

@ -0,0 +1,15 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public abstract class GBDeviceCommand {
public CommandClass commandClass = CommandClass.UNKNOWN;
public enum CommandClass {
UNKNOWN,
MUSIC_CONTROL,
CALL_CONTROL,
APP_INFO,
VERSION_INFO
}
}

View File

@ -0,0 +1,11 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
import nodomain.freeyourgadget.gadgetbridge.GBDeviceApp;
public class GBDeviceCommandAppInfo extends GBDeviceCommand {
public GBDeviceApp apps[];
public GBDeviceCommandAppInfo() {
commandClass = CommandClass.APP_INFO;
}
}

View File

@ -0,0 +1,20 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public class GBDeviceCommandCallControl extends GBDeviceCommand {
public Command command = Command.UNKNOWN;
public GBDeviceCommandCallControl() {
commandClass = CommandClass.CALL_CONTROL;
}
public enum Command {
UNKNOWN,
ACCEPT,
END,
INCOMING,
OUTGOING,
REJECT,
START,
}
}

View File

@ -0,0 +1,19 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public class GBDeviceCommandMusicControl extends GBDeviceCommand {
public Command command = Command.UNKNOWN;
public GBDeviceCommandMusicControl() {
commandClass = CommandClass.MUSIC_CONTROL;
}
public enum Command {
UNKNOWN,
PLAY,
PAUSE,
PLAYPAUSE,
NEXT,
PREVIOUS,
}
}

View File

@ -0,0 +1,10 @@
package nodomain.freeyourgadget.gadgetbridge.protocol;
public class GBDeviceCommandVersionInfo extends GBDeviceCommand {
public String fwVersion = "N/A";
public String hwVersion = "N/A";
public GBDeviceCommandVersionInfo() {
commandClass = CommandClass.VERSION_INFO;
}
}

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge;
package nodomain.freeyourgadget.gadgetbridge.protocol;
import android.util.Log;
@ -6,6 +6,9 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.SimpleTimeZone;
import nodomain.freeyourgadget.gadgetbridge.GBCommand;
import nodomain.freeyourgadget.gadgetbridge.GBDeviceApp;
public class PebbleProtocol {
static private String TAG = "PebbleProtocol";
@ -13,7 +16,7 @@ public class PebbleProtocol {
static final short ENDPOINT_FIRMWARE = 1;
static final short ENDPOINT_TIME = 11;
static final short ENDPOINT_FIRMWAREVERSION = 16;
static final short ENDPOINT_PHONEVERSION = 17;
public static final short ENDPOINT_PHONEVERSION = 17;
static final short ENDPOINT_SYSTEMMESSAGE = 18;
static final short ENDPOINT_MUSICCONTROL = 32;
static final short ENDPOINT_PHONECONTROL = 33;
@ -30,7 +33,7 @@ public class PebbleProtocol {
static final short ENDPOINT_SYSREG = 5000;
static final short ENDPOINT_FCTREG = 5001;
static final short ENDPOINT_APPMANAGER = 6000;
static final short ENDPOINT_DATALOG = 6778;
public static final short ENDPOINT_DATALOG = 6778;
static final short ENDPOINT_RUNKEEPER = 7000;
static final short ENDPOINT_SCREENSHOT = 8000;
static final short ENDPOINT_PUTBYTES = (short) 48879;
@ -91,7 +94,7 @@ public class PebbleProtocol {
static final byte PHONEVERSION_REMOTE_OS_UNKNOWN = 0;
static final byte PHONEVERSION_REMOTE_OS_IOS = 1;
static final byte PHONEVERSION_REMOTE_OS_ANDROID = 2;
public static final byte PHONEVERSION_REMOTE_OS_ANDROID = 2;
static final byte PHONEVERSION_REMOTE_OS_OSX = 3;
static final byte PHONEVERSION_REMOTE_OS_LINUX = 4;
static final byte PHONEVERSION_REMOTE_OS_WINDOWS = 5;
@ -242,69 +245,69 @@ public class PebbleProtocol {
return buf.array();
}
public static GBCommandBundle decodeResponse(byte[] responseData) {
public static GBDeviceCommand decodeResponse(byte[] responseData) {
ByteBuffer buf = ByteBuffer.wrap(responseData);
buf.order(ByteOrder.BIG_ENDIAN);
short length = buf.getShort();
short endpoint = buf.getShort();
byte pebbleCmd = buf.get();
GBCommandBundle cmd = new GBCommandBundle();
GBDeviceCommand cmd = null;
switch (endpoint) {
case ENDPOINT_MUSICCONTROL:
cmd.commandClass = GBCommandClass.MUSIC_CONTROL;
GBDeviceCommandMusicControl musicCmd = new GBDeviceCommandMusicControl();
switch (pebbleCmd) {
case MUSICCONTROL_NEXT:
cmd.command = GBCommand.MUSIC_NEXT;
musicCmd.command = GBDeviceCommandMusicControl.Command.NEXT;
break;
case MUSICCONTROL_PREVIOUS:
cmd.command = GBCommand.MUSIC_PREVIOUS;
musicCmd.command = GBDeviceCommandMusicControl.Command.PREVIOUS;
break;
case MUSICCONTROL_PLAY:
cmd.command = GBCommand.MUSIC_PLAY;
musicCmd.command = GBDeviceCommandMusicControl.Command.PLAY;
break;
case MUSICCONTROL_PAUSE:
cmd.command = GBCommand.MUSIC_PAUSE;
musicCmd.command = GBDeviceCommandMusicControl.Command.PAUSE;
break;
case MUSICCONTROL_PLAYPAUSE:
cmd.command = GBCommand.MUSIC_PLAYPAUSE;
musicCmd.command = GBDeviceCommandMusicControl.Command.PLAYPAUSE;
break;
default:
cmd.command = GBCommand.UNDEFINEND;
break;
}
cmd = musicCmd;
break;
case ENDPOINT_PHONECONTROL:
cmd.commandClass = GBCommandClass.CALL_CONTROL;
GBDeviceCommandCallControl callCmd = new GBDeviceCommandCallControl();
switch (pebbleCmd) {
case PHONECONTROL_HANGUP:
cmd.command = GBCommand.CALL_END;
callCmd.command = GBDeviceCommandCallControl.Command.END;
break;
default:
Log.i(TAG, "Unknown PHONECONTROL command" + pebbleCmd);
cmd.command = GBCommand.UNDEFINEND;
break;
}
cmd = callCmd;
break;
case ENDPOINT_FIRMWAREVERSION:
GBDeviceCommandVersionInfo versionCmd = new GBDeviceCommandVersionInfo();
int version = buf.getInt();
byte[] versionString = new byte[32];
buf.get(versionString, 0, 32);
cmd.commandClass = GBCommandClass.VERSION_INFO;
cmd.command = GBCommand.VERSION_FIRMWARE;
cmd.info = new String[]{new String(versionString).trim()};
Log.i(TAG, "Got firmware version: " + cmd.info);
versionCmd.fwVersion = new String(versionString).trim();
Log.i(TAG, "Got firmware version: " + versionCmd.fwVersion);
cmd = versionCmd;
break;
case ENDPOINT_APPMANAGER:
cmd.commandClass = GBCommandClass.APP_INFO;
switch (pebbleCmd) {
case APPMANAGER_GETAPPBANKSTATUS:
cmd.command = GBCommand.APP_INFO_NAME;
GBDeviceCommandAppInfo appInfoCmd = new GBDeviceCommandAppInfo();
int banks = buf.getInt();
int banksUsed = buf.getInt();
byte[] appName = new byte[32];
byte[] creatorName = new byte[32];
cmd.info = new String[banksUsed * 2];
appInfoCmd.apps = new GBDeviceApp[banksUsed];
for (int i = 0; i < banksUsed; i++) {
buf.getInt(); // id
@ -312,14 +315,13 @@ public class PebbleProtocol {
buf.get(appName, 0, 32);
buf.get(creatorName, 0, 32);
int flags = buf.getInt();
short appVersion = buf.getShort();
cmd.info[i * 2] = new String(appName).trim();
cmd.info[i * 2 + 1] = new String(creatorName).trim();
Short appVersion = buf.getShort();
appInfoCmd.apps[i] = new GBDeviceApp(new String(appName).trim(), new String(creatorName).trim(), appVersion.toString());
}
cmd = appInfoCmd;
break;
default:
Log.i(TAG, "Unknown APPMANAGER command" + pebbleCmd);
cmd.command = GBCommand.UNDEFINEND;
break;
}
break;