From 0fe97c687d1ec57e98adfcccdfb3d801e3fe7689 Mon Sep 17 00:00:00 2001 From: Daniel Dakhno Date: Fri, 25 Oct 2019 19:13:55 +0200 Subject: [PATCH] created api specific abstraction layer --- .../externalevents/NotificationListener.java | 28 ++--- .../devices/qhybrid/QHybridSupport.java | 108 +++--------------- .../devices/qhybrid/adapter/WatchAdapter.java | 7 ++ .../qhybrid/adapter/WatchAdapterFactory.java | 2 +- .../adapter/misfit/MisfitWatchAdapter.java | 64 +++++++++-- 5 files changed, 96 insertions(+), 113 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index 6c98ee4c9..552341e4d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -32,6 +32,7 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.media.MediaMetadata; +import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.os.RemoteException; @@ -43,6 +44,7 @@ import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.core.app.NotificationCompat; import androidx.core.app.RemoteInput; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -631,36 +633,30 @@ public class NotificationListener extends NotificationListenerService { } } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public void onNotificationRemoved(StatusBarNotification sbn) { - LOG.info("Notification removed: " + sbn.getPackageName()); + LOG.info("Notification removed: " + sbn.getPackageName() + ": " + sbn.getNotification().category); notificationStack.remove(sbn.getPackageName()); - Object lookupObject = mNotificationHandleLookup.lookupByValue(sbn.getPostTime());; - if(lookupObject == null){ - LOG.debug("removed notification not found"); - return; + if(Notification.CATEGORY_CALL.equals(sbn.getNotification().category) && activeCallPostTime == sbn.getPostTime()) { + activeCallPostTime = 0; + CallSpec callSpec = new CallSpec(); + callSpec.command = CallSpec.CALL_END; + GBApplication.deviceService().onSetCallState(callSpec); } - int originalId = (int) lookupObject; + // FIXME: DISABLED for now - if (GBApplication.isRunningLollipopOrLater()) { - LOG.info("Notification removed: " + sbn.getPackageName() + ", category: " + sbn.getNotification().category); - if (Notification.CATEGORY_CALL.equals(sbn.getNotification().category) && activeCallPostTime == sbn.getPostTime()) { - activeCallPostTime = 0; - CallSpec callSpec = new CallSpec(); - callSpec.command = CallSpec.CALL_END; - GBApplication.deviceService().onSetCallState(callSpec); - } - } if (shouldIgnore(sbn)) return; Prefs prefs = GBApplication.getPrefs(); if (prefs.getBoolean("autoremove_notifications", true)) { LOG.info("notification removed, will ask device to delete it"); - GBApplication.deviceService().onDeleteNotification(originalId); + GBApplication.deviceService().onDeleteNotification((int) sbn.getPostTime()); } + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java index 751b9b2e3..3b7771eb4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java @@ -7,10 +7,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; -import android.os.Build; import android.os.Bundle; import android.util.Log; -import android.util.SparseArray; import android.widget.Toast; import org.slf4j.Logger; @@ -18,14 +16,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayDeque; -import java.util.Date; -import java.util.GregorianCalendar; import java.util.HashMap; -import java.util.NoSuchElementException; -import java.util.Queue; -import java.util.TimeZone; import java.util.UUID; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -33,7 +24,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; -import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfig; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfigHelper; import nodomain.freeyourgadget.gadgetbridge.externalevents.NotificationListener; @@ -46,30 +36,10 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapterFactory; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.ActivityPointGetRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.BatteryLevelRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.DownloadFileRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.EraseFileRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.FileRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.GetCountdownSettingsRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.GetCurrentStepCountRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.GetStepGoalRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.GetVibrationStrengthRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.GoalTrackingGetRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.ListFilesRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.MoveHandsRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.OTAEnterRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.OTAEraseRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.ReleaseHandsControlRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.Request; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.RequestHandControlRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetCurrentStepCountRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetStepGoalRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetTimeRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetVibrationStrengthRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.UploadFileRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.VibrateRequest; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -135,30 +105,14 @@ public class QHybridSupport extends QHybridBaseSupport { GBApplication.getContext().registerReceiver(globalCommandReceiver, globalFilter); } - private boolean supportsActivityHand() { - switch (modelNumber) { - case "HL.0.0": - return false; - case "HW.0.0": - return true; - } - throw new UnsupportedOperationException(); - } - - private boolean supportsExtendedVibration() { - switch (modelNumber) { - case "HL.0.0": - return false; - case "HW.0.0": - return true; - } - throw new UnsupportedOperationException(); - } - - private void getTimeOffset() { + private void loadTimeOffset() { timeOffset = getContext().getSharedPreferences(getContext().getPackageName(), Context.MODE_PRIVATE).getInt("QHYBRID_TIME_OFFSET", 0); } + public long getTimeOffset(){ + return this.timeOffset; + } + @Override protected TransactionBuilder initializeDevice(TransactionBuilder builder) { builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); @@ -172,34 +126,23 @@ public class QHybridSupport extends QHybridBaseSupport { for (int i = 2; i <= 7; i++) builder.notify(getCharacteristic(UUID.fromString("3dda000" + i + "-957f-7d4a-34a6-74696673696d")), true); - - Request initialRequest = new GetStepGoalRequest(); - builder - // .read(getCharacteristic(UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb"))) - // .read(getCharacteristic(UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb"))) .read(getCharacteristic(UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb"))) - // .read(getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb"))) - // .notify(getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")), true) - // .write(getCharacteristic(initialRequest.getRequestUUID()), initialRequest.getRequestData()) + .read(getCharacteristic(UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb"))) ; - getTimeOffset(); + loadTimeOffset(); - // builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext())); + builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext())); return builder; } @Override public void onFetchRecordedData(int dataTypes) { - //TODO - /* if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0) { - requestQueue.add(new BatteryLevelRequest()); - requestQueue.add(new GetCurrentStepCountRequest()); - requestQueue.add(new ListFilesRequest()); - queueWrite(new ActivityPointGetRequest()); - } */ + if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0) { + this.watchAdapter.onFetchActivityData(); + } } @Override @@ -241,7 +184,6 @@ public class QHybridSupport extends QHybridBaseSupport { watchAdapter.playNotification(new PackageConfig( (short) -1, (short) -1, - //TODO test activity hand (short) (progress * 180), PlayNotificationRequest.VibrationType.NO_VIBE )); @@ -249,7 +191,7 @@ public class QHybridSupport extends QHybridBaseSupport { } - private double calculateNotificationProgress() { + public double calculateNotificationProgress() { HashMap configs = new HashMap<>(0); for (PackageConfig config : helper.getSettings()) { configs.put(config, false); @@ -290,7 +232,7 @@ public class QHybridSupport extends QHybridBaseSupport { @Override public void onFindDevice(boolean start) { try { - if (start && !supportsExtendedVibration()) { + if (start && !watchAdapter.supportsExtendedVibration()) { GB.toast("Device does not support brr brr", Toast.LENGTH_SHORT, GB.INFO); return; } @@ -306,11 +248,9 @@ public class QHybridSupport extends QHybridBaseSupport { new Thread(new Runnable() { @Override public void run() { - VibrateRequest request = new VibrateRequest(false, (short) 4, (short) 1); - BluetoothGattCharacteristic chara = getCharacteristic(request.getRequestUUID()); int i = 0; while (searchDevice) { - new TransactionBuilder("findDevice#" + i++).write(chara, request.getRequestData()).queue(getQueue()); + QHybridSupport.this.watchAdapter.vibrateFindMyDevicePattern(); try { Thread.sleep(2500); } catch (InterruptedException e) { @@ -370,15 +310,16 @@ public class QHybridSupport extends QHybridBaseSupport { gbDevice.setFirmwareVersion(firmwareVersion); this.watchAdapter = new WatchAdapterFactory().createWatchAdapter(firmwareVersion, this); + this.watchAdapter.initialize(); break; } case "00002a24-0000-1000-8000-00805f9b34fb": { modelNumber = characteristic.getStringValue(0); gbDevice.setModel(modelNumber); - gbDevice.setName(getModelNameByModelNumber(modelNumber)); + gbDevice.setName(watchAdapter.getModelName()); try { - gbDevice.addDeviceInfo(new GenericItem(ITEM_EXTENDED_VIBRATION_SUPPORT, String.valueOf(supportsExtendedVibration()))); - gbDevice.addDeviceInfo(new GenericItem(ITEM_HAS_ACTIVITY_HAND, String.valueOf(supportsActivityHand()))); + gbDevice.addDeviceInfo(new GenericItem(ITEM_EXTENDED_VIBRATION_SUPPORT, String.valueOf(watchAdapter.supportsExtendedVibration()))); + gbDevice.addDeviceInfo(new GenericItem(ITEM_HAS_ACTIVITY_HAND, String.valueOf(watchAdapter.supportsActivityHand()))); } catch (UnsupportedOperationException e) { GB.toast("Please contact dakhnod@gmail.com\n", Toast.LENGTH_SHORT, GB.INFO); gbDevice.addDeviceInfo(new GenericItem(ITEM_EXTENDED_VIBRATION_SUPPORT, "false")); @@ -403,16 +344,6 @@ public class QHybridSupport extends QHybridBaseSupport { return true; } - private String getModelNameByModelNumber(String modelNumber) { - switch (modelNumber) { - case "HW.0.0": - return "Q Commuter"; - case "HL.0.0": - return "Q Activist"; - } - return "unknwon Q"; - } - @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { @@ -480,7 +411,7 @@ public class QHybridSupport extends QHybridBaseSupport { break; } case QHYBRID_COMMAND_UPDATE: { - getTimeOffset(); + loadTimeOffset(); onSetTime(); break; } @@ -489,7 +420,6 @@ public class QHybridSupport extends QHybridBaseSupport { switch (newSetting) { case ITEM_VIBRATION_STRENGTH: { watchAdapter.setVibrationStrength(Short.parseShort(gbDevice.getDeviceInfo(ITEM_VIBRATION_STRENGTH).getDetails())); - // queueWrite(new VibrateRequest(false, (short)4, (short)1)); break; } case ITEM_STEP_GOAL: { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java index cf2a1a45d..aca374cff 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java @@ -36,11 +36,18 @@ public abstract class WatchAdapter { public abstract void setActivityHand(double progress); public abstract void setHands(short hour, short minute); public abstract void vibrate(PlayNotificationRequest.VibrationType vibration); + public abstract void vibrateFindMyDevicePattern(); public abstract void requestHandsControl(); public abstract void releaseHandsControl(); public abstract void setStepGoal(int stepGoal); public abstract void setVibrationStrength(short strength); + public abstract boolean supportsExtendedVibration(); + public abstract boolean supportsActivityHand(); + public abstract String getModelName(); + + public abstract void onFetchActivityData(); + public abstract boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapterFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapterFactory.java index e0f979124..279e302ba 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapterFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapterFactory.java @@ -8,7 +8,7 @@ public final class WatchAdapterFactory { public final WatchAdapter createWatchAdapter(String firmwareVersion, QHybridSupport deviceSupport){ char major = firmwareVersion.charAt(6); switch (major){ - case 'a': return new MisfitWatchAdapter(deviceSupport); + case '1': return new MisfitWatchAdapter(deviceSupport); } throw new UnsupportedOperationException("Firmware " + firmwareVersion + " not supported"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java index 5913aac27..d038021df 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java @@ -58,6 +58,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mis import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetTimeRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetVibrationStrengthRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.UploadFileRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.VibrateRequest; import nodomain.freeyourgadget.gadgetbridge.util.GB; import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.ITEM_ACTIVITY_POINT; @@ -85,14 +86,14 @@ public class MisfitWatchAdapter extends WatchAdapter { @Override public void initialize() { - requestQueue.add(new GetCurrentStepCountRequest()); + requestQueue.add(new GetStepGoalRequest()); requestQueue.add(new GetVibrationStrengthRequest()); requestQueue.add(new ActivityPointGetRequest()); requestQueue.add(prepareSetTimeRequest()); requestQueue.add(new AnimationRequest()); + requestQueue.add(new SetCurrentStepCountRequest((int) (999999 * getDeviceSupport().calculateNotificationProgress()))); - //TODO - // requestQueue.add(new SetCurrentStepCountRequest((int) (999999 * calculateNotificationProgress()))); + queueWrite(new GetCurrentStepCountRequest()); } @@ -100,8 +101,7 @@ public class MisfitWatchAdapter extends WatchAdapter { long millis = System.currentTimeMillis(); TimeZone zone = new GregorianCalendar().getTimeZone(); return new SetTimeRequest( - //TODO time offset - (int) (millis / 1000 + 0 * 60), + (int) (millis / 1000 + getDeviceSupport().getTimeOffset() * 60), (short) (millis % 1000), (short) ((zone.getRawOffset() + zone.getDSTSavings()) / 60000)); } @@ -117,13 +117,14 @@ public class MisfitWatchAdapter extends WatchAdapter { queueWrite(new PlayNotificationRequest( config.getVibration(), config.getHour(), - config.getMin() + config.getMin(), + config.getActivity() )); } @Override public void setTime() { - + queueWrite(prepareSetTimeRequest()); } @Override @@ -372,6 +373,12 @@ public class MisfitWatchAdapter extends WatchAdapter { queueWrite(new PlayNotificationRequest(vibration, -1, -1)); } + @Override + public void vibrateFindMyDevicePattern() { + queueWrite(new VibrateRequest(false, (short) 4, (short) 1)); + } + + @Override public void requestHandsControl() { queueWrite(new RequestHandControlRequest()); @@ -392,6 +399,49 @@ public class MisfitWatchAdapter extends WatchAdapter { queueWrite(new SetVibrationStrengthRequest(strength)); } + @Override + public boolean supportsExtendedVibration() { + String modelNumber = getDeviceSupport().getDevice().getModel(); + switch (modelNumber) { + case "HW.0.0": + return true; + case "HL.0.0": + return false; + } + throw new UnsupportedOperationException("Model " + modelNumber + " not supported"); + } + + @Override + public boolean supportsActivityHand() { + String modelNumber = getDeviceSupport().getDevice().getModel(); + switch (modelNumber) { + case "HW.0.0": + return true; + case "HL.0.0": + return false; + } + throw new UnsupportedOperationException("Model " + modelNumber + " not supported"); + } + + @Override + public String getModelName() { + String modelNumber = getDeviceSupport().getDevice().getModel(); + switch (modelNumber) { + case "HW.0.0": + return "Q Commuter"; + case "HL.0.0": + return "Q Activist"; + } + return "unknwon Q"; + } + + @Override + public void onFetchActivityData() { + requestQueue.add(new BatteryLevelRequest()); + requestQueue.add(new GetCurrentStepCountRequest()); + // requestQueue.add(new ListFilesRequest()); + queueWrite(new ActivityPointGetRequest()); + } @Override public void overwriteButtons() {