From d28ee8d00d822dfd818bd246c21afc3b07e1f3a2 Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 3 Dec 2021 22:30:34 +0100 Subject: [PATCH 1/8] Fixed infinite loop --- .../java/com/jens/automation2/Rule.java | 549 +--------------- .../java/com/jens/automation2/Trigger.java | 596 +++++++++++++++++- .../receivers/DateTimeListener.java | 2 +- 3 files changed, 604 insertions(+), 543 deletions(-) diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index 249a5370e..bd5ee2b67 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -34,8 +34,6 @@ import java.util.Calendar; import java.util.Date; import static com.jens.automation2.Trigger.triggerParameter2Split; -import static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT; -import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE; import androidx.core.app.NotificationCompat; @@ -371,344 +369,27 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.pointOfInterest)) + if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) { - // Am I here? - PointOfInterest activePoi = PointOfInterest.getActivePoi(); - if(activePoi != null) //entering one - { - if(oneTrigger.getPointOfInterest() != null) - { - if(activePoi.equals(oneTrigger.getPointOfInterest())) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're entering POI: " + oneTrigger.getPointOfInterest().getName() + ", not leaving it.", 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + oneTrigger.getPointOfInterest().getName() + ".", 4); - return false; - } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at a POI. Rule specifies not at none, so leaving any.", 4); - return false; - } - } - } - else //leaving one - { - // We are not at any POI. But if this trigger requires us NOT to be there, that may be fine. - if(oneTrigger.getPointOfInterest() != null) - { -// if(activePoi.equals(oneTrigger.getPointOfInterest())) -// { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "We are not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\".", 3); - return false; - } -// } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5); - return false; - } - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) - { - Date now = new Date(); - String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds()); - Time nowTime = Time.valueOf(timeString); - Calendar calNow = Calendar.getInstance(); - - - if(oneTrigger.getTimeFrame().getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK))) - { - if( - // Regular case, start time is lower than end time - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - && - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0 - ) - || - // Other case, start time higher than end time, timeframe goes over midnight - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), oneTrigger.getTimeFrame().getTriggerTimeStop()) < 0 - && - (Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - || - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0) - ) - - ) - { - // We are in the timeframe - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + "). Trigger of Rule " + this.getName() + " applies.", 3); - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 3); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 3); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the time. Trigger of Rule " + this.getName() + " doesn\'t apply..", 5); - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 5); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 5); - return false; - } - // return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the day. Trigger of Rule " + this.getName() + " doesn\'t apply.", 5); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.charging)) - { - if(BatteryReceiver.isDeviceCharging(context) == 0) - { - return false; // unknown charging state, can't activate rule under these conditions - } - else if(BatteryReceiver.isDeviceCharging(context) == 1) - { - if(oneTrigger.getTriggerParameter()) //rule says when charging, but we're currently discharging - return false; - } - else if(BatteryReceiver.isDeviceCharging(context) == 2) - { - if(!oneTrigger.getTriggerParameter()) //rule says when discharging, but we're currently charging - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.usb_host_connection)) - { - if(BatteryReceiver.isUsbHostConnected() != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.batteryLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(BatteryReceiver.getBatteryLevel() <= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - else - { - if(oneTrigger.getBatteryLevel() >= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.speed)) - { - if(oneTrigger.getTriggerParameter()) - { - if(LocationProvider.getSpeed() < oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - else - { - if(LocationProvider.getSpeed() > oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.noiseLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(NoiseListener.getNoiseLevelDb() < oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - else - { - if(NoiseListener.getNoiseLevelDb() > oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.wifiConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for wifi state", 4); - if(oneTrigger.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected - { - if(oneTrigger.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name specified, checking that.", 4); - if(!WifiBroadcastReceiver.getLastWifiSsid().equals(oneTrigger.getTriggerParameter2())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), oneTrigger.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); - return false; - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name matches. Rule will apply.", 4); - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "No wifi name specified, any will do.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi state not correct, demanded " + String.valueOf(oneTrigger.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.process_started_stopped)) - { - boolean running = ProcessListener.getRunningApps().contains(oneTrigger.getProcessName()); - - if(running) - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is currently running.", 4); - else - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is not running.", 4); - - if(running != oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4); - return false; - } - - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4); - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.airplaneMode)) - { - if(ConnectivityReceiver.isAirplaneMode(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.roaming)) - { - if(ConnectivityReceiver.isRoaming(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.phoneCall)) - { - String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - // state dir number - - if(elements[2].equals(Trigger.triggerPhoneCallNumberAny) || Miscellaneous.comparePhoneNumbers(PhoneStatusListener.getLastPhoneNumber(), elements[2]) || (Miscellaneous.isRegularExpression(elements[2]) && PhoneStatusListener.getLastPhoneNumber().matches(elements[2]))) - { - //if(PhoneStatusListener.isInACall() == oneTrigger.getTriggerParameter()) - if( - (elements[0].equals(Trigger.triggerPhoneCallStateRinging) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_RINGING) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStarted) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_OFFHOOK) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStopped) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_IDLE) - ) - { - if( - elements[1].equals(Trigger.triggerPhoneCallDirectionAny) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionIncoming) && PhoneStatusListener.getLastPhoneDirection() == 1) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionOutgoing) && PhoneStatusListener.getLastPhoneDirection() == 2) - ) - { - // Trigger conditions are met - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(oneTrigger.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(oneTrigger.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + oneTrigger.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.nfcTag)) - { - if(NfcReceiver.lastReadLabel == null) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3); - return false; - } - else if(!NfcReceiver.lastReadLabel.equals(oneTrigger.getNfcTagId())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + oneTrigger.getNfcTagId(), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) - { - if(ActivityDetectionReceiver.getActivityDetectionLastResult() != null) + if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) { boolean found = false; - for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) { - if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) found = true; } - if(!found) + if (!found) { Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); return false; } else { - for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) { Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); return false; @@ -717,220 +398,10 @@ public class Rule implements Comparable } } } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.bluetoothConnection)) + else { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for bluetooth...", 4); - - if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() != oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() == oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().length() > 0) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3); + if (!oneTrigger.applies(null, context)) return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.headsetPlugged)) - { - if(HeadphoneJackListener.isHeadsetConnected() != oneTrigger.getTriggerParameter()) - return false; - else - if(oneTrigger.getHeadphoneType() != 2 && oneTrigger.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.notification)) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) - { - String[] params = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - - String myApp = params[0]; - String myTitleDir = params[1]; - String requiredTitle = params[2]; - String myTextDir = params[3]; - String requiredText; - if (params.length >= 5) - requiredText = params[4]; - else - requiredText = ""; - - if(oneTrigger.getTriggerParameter()) - { - // Check an active notification that is still there - - boolean foundMatch = false; - - for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) - { - if(getLastExecution() == null || sbn.getPostTime() > this.lastExecution.getTimeInMillis()) - { - String notificationApp = sbn.getPackageName(); - String notificationTitle = null; - String notificationText = null; - - Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5); - - if (!myApp.equals("-1")) - { - if (!notificationApp.equalsIgnoreCase(myApp)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5); - continue; - } - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - /* - If there are multiple notifications ("stacked") title or text might be null: - https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications - */ - - Bundle extras = sbn.getNotification().extras; - - // T I T L E - if (extras.containsKey(EXTRA_TITLE)) - notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE); - - if (!StringUtils.isEmpty(requiredTitle)) - { - if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5); - - // T E X T - - if (extras.containsKey(EXTRA_TEXT)) - notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT); - - if (!StringUtils.isEmpty(requiredText)) - { - if (!Miscellaneous.compare(myTextDir, requiredText, notificationText)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5); - - foundMatch = true; - break; - } - } - - if(!foundMatch) - return false; - } - else - { - // check a notification that is gone - - if(NotificationListener.getLastNotification() != null) - { - if(!NotificationListener.getLastNotification().isCreated()) - { - String app = NotificationListener.getLastNotification().getApp(); - String title = NotificationListener.getLastNotification().getTitle(); - String text = NotificationListener.getLastNotification().getText(); - - if (!myApp.equals("-1")) - { - if (!app.equalsIgnoreCase(myApp)) - return false; - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - if (requiredTitle.length() > 0) - { - if (!Miscellaneous.compare(myTitleDir, title, requiredTitle)) - return false; - } - - if (requiredText.length() > 0) - { - if (!Miscellaneous.compare(myTextDir, text, requiredText)) - return false; - } - } - else - return false; - } - } - } } } diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index 1c8064b4d..209a4d6c3 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -3,11 +3,28 @@ package com.jens.automation2; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.os.Build; +import android.os.Bundle; +import android.service.notification.StatusBarNotification; +import android.telephony.TelephonyManager; import android.util.Log; import androidx.annotation.RequiresApi; +import com.jens.automation2.location.LocationProvider; +import com.jens.automation2.location.WifiBroadcastReceiver; +import com.jens.automation2.receivers.BatteryReceiver; import com.jens.automation2.receivers.BluetoothReceiver; +import com.jens.automation2.receivers.ConnectivityReceiver; +import com.jens.automation2.receivers.HeadphoneJackListener; +import com.jens.automation2.receivers.NfcReceiver; +import com.jens.automation2.receivers.NoiseListener; +import com.jens.automation2.receivers.NotificationListener; +import com.jens.automation2.receivers.PhoneStatusListener; +import com.jens.automation2.receivers.ProcessListener; +import static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT; +import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE; + +import org.apache.commons.lang3.StringUtils; import java.sql.Time; import java.util.ArrayList; @@ -30,7 +47,7 @@ public class Trigger this.hasFlipped = hasFlipped; } - public boolean applies(Object triggeringObject) + public boolean applies(Object triggeringObject, Context context) { try { @@ -40,6 +57,66 @@ public class Trigger if(!checkDateTime(triggeringObject, false)) return false; break; + case pointOfInterest: + if(!checkLocation()) + return false; + break; + case charging: + if(!checkCharging()) + return false; + break; + case usb_host_connection: + if(!checkUsbHostConnection()) + return false; + break; + case batteryLevel: + if(!checkBatteryLevel()) + return false; + break; + case speed: + if(!checkSpeed()) + return false; + break; + case noiseLevel: + if(!checkNoiseLevel()) + return false; + break; + case wifiConnection: + if(!checkWifiConnection()) + return false; + break; + case process_started_stopped: + if(!checkProcess()) + return false; + break; + case airplaneMode: + if(!checkAirplaneMode()) + return false; + break; + case roaming: + if(!checkRoaming()) + return false; + break; + case phoneCall: + if(!checkPhoneCall()) + return false; + break; + case nfcTag: + if(!checkNfc()) + return false; + break; + case bluetoothConnection: + if(!checkBluetooth()) + return false; + break; + case headsetPlugged: + if(!checkHeadsetPlugged()) + return false; + break; + case notification: + if(!checkNotification()) + return false; + break; default: break; } @@ -48,11 +125,504 @@ public class Trigger } catch(Exception e) { - Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1); + Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.getParentRule().toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1); return false; } } + boolean checkNotification() + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) + { + String[] params = this.getTriggerParameter2().split(triggerParameter2Split); + + String myApp = params[0]; + String myTitleDir = params[1]; + String requiredTitle = params[2]; + String myTextDir = params[3]; + String requiredText; + if (params.length >= 5) + requiredText = params[4]; + else + requiredText = ""; + + if(this.getTriggerParameter()) + { + // Check an active notification that is still there + + boolean foundMatch = false; + + for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) + { + if(getParentRule().getLastExecution() == null || sbn.getPostTime() > this.getParentRule().getLastExecution().getTimeInMillis()) + { + String notificationApp = sbn.getPackageName(); + String notificationTitle = null; + String notificationText = null; + + Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getParentRule().getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5); + + if (!myApp.equals("-1")) + { + if (!notificationApp.equalsIgnoreCase(myApp)) + { + Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5); + continue; + } + } + else + { + if(myApp.equals(BuildConfig.APPLICATION_ID)) + { + return false; + } + } + + /* + If there are multiple notifications ("stacked") title or text might be null: + https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications + */ + + Bundle extras = sbn.getNotification().extras; + + // T I T L E + if (extras.containsKey(EXTRA_TITLE)) + notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE); + + if (!StringUtils.isEmpty(requiredTitle)) + { + if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle)) + { + Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5); + continue; + } + } + else + Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5); + + // T E X T + + if (extras.containsKey(EXTRA_TEXT)) + notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT); + + if (!StringUtils.isEmpty(requiredText)) + { + if (!Miscellaneous.compare(myTextDir, requiredText, notificationText)) + { + Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5); + continue; + } + } + else + Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5); + + foundMatch = true; + break; + } + } + + if(!foundMatch) + return false; + } + else + { + // check a notification that is gone + + if(NotificationListener.getLastNotification() != null) + { + if(!NotificationListener.getLastNotification().isCreated()) + { + String app = NotificationListener.getLastNotification().getApp(); + String title = NotificationListener.getLastNotification().getTitle(); + String text = NotificationListener.getLastNotification().getText(); + + if (!myApp.equals("-1")) + { + if (!app.equalsIgnoreCase(myApp)) + return false; + } + else + { + if(myApp.equals(BuildConfig.APPLICATION_ID)) + { + return false; + } + } + + if (requiredTitle.length() > 0) + { + if (!Miscellaneous.compare(myTitleDir, title, requiredTitle)) + return false; + } + + if (requiredText.length() > 0) + { + if (!Miscellaneous.compare(myTextDir, text, requiredText)) + return false; + } + } + else + return false; + } + } + } + + return true; + } + + boolean checkHeadsetPlugged() + { + if(HeadphoneJackListener.isHeadsetConnected() != this.getTriggerParameter()) + return false; + else + if(this.getHeadphoneType() != 2 && this.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3); + return false; + } + + return true; + } + + boolean checkBluetooth() + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Checking for bluetooth...", 4); + + if(this.getBluetoothDeviceAddress().equals("")) + { + if(this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) + { + if(BluetoothReceiver.isAnyDeviceConnected() != this.getTriggerParameter()) + return false; + } + else if((this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) + { + if(BluetoothReceiver.isAnyDeviceConnected() != this.getTriggerParameter()) + return false; + } + else + { + // range + if(BluetoothReceiver.isAnyDeviceInRange() != this.getTriggerParameter()) + return false; + } + } + else if(this.getBluetoothDeviceAddress().equals("")) + { + if(this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) + { + if(BluetoothReceiver.isAnyDeviceConnected() == this.getTriggerParameter()) + return false; + } + else if((this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) + { + if(BluetoothReceiver.isAnyDeviceConnected() == this.getTriggerParameter()) + return false; + } + else + { + // range + if(BluetoothReceiver.isAnyDeviceInRange() == this.getTriggerParameter()) + return false; + } + } + else if(this.getBluetoothDeviceAddress().length() > 0) + { + if(this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) + { + if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(this.getBluetoothDeviceAddress())) != this.getTriggerParameter()) + return false; + } + else if((this.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) + { + if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(this.getBluetoothDeviceAddress())) != this.getTriggerParameter()) + return false; + } + else + { + // range + if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(this.getBluetoothDeviceAddress())) != this.getTriggerParameter()) + return false; + } + } + else + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3); + return false; + } + + return true; + } + + boolean checkNfc() + { + if(NfcReceiver.lastReadLabel == null) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3); + return false; + } + else if(!NfcReceiver.lastReadLabel.equals(this.getNfcTagId())) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + this.getNfcTagId(), 3); + return false; + } + + return true; + } + + boolean checkPhoneCall() + { + String[] elements = this.getTriggerParameter2().split(triggerParameter2Split); + // state dir number + + if(elements[2].equals(Trigger.triggerPhoneCallNumberAny) || Miscellaneous.comparePhoneNumbers(PhoneStatusListener.getLastPhoneNumber(), elements[2]) || (Miscellaneous.isRegularExpression(elements[2]) && PhoneStatusListener.getLastPhoneNumber().matches(elements[2]))) + { + //if(PhoneStatusListener.isInACall() == oneTrigger.getTriggerParameter()) + if( + (elements[0].equals(Trigger.triggerPhoneCallStateRinging) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_RINGING) + || + (elements[0].equals(Trigger.triggerPhoneCallStateStarted) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_OFFHOOK) + || + (elements[0].equals(Trigger.triggerPhoneCallStateStopped) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_IDLE) + ) + { + if( + elements[1].equals(Trigger.triggerPhoneCallDirectionAny) + || + (elements[1].equals(Trigger.triggerPhoneCallDirectionIncoming) && PhoneStatusListener.getLastPhoneDirection() == 1) + || + (elements[1].equals(Trigger.triggerPhoneCallDirectionOutgoing) && PhoneStatusListener.getLastPhoneDirection() == 2) + ) + { + // Trigger conditions are met + } + else + { + Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(this.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); + return false; + } + } + else + { + Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(this.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); + return false; + } + } + else + { + Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + this.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); + return false; + } + + return false; + } + + boolean checkRoaming() + { + if(ConnectivityReceiver.isRoaming(Miscellaneous.getAnyContext()) != this.getTriggerParameter()) + { + return false; + } + + return true; + } + + boolean checkAirplaneMode() + { + if(ConnectivityReceiver.isAirplaneMode(Miscellaneous.getAnyContext()) != this.getTriggerParameter()) + { + return false; + } + + return true; + } + + boolean checkProcess() + { + boolean running = ProcessListener.getRunningApps().contains(this.getProcessName()); + + if(running) + Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + this.getProcessName() + " is currently running.", 4); + else + Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + this.getProcessName() + " is not running.", 4); + + if(running != this.getTriggerParameter()) + { + Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4); + return false; + } + + Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4); + + return true; + } + + boolean checkWifiConnection() + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Checking for wifi state", 4); + if(this.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected + { + if(this.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi name specified, checking that.", 4); + if(!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2())) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); + return false; + } + else + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi name matches. Rule will apply.", 4); + } + else + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "No wifi name specified, any will do.", 4); + } + else + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi state not correct, demanded " + String.valueOf(this.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4); + return false; + } + + return true; + } + + boolean checkNoiseLevel() + { + if(this.getTriggerParameter()) + { + if(NoiseListener.getNoiseLevelDb() < this.getNoiseLevelDb()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(this.getNoiseLevelDb()), 3); + return false; + } + } + else + { + if(NoiseListener.getNoiseLevelDb() > this.getNoiseLevelDb()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(this.getNoiseLevelDb()), 3); + return false; + } + } + + return true; + } + + boolean checkSpeed() + { + if(this.getTriggerParameter()) + { + if(LocationProvider.getSpeed() < this.getSpeed()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(this.getSpeed()), 3); + return false; + } + } + else + { + if(LocationProvider.getSpeed() > this.getSpeed()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(this.getSpeed()), 3); + return false; + } + } + + return true; + } + + boolean checkBatteryLevel() + { + if(this.getTriggerParameter()) + { + if(BatteryReceiver.getBatteryLevel() <= this.getBatteryLevel()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(this.getBatteryLevel()), 3); + return false; + } + } + else + { + if(this.getBatteryLevel() >= this.getBatteryLevel()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(this.getBatteryLevel()), 3); + return false; + } + } + + return true; + } + + boolean checkUsbHostConnection() + { + if(BatteryReceiver.isUsbHostConnected() != this.getTriggerParameter()) + { + return false; + } + + return true; + } + + boolean checkLocation() + { + // Am I here? + PointOfInterest activePoi = PointOfInterest.getActivePoi(); + if(activePoi != null) //entering one + { + if(this.getPointOfInterest() != null) + { + if(activePoi.equals(this.getPointOfInterest())) + { + if(!this.getTriggerParameter()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're entering POI: " + this.getPointOfInterest().getName() + ", not leaving it.", 4); + return false; + } + } + else + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + this.getPointOfInterest().getName() + ".", 4); + return false; + } + } + else if(this.getPointOfInterest() == null) + { + if(this.getTriggerParameter()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're at a POI. Rule specifies not at none, so leaving any.", 4); + return false; + } + } + } + else //leaving one + { + // We are not at any POI. But if this trigger requires us NOT to be there, that may be fine. + if(this.getPointOfInterest() != null) + { +// if(activePoi.equals(oneTrigger.getPointOfInterest())) +// { + if(!this.getTriggerParameter()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "We are not at POI \"" + this.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4); + } + else + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're not at POI \"" + this.getPointOfInterest().getName() + "\".", 3); + return false; + } +// } + } + else if(this.getPointOfInterest() == null) + { + if(!this.getTriggerParameter()) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5); + return false; + } + } + } + + return true; + } + public boolean hasStateRecentlyNotApplied(Object triggeringObject) { // nur mit einem Trigger? @@ -75,11 +645,31 @@ public class Trigger } catch(Exception e) { - Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1); + Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.getParentRule().toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1); return false; } } + boolean checkCharging() + { + if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 0) + { + return false; // unknown charging state, can't activate rule under these conditions + } + else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 1) + { + if(this.getTriggerParameter()) //rule says when charging, but we're currently discharging + return false; + } + else if(BatteryReceiver.isDeviceCharging(Miscellaneous.getAnyContext()) == 2) + { + if(!this.getTriggerParameter()) //rule says when discharging, but we're currently charging + return false; + } + + return true; + } + public boolean checkDateTime(Object triggeringObject, boolean checkifStateChangedSinceLastRuleExecution) { /* diff --git a/app/src/main/java/com/jens/automation2/receivers/DateTimeListener.java b/app/src/main/java/com/jens/automation2/receivers/DateTimeListener.java index 3c4cfc1e4..16ac40a0b 100644 --- a/app/src/main/java/com/jens/automation2/receivers/DateTimeListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/DateTimeListener.java @@ -215,7 +215,7 @@ public class DateTimeListener extends BroadcastReceiver implements AutomationLis if(tf.getRepetition() > 0) { - if(oneTrigger.applies(calNow)) + if(oneTrigger.applies(calNow, Miscellaneous.getAnyContext())) { Calendar calSchedule = getNextRepeatedExecutionAfter(oneTrigger, calNow); From cdf1a8baa87cf4b0e9ae8b2765818185c7a48aab Mon Sep 17 00:00:00 2001 From: jens Date: Sat, 4 Dec 2021 02:39:37 +0100 Subject: [PATCH 2/8] Rework --- .idea/deploymentTargetDropDown.xml | 13 +- .../java/com/jens/automation2/Rule.java | 67 +- .../receivers/ActivityDetectionReceiver.java | 2 +- .../java/com/jens/automation2/Rule.java | 597 +---------------- .../java/com/jens/automation2/Rule.java | 616 +----------------- .../com/jens/automation2/PointOfInterest.java | 4 +- .../jens/automation2/ReceiverCoordinator.java | 7 +- .../java/com/jens/automation2/Trigger.java | 88 +-- .../location/LocationProvider.java | 2 +- .../location/WifiBroadcastReceiver.java | 2 +- .../receivers/BatteryReceiver.java | 10 +- .../receivers/BluetoothReceiver.java | 2 +- .../receivers/ConnectivityReceiver.java | 4 +- .../receivers/DateTimeListener.java | 2 +- .../receivers/DevicePositionListener.java | 4 +- .../receivers/HeadphoneJackListener.java | 2 +- .../automation2/receivers/NfcReceiver.java | 2 +- .../automation2/receivers/NoiseListener.java | 2 +- .../receivers/NotificationListener.java | 2 +- .../receivers/PhoneStatusListener.java | 6 +- .../receivers/ProcessListener.java | 2 +- 21 files changed, 136 insertions(+), 1300 deletions(-) diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index f9040a532..cc7935bdf 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,6 +1,17 @@ + + + + + + + + + + + @@ -12,6 +23,6 @@ - + \ No newline at end of file diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index bd5ee2b67..1120377d6 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -1,44 +1,22 @@ package com.jens.automation2; +import static com.jens.automation2.Trigger.triggerParameter2Split; + import android.annotation.SuppressLint; -import android.app.Notification; -import android.bluetooth.BluetoothDevice; import android.content.Context; import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; import android.os.Looper; -import android.os.Parcelable; -import android.service.notification.StatusBarNotification; -import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; import com.google.android.gms.location.DetectedActivity; -import com.jens.automation2.location.LocationProvider; -import com.jens.automation2.location.WifiBroadcastReceiver; import com.jens.automation2.receivers.ActivityDetectionReceiver; -import com.jens.automation2.receivers.BatteryReceiver; -import com.jens.automation2.receivers.BluetoothReceiver; -import com.jens.automation2.receivers.ConnectivityReceiver; -import com.jens.automation2.receivers.HeadphoneJackListener; -import com.jens.automation2.receivers.NfcReceiver; -import com.jens.automation2.receivers.NoiseListener; -import com.jens.automation2.receivers.NotificationListener; -import com.jens.automation2.receivers.PhoneStatusListener; -import com.jens.automation2.receivers.ProcessListener; import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import static com.jens.automation2.Trigger.triggerParameter2Split; - -import androidx.core.app.NotificationCompat; - -import org.apache.commons.lang3.StringUtils; - public class Rule implements Comparable { @@ -356,6 +334,17 @@ public class Rule implements Comparable return false; } + + public boolean hasNotAppliedSinceLastExecution() + { + for(Trigger oneTrigger : this.getTriggerSet()) + { + if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) + return true; + } + + return false; + } public boolean applies(Context context) { @@ -461,32 +450,6 @@ public class Rule implements Comparable } } - public boolean haveTriggersReallyChanged(Object triggeringObject) - { - boolean returnValue = false; - - try - { - for(int i=0; i < triggerSet.size(); i++) - { - Trigger t = (Trigger) triggerSet.get(i); - - if(t.hasStateRecentlyNotApplied(triggeringObject)) - { - Miscellaneous.logEvent("i", "Rule", "Rule \"" + getName() + "\" has trigger that flipped: " + t.toString(), 4); - returnValue = true; // only 1 trigger needs to have flipped recently - } - } - - return returnValue; - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Rule", "Error while checking if rule \"" + getName() + "\" haveTriggersReallyChanged(): " + Log.getStackTraceString(e), 1); - return false; - } - } - /** * Will activate the rule. Should be called by a separate execution thread * @param automationService @@ -497,9 +460,9 @@ public class Rule implements Comparable boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean doToggle = ruleToggle && isActuallyToggable; - boolean triggersApplyAnew = haveTriggersReallyChanged(new Date()); - if(notLastActive || force || doToggle || triggersApplyAnew) + //if(notLastActive || force || doToggle) + if(force || doToggle) { String message; if(!doToggle) diff --git a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java index 90ca7e6cf..f20ec6879 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java +++ b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java @@ -294,7 +294,7 @@ public class ActivityDetectionReceiver extends IntentService implements Automati ArrayList allRulesWithActivityDetection = Rule.findRuleCandidatesByActivityDetection(); for(int i=0; i { @@ -357,6 +341,17 @@ public class Rule implements Comparable return false; } + + public boolean hasNotAppliedSinceLastExecution() + { + for(Trigger oneTrigger : this.getTriggerSet()) + { + if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) + return true; + } + + return false; + } public boolean applies(Context context) { @@ -370,538 +365,8 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.pointOfInterest)) - { - // Am I here? - PointOfInterest activePoi = PointOfInterest.getActivePoi(); - if(activePoi != null) //entering one - { - if(oneTrigger.getPointOfInterest() != null) - { - if(activePoi.equals(oneTrigger.getPointOfInterest())) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're entering POI: " + oneTrigger.getPointOfInterest().getName() + ", not leaving it.", 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + oneTrigger.getPointOfInterest().getName() + ".", 4); - return false; - } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at a POI. Rule specifies not at none, so leaving any.", 4); - return false; - } - } - } - else //leaving one - { - // We are not at any POI. But if this trigger requires us NOT to be there, that may be fine. - if(oneTrigger.getPointOfInterest() != null) - { -// if(activePoi.equals(oneTrigger.getPointOfInterest())) -// { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "We are not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\".", 3); - return false; - } -// } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5); - return false; - } - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) - { - Date now = new Date(); - String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds()); - Time nowTime = Time.valueOf(timeString); - Calendar calNow = Calendar.getInstance(); - - - if(oneTrigger.getTimeFrame().getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK))) - { - if( - // Regular case, start time is lower than end time - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - && - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0 - ) - || - // Other case, start time higher than end time, timeframe goes over midnight - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), oneTrigger.getTimeFrame().getTriggerTimeStop()) < 0 - && - (Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - || - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0) - ) - - ) - { - // We are in the timeframe - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + "). Trigger of Rule " + this.getName() + " applies.", 3); - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 3); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 3); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the time. Trigger of Rule " + this.getName() + " doesn\'t apply..", 5); - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 5); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 5); - return false; - } - // return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the day. Trigger of Rule " + this.getName() + " doesn\'t apply.", 5); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.charging)) - { - if(BatteryReceiver.isDeviceCharging(context) == 0) - { - return false; // unknown charging state, can't activate rule under these conditions - } - else if(BatteryReceiver.isDeviceCharging(context) == 1) - { - if(oneTrigger.getTriggerParameter()) //rule says when charging, but we're currently discharging - return false; - } - else if(BatteryReceiver.isDeviceCharging(context) == 2) - { - if(!oneTrigger.getTriggerParameter()) //rule says when discharging, but we're currently charging - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.usb_host_connection)) - { - if(BatteryReceiver.isUsbHostConnected() != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.batteryLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(BatteryReceiver.getBatteryLevel() <= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - else - { - if(oneTrigger.getBatteryLevel() >= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.speed)) - { - if(oneTrigger.getTriggerParameter()) - { - if(LocationProvider.getSpeed() < oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - else - { - if(LocationProvider.getSpeed() > oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.noiseLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(NoiseListener.getNoiseLevelDb() < oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - else - { - if(NoiseListener.getNoiseLevelDb() > oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.wifiConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for wifi state", 4); - if(oneTrigger.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected - { - if(oneTrigger.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name specified, checking that.", 4); - if(!WifiBroadcastReceiver.getLastWifiSsid().equals(oneTrigger.getTriggerParameter2())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), oneTrigger.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); - return false; - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name matches. Rule will apply.", 4); - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "No wifi name specified, any will do.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi state not correct, demanded " + String.valueOf(oneTrigger.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.process_started_stopped)) - { - boolean running = ProcessListener.getRunningApps().contains(oneTrigger.getProcessName()); - - if(running) - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is currently running.", 4); - else - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is not running.", 4); - - if(running != oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4); - return false; - } - - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4); - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.airplaneMode)) - { - if(ConnectivityReceiver.isAirplaneMode(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.roaming)) - { - if(ConnectivityReceiver.isRoaming(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.phoneCall)) - { - String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - // state dir number - - if(elements[2].equals(Trigger.triggerPhoneCallNumberAny) || Miscellaneous.comparePhoneNumbers(PhoneStatusListener.getLastPhoneNumber(), elements[2]) || (Miscellaneous.isRegularExpression(elements[2]) && PhoneStatusListener.getLastPhoneNumber().matches(elements[2]))) - { - //if(PhoneStatusListener.isInACall() == oneTrigger.getTriggerParameter()) - if( - (elements[0].equals(Trigger.triggerPhoneCallStateRinging) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_RINGING) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStarted) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_OFFHOOK) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStopped) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_IDLE) - ) - { - if( - elements[1].equals(Trigger.triggerPhoneCallDirectionAny) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionIncoming) && PhoneStatusListener.getLastPhoneDirection() == 1) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionOutgoing) && PhoneStatusListener.getLastPhoneDirection() == 2) - ) - { - // Trigger conditions are met - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(oneTrigger.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(oneTrigger.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + oneTrigger.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.nfcTag)) - { - if(NfcReceiver.lastReadLabel == null) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3); - return false; - } - else if(!NfcReceiver.lastReadLabel.equals(oneTrigger.getNfcTagId())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + oneTrigger.getNfcTagId(), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.bluetoothConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for bluetooth...", 4); - - if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() != oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() == oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().length() > 0) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.headsetPlugged)) - { - if(HeadphoneJackListener.isHeadsetConnected() != oneTrigger.getTriggerParameter()) - return false; - else - if(oneTrigger.getHeadphoneType() != 2 && oneTrigger.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.notification)) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) - { - String[] params = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - - String myApp = params[0]; - String myTitleDir = params[1]; - String requiredTitle = params[2]; - String myTextDir = params[3]; - String requiredText; - if (params.length >= 5) - requiredText = params[4]; - else - requiredText = ""; - - if(oneTrigger.getTriggerParameter()) - { - // Check an active notification that is still there - - boolean foundMatch = false; - - for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) - { - if(getLastExecution() == null || sbn.getPostTime() > this.lastExecution.getTimeInMillis()) - { - String notificationApp = sbn.getPackageName(); - String notificationTitle = null; - String notificationText = null; - - Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5); - - if (!myApp.equals("-1")) - { - if (!notificationApp.equalsIgnoreCase(myApp)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5); - continue; - } - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - /* - If there are multiple notifications ("stacked") title or text might be null: - https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications - */ - - Bundle extras = sbn.getNotification().extras; - - // T I T L E - if (extras.containsKey(EXTRA_TITLE)) - notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE); - - if (!StringUtils.isEmpty(requiredTitle)) - { - if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5); - - // T E X T - - if (extras.containsKey(EXTRA_TEXT)) - notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT); - - if (!StringUtils.isEmpty(requiredText)) - { - if (!Miscellaneous.compare(myTextDir, requiredText, notificationText)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5); - - foundMatch = true; - break; - } - } - - if(!foundMatch) - return false; - } - else - { - // check a notification that is gone - - if(NotificationListener.getLastNotification() != null) - { - if(!NotificationListener.getLastNotification().isCreated()) - { - String app = NotificationListener.getLastNotification().getApp(); - String title = NotificationListener.getLastNotification().getTitle(); - String text = NotificationListener.getLastNotification().getText(); - - if (!myApp.equals("-1")) - { - if (!app.equalsIgnoreCase(myApp)) - return false; - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - if (requiredTitle.length() > 0) - { - if (!Miscellaneous.compare(myTitleDir, title, requiredTitle)) - return false; - } - - if (requiredText.length() > 0) - { - if (!Miscellaneous.compare(myTextDir, text, requiredText)) - return false; - } - } - else - return false; - } - } - } - } + if (!oneTrigger.applies(null, context)) + return false; } return true; @@ -960,32 +425,6 @@ public class Rule implements Comparable } } - public boolean haveTriggersReallyChanged(Object triggeringObject) - { - boolean returnValue = false; - - try - { - for(int i=0; i < triggerSet.size(); i++) - { - Trigger t = (Trigger) triggerSet.get(i); - - if(t.hasStateRecentlyNotApplied(triggeringObject)) - { - Miscellaneous.logEvent("i", "Rule", "Rule \"" + getName() + "\" has trigger that flipped: " + t.toString(), 4); - returnValue = true; // only 1 trigger needs to have flipped recently - } - } - - return returnValue; - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Rule", "Error while checking if rule \"" + getName() + "\" haveTriggersReallyChanged(): " + Log.getStackTraceString(e), 1); - return false; - } - } - /** * Will activate the rule. Should be called by a separate execution thread * @param automationService @@ -996,9 +435,9 @@ public class Rule implements Comparable boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean doToggle = ruleToggle && isActuallyToggable; - boolean triggersApplyAnew = haveTriggersReallyChanged(new Date()); - if(notLastActive || force || doToggle || triggersApplyAnew) + //if(notLastActive || force || doToggle) + if(force || doToggle) { String message; if(!doToggle) diff --git a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java index e541dc727..4a4fa69b6 100644 --- a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java @@ -1,46 +1,22 @@ package com.jens.automation2; +import static com.jens.automation2.Trigger.triggerParameter2Split; + import android.annotation.SuppressLint; -import android.app.Notification; -import android.bluetooth.BluetoothDevice; import android.content.Context; import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; import android.os.Looper; -import android.os.Parcelable; -import android.service.notification.StatusBarNotification; -import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; import com.google.android.gms.location.DetectedActivity; -import com.jens.automation2.location.LocationProvider; -import com.jens.automation2.location.WifiBroadcastReceiver; import com.jens.automation2.receivers.ActivityDetectionReceiver; -import com.jens.automation2.receivers.BatteryReceiver; -import com.jens.automation2.receivers.BluetoothReceiver; -import com.jens.automation2.receivers.ConnectivityReceiver; -import com.jens.automation2.receivers.HeadphoneJackListener; -import com.jens.automation2.receivers.NfcReceiver; -import com.jens.automation2.receivers.NoiseListener; -import com.jens.automation2.receivers.NotificationListener; -import com.jens.automation2.receivers.PhoneStatusListener; -import com.jens.automation2.receivers.ProcessListener; import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import static com.jens.automation2.Trigger.triggerParameter2Split; -import static com.jens.automation2.receivers.NotificationListener.EXTRA_TEXT; -import static com.jens.automation2.receivers.NotificationListener.EXTRA_TITLE; - -import androidx.core.app.NotificationCompat; - -import org.apache.commons.lang3.StringUtils; - public class Rule implements Comparable { @@ -358,6 +334,17 @@ public class Rule implements Comparable return false; } + + public boolean hasNotAppliedSinceLastExecution() + { + for(Trigger oneTrigger : this.getTriggerSet()) + { + if (oneTrigger.hasStateNotAppliedSinceLastRuleExecution()) + return true; + } + + return false; + } public boolean applies(Context context) { @@ -371,344 +358,27 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.pointOfInterest)) + if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) { - // Am I here? - PointOfInterest activePoi = PointOfInterest.getActivePoi(); - if(activePoi != null) //entering one - { - if(oneTrigger.getPointOfInterest() != null) - { - if(activePoi.equals(oneTrigger.getPointOfInterest())) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're entering POI: " + oneTrigger.getPointOfInterest().getName() + ", not leaving it.", 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. This is " + activePoi.getName() + ", not " + oneTrigger.getPointOfInterest().getName() + ".", 4); - return false; - } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at a POI. Rule specifies not at none, so leaving any.", 4); - return false; - } - } - } - else //leaving one - { - // We are not at any POI. But if this trigger requires us NOT to be there, that may be fine. - if(oneTrigger.getPointOfInterest() != null) - { -// if(activePoi.equals(oneTrigger.getPointOfInterest())) -// { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "We are not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\". But since that's required by this rule that's fine.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're not at POI \"" + oneTrigger.getPointOfInterest().getName() + "\".", 3); - return false; - } -// } - } - else if(oneTrigger.getPointOfInterest() == null) - { - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Rule doesn't apply. We're at no POI. Rule specifies to be at anyone.", 5); - return false; - } - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.timeFrame)) - { - Date now = new Date(); - String timeString = String.valueOf(now.getHours()) + ":" + String.valueOf(now.getMinutes()) + ":" + String.valueOf(now.getSeconds()); - Time nowTime = Time.valueOf(timeString); - Calendar calNow = Calendar.getInstance(); - - - if(oneTrigger.getTimeFrame().getDayList().contains(calNow.get(Calendar.DAY_OF_WEEK))) - { - if( - // Regular case, start time is lower than end time - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - && - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0 - ) - || - // Other case, start time higher than end time, timeframe goes over midnight - ( - Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), oneTrigger.getTimeFrame().getTriggerTimeStop()) < 0 - && - (Miscellaneous.compareTimes(oneTrigger.getTimeFrame().getTriggerTimeStart(), nowTime) >= 0 - || - Miscellaneous.compareTimes(nowTime, oneTrigger.getTimeFrame().getTriggerTimeStop()) > 0) - ) - - ) - { - // We are in the timeframe - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ") in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + "). Trigger of Rule " + this.getName() + " applies.", 3); - if(oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 3); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 3); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the time. Trigger of Rule " + this.getName() + " doesn\'t apply..", 5); - if(!oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "TimeFrame", "That's what's specified. Trigger of Rule " + this.getName() + " applies.", 5); - //return true; - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "That's not what's specified. Trigger of Rule " + this.getName() + " doesn't apply.", 5); - return false; - } - // return false; - } - } - else - { - Miscellaneous.logEvent("i", "TimeFrame", "We're currently (" + calNow.getTime().toString() + ", Day: " + String.valueOf(calNow.get(Calendar.DAY_OF_WEEK)) + ") not in the specified TimeFrame (" + oneTrigger.getTimeFrame().toString() + ") because of the day. Trigger of Rule " + this.getName() + " doesn\'t apply.", 5); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.charging)) - { - if(BatteryReceiver.isDeviceCharging(context) == 0) - { - return false; // unknown charging state, can't activate rule under these conditions - } - else if(BatteryReceiver.isDeviceCharging(context) == 1) - { - if(oneTrigger.getTriggerParameter()) //rule says when charging, but we're currently discharging - return false; - } - else if(BatteryReceiver.isDeviceCharging(context) == 2) - { - if(!oneTrigger.getTriggerParameter()) //rule says when discharging, but we're currently charging - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.usb_host_connection)) - { - if(BatteryReceiver.isUsbHostConnected() != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.batteryLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(BatteryReceiver.getBatteryLevel() <= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryLowerThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - else - { - if(oneTrigger.getBatteryLevel() >= oneTrigger.getBatteryLevel()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyBatteryHigherThan) + " " + String.valueOf(oneTrigger.getBatteryLevel()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.speed)) - { - if(oneTrigger.getTriggerParameter()) - { - if(LocationProvider.getSpeed() < oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreSlowerThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - else - { - if(LocationProvider.getSpeed() > oneTrigger.getSpeed()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWeAreFasterThan) + " " + String.valueOf(oneTrigger.getSpeed()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.noiseLevel)) - { - if(oneTrigger.getTriggerParameter()) - { - if(NoiseListener.getNoiseLevelDb() < oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsQuieterThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - else - { - if(NoiseListener.getNoiseLevelDb() > oneTrigger.getNoiseLevelDb()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyItsLouderThan) + " " + String.valueOf(oneTrigger.getNoiseLevelDb()), 3); - return false; - } - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.wifiConnection)) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for wifi state", 4); - if(oneTrigger.getTriggerParameter() == WifiBroadcastReceiver.lastConnectedState) // connected / disconnected - { - if(oneTrigger.getTriggerParameter2().length() > 0) // only check if any wifi name specified, otherwise any wifi will do - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name specified, checking that.", 4); - if(!WifiBroadcastReceiver.getLastWifiSsid().equals(oneTrigger.getTriggerParameter2())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), oneTrigger.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); - return false; - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi name matches. Rule will apply.", 4); - } - else - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "No wifi name specified, any will do.", 4); - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Wifi state not correct, demanded " + String.valueOf(oneTrigger.getTriggerParameter() + ", got " + String.valueOf(WifiBroadcastReceiver.lastConnectedState)), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.process_started_stopped)) - { - boolean running = ProcessListener.getRunningApps().contains(oneTrigger.getProcessName()); - - if(running) - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is currently running.", 4); - else - Miscellaneous.logEvent("i", "ProcessMonitoring", "App " + oneTrigger.getProcessName() + " is not running.", 4); - - if(running != oneTrigger.getTriggerParameter()) - { - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger doesn't apply.", 4); - return false; - } - - Miscellaneous.logEvent("i", "ProcessMonitoring", "Trigger applies.", 4); - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.airplaneMode)) - { - if(ConnectivityReceiver.isAirplaneMode(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.roaming)) - { - if(ConnectivityReceiver.isRoaming(context) != oneTrigger.getTriggerParameter()) - { - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.phoneCall)) - { - String[] elements = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - // state dir number - - if(elements[2].equals(Trigger.triggerPhoneCallNumberAny) || Miscellaneous.comparePhoneNumbers(PhoneStatusListener.getLastPhoneNumber(), elements[2]) || (Miscellaneous.isRegularExpression(elements[2]) && PhoneStatusListener.getLastPhoneNumber().matches(elements[2]))) - { - //if(PhoneStatusListener.isInACall() == oneTrigger.getTriggerParameter()) - if( - (elements[0].equals(Trigger.triggerPhoneCallStateRinging) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_RINGING) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStarted) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_OFFHOOK) - || - (elements[0].equals(Trigger.triggerPhoneCallStateStopped) && PhoneStatusListener.getCurrentState() == TelephonyManager.CALL_STATE_IDLE) - ) - { - if( - elements[1].equals(Trigger.triggerPhoneCallDirectionAny) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionIncoming) && PhoneStatusListener.getLastPhoneDirection() == 1) - || - (elements[1].equals(Trigger.triggerPhoneCallDirectionOutgoing) && PhoneStatusListener.getLastPhoneDirection() == 2) - ) - { - // Trigger conditions are met - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(oneTrigger.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(oneTrigger.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); - return false; - } - } - else - { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + oneTrigger.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.nfcTag)) - { - if(NfcReceiver.lastReadLabel == null) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyNoTagLabel), 3); - return false; - } - else if(!NfcReceiver.lastReadLabel.equals(oneTrigger.getNfcTagId())) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongTagLabel) + " " + NfcReceiver.lastReadLabel + " / " + oneTrigger.getNfcTagId(), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) - { - if(ActivityDetectionReceiver.getActivityDetectionLastResult() != null) + if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) { boolean found = false; - for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) { - if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) found = true; } - if(!found) + if (!found) { Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); return false; } else { - for(DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if(oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) { Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); return false; @@ -717,220 +387,10 @@ public class Rule implements Comparable } } } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.bluetoothConnection)) + else { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), "Checking for bluetooth...", 4); - - if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() != oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().equals("")) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isAnyDeviceConnected() == oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isAnyDeviceInRange() == oneTrigger.getTriggerParameter()) - return false; - } - } - else if(oneTrigger.getBluetoothDeviceAddress().length() > 0) - { - if(oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_CONNECTED)) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else if((oneTrigger.getBluetoothEvent().equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))) - { - if(BluetoothReceiver.isDeviceCurrentlyConnected(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - else - { - // range - if(BluetoothReceiver.isDeviceInRange(BluetoothReceiver.getDeviceByAddress(oneTrigger.getBluetoothDeviceAddress())) != oneTrigger.getTriggerParameter()) - return false; - } - } - else - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyStateNotCorrect), 3); + if (!oneTrigger.applies(null, context)) return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.headsetPlugged)) - { - if(HeadphoneJackListener.isHeadsetConnected() != oneTrigger.getTriggerParameter()) - return false; - else - if(oneTrigger.getHeadphoneType() != 2 && oneTrigger.getHeadphoneType() != HeadphoneJackListener.getHeadphoneType()) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), context.getResources().getString(R.string.ruleDoesntApplyWrongHeadphoneType), 3); - return false; - } - } - else if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.notification)) - { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) - { - String[] params = oneTrigger.getTriggerParameter2().split(triggerParameter2Split); - - String myApp = params[0]; - String myTitleDir = params[1]; - String requiredTitle = params[2]; - String myTextDir = params[3]; - String requiredText; - if (params.length >= 5) - requiredText = params[4]; - else - requiredText = ""; - - if(oneTrigger.getTriggerParameter()) - { - // Check an active notification that is still there - - boolean foundMatch = false; - - for (StatusBarNotification sbn : NotificationListener.getInstance().getActiveNotifications()) - { - if(getLastExecution() == null || sbn.getPostTime() > this.lastExecution.getTimeInMillis()) - { - String notificationApp = sbn.getPackageName(); - String notificationTitle = null; - String notificationText = null; - - Miscellaneous.logEvent("i", "NotificationCheck", "Checking if this notification matches our rule " + this.getName() + ". App: " + notificationApp + ", title: " + notificationTitle + ", text: " + notificationText, 5); - - if (!myApp.equals("-1")) - { - if (!notificationApp.equalsIgnoreCase(myApp)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification app name does not match rule.", 5); - continue; - } - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - /* - If there are multiple notifications ("stacked") title or text might be null: - https://stackoverflow.com/questions/28047767/notificationlistenerservice-not-reading-text-of-stacked-notifications - */ - - Bundle extras = sbn.getNotification().extras; - - // T I T L E - if (extras.containsKey(EXTRA_TITLE)) - notificationTitle = sbn.getNotification().extras.getString(EXTRA_TITLE); - - if (!StringUtils.isEmpty(requiredTitle)) - { - if (!Miscellaneous.compare(myTitleDir, requiredTitle, notificationTitle)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification title does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required title for a notification trigger was not specified.", 5); - - // T E X T - - if (extras.containsKey(EXTRA_TEXT)) - notificationText = sbn.getNotification().extras.getString(EXTRA_TEXT); - - if (!StringUtils.isEmpty(requiredText)) - { - if (!Miscellaneous.compare(myTextDir, requiredText, notificationText)) - { - Miscellaneous.logEvent("i", "NotificationCheck", "Notification text does not match rule.", 5); - continue; - } - } - else - Miscellaneous.logEvent("i", "NotificationCheck", "A required text for a notification trigger was not specified.", 5); - - foundMatch = true; - break; - } - } - - if(!foundMatch) - return false; - } - else - { - // check a notification that is gone - - if(NotificationListener.getLastNotification() != null) - { - if(!NotificationListener.getLastNotification().isCreated()) - { - String app = NotificationListener.getLastNotification().getApp(); - String title = NotificationListener.getLastNotification().getTitle(); - String text = NotificationListener.getLastNotification().getText(); - - if (!myApp.equals("-1")) - { - if (!app.equalsIgnoreCase(myApp)) - return false; - } - else - { - if(myApp.equals(BuildConfig.APPLICATION_ID)) - { - return false; - } - } - - if (requiredTitle.length() > 0) - { - if (!Miscellaneous.compare(myTitleDir, title, requiredTitle)) - return false; - } - - if (requiredText.length() > 0) - { - if (!Miscellaneous.compare(myTextDir, text, requiredText)) - return false; - } - } - else - return false; - } - } - } } } @@ -990,32 +450,6 @@ public class Rule implements Comparable } } - public boolean haveTriggersReallyChanged(Object triggeringObject) - { - boolean returnValue = false; - - try - { - for(int i=0; i < triggerSet.size(); i++) - { - Trigger t = (Trigger) triggerSet.get(i); - - if(t.hasStateRecentlyNotApplied(triggeringObject)) - { - Miscellaneous.logEvent("i", "Rule", "Rule \"" + getName() + "\" has trigger that flipped: " + t.toString(), 4); - returnValue = true; // only 1 trigger needs to have flipped recently - } - } - - return returnValue; - } - catch(Exception e) - { - Miscellaneous.logEvent("e", "Rule", "Error while checking if rule \"" + getName() + "\" haveTriggersReallyChanged(): " + Log.getStackTraceString(e), 1); - return false; - } - } - /** * Will activate the rule. Should be called by a separate execution thread * @param automationService @@ -1026,9 +460,9 @@ public class Rule implements Comparable boolean notLastActive = getLastActivatedRule() == null || !getLastActivatedRule().equals(Rule.this); boolean doToggle = ruleToggle && isActuallyToggable; - boolean triggersApplyAnew = haveTriggersReallyChanged(new Date()); - if(notLastActive || force || doToggle || triggersApplyAnew) + //if(notLastActive || force || doToggle) + if(force || doToggle) { String message; if(!doToggle) diff --git a/app/src/main/java/com/jens/automation2/PointOfInterest.java b/app/src/main/java/com/jens/automation2/PointOfInterest.java index 7a42031a3..edf395970 100644 --- a/app/src/main/java/com/jens/automation2/PointOfInterest.java +++ b/app/src/main/java/com/jens/automation2/PointOfInterest.java @@ -264,7 +264,7 @@ public class PointOfInterest implements Comparable for(int i=0; i Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2); for(int i=0; i was state different in previous step - - try - { - switch(getTriggerType()) - { - case timeFrame: - if(!checkDateTime(triggeringObject, true)) - return false; - break; - default: - break; - } - + if(getParentRule().getLastExecution() == null) return true; - } - catch(Exception e) + else if(lastTimeNotApplied != null) { - Miscellaneous.logEvent("e", "Trigger", "Error while checking if rule " + getParentRule().getName() + " applies. Error occured in trigger " + this.getParentRule().toString() + "." + Miscellaneous.lineSeparator + Log.getStackTraceString(e), 1); - return false; + if(lastTimeNotApplied.getTimeInMillis() > getParentRule().getLastExecution().getTimeInMillis()) + { + return true; + } } + + return false; } boolean checkCharging() diff --git a/app/src/main/java/com/jens/automation2/location/LocationProvider.java b/app/src/main/java/com/jens/automation2/location/LocationProvider.java index 8a2956ecc..d50ac70bc 100644 --- a/app/src/main/java/com/jens/automation2/location/LocationProvider.java +++ b/app/src/main/java/com/jens/automation2/location/LocationProvider.java @@ -201,7 +201,7 @@ public class LocationProvider ArrayList ruleCandidates = Rule.findRuleCandidatesBySpeed(); for (Rule oneRule : ruleCandidates) { - if (oneRule.applies(this.getParentService())) + if (oneRule.applies(this.getParentService()) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(getParentService(), false); } } diff --git a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java index c2b2ea534..b8a9a8c70 100644 --- a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java @@ -147,7 +147,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver ArrayList ruleCandidates = Rule.findRuleCandidatesByWifiConnection(); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(automationServiceInstance)) + if(oneRule.applies(automationServiceInstance) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationServiceInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java index 0d75214d3..9d2de54ed 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java @@ -206,7 +206,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByCharging(true); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByBatteryLevel(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByCharging(false); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByUsbHost(true); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(context)) + if(oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationServiceRef, false); } @@ -278,7 +278,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByUsbHost(false); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(context)) + if(oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationServiceRef, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java index 0415c7814..0abc46b9e 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java @@ -127,7 +127,7 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi ArrayList ruleCandidates = Rule.findRuleCandidatesByBluetoothConnection(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming); for(int i=0; i allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime); for(int i=0; i ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.devicePosition); for (int i = 0; i < ruleCandidates.size(); i++) { - if (ruleCandidates.get(i).applies(Miscellaneous.getAnyContext())) + if (ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java index fc377183b..807fcd417 100644 --- a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java @@ -77,7 +77,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati ArrayList ruleCandidates = Rule.findRuleCandidatesByHeadphoneJack(isHeadsetConnected()); for(int i=0; i allRulesWithNfcTags = Rule.findRuleCandidatesByNfc(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByNoiseLevel(); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(automationService)) + if(oneRule.applies(automationService) && oneRule.hasNotAppliedSinceLastExecution()) oneRule.activate(automationService, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java index 8daaf3443..f3d97b068 100644 --- a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java @@ -96,7 +96,7 @@ public class NotificationListener extends NotificationListenerService ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification); for (int i = 0; i < ruleCandidates.size(); i++) { - if (ruleCandidates.get(i).applies(NotificationListener.this)) + if (ruleCandidates.get(i).applies(NotificationListener.this) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } // } diff --git a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java index ae67a2f8e..9e9f41005 100644 --- a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java @@ -114,7 +114,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if(ruleCandidates.get(i).applies(asInstance)) + if(ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(asInstance, false); } } @@ -146,7 +146,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if (asInstance != null) - if (ruleCandidates.get(i).applies(asInstance)) + if (ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(asInstance, false); } } @@ -183,7 +183,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if(ruleCandidates.get(i).applies(asInstance)) + if(ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) ruleCandidates.get(i).activate(asInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java index 42778dc60..4390ea0bd 100644 --- a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java @@ -62,7 +62,7 @@ public class ProcessListener implements AutomationListenerInterface ArrayList ruleCandidates = Rule.findRuleCandidatesByProcess(); for(int i=0; i Date: Sat, 4 Dec 2021 13:24:43 +0100 Subject: [PATCH 3/8] Rework --- .idea/deploymentTargetDropDown.xml | 11 --- .../java/com/jens/automation2/Rule.java | 96 ++++++++++--------- .../java/com/jens/automation2/Trigger.java | 61 +++++++++++- .../receivers/DevicePositionListener.java | 25 ++++- 4 files changed, 136 insertions(+), 57 deletions(-) diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index cc7935bdf..9f3e9f1bb 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,17 +1,6 @@ - - - - - - - - - - - diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index 1120377d6..731df84c8 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -358,40 +358,8 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) - { - if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) - { - boolean found = false; - for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) - found = true; - } - - if (!found) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); - return false; - } - else - { - for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); - return false; - } - } - } - } - } - else - { - if (!oneTrigger.applies(null, context)) - return false; - } + if (!oneTrigger.applies(null, context)) + return false; } return true; @@ -401,6 +369,44 @@ public class Rule implements Comparable return false; } + /** + * This is actually a function of the class Trigger, but Rule is already distinguished by flavors, Trigger is not. + * Hence it is here. + * @param oneTrigger + * @return + */ + boolean checkActivityDetection(Trigger oneTrigger) + { + if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) + { + boolean found = false; + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) + found = true; + } + + if (!found) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); + return false; + } + else + { + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); + return false; + } + } + } + } + + return true; + } + private class ActivateRuleTask extends AsyncTask { boolean wasActivated = false; @@ -418,7 +424,8 @@ public class Rule implements Comparable if (Looper.myLooper() == null) Looper.prepare(); - + + setLastExecution(Calendar.getInstance()); wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]); return null; @@ -443,7 +450,7 @@ public class Rule implements Comparable */ if(wasActivated) { - setLastExecution(Calendar.getInstance()); +// setLastExecution(Calendar.getInstance()); AutomationService.updateNotification(); ActivityMainScreen.updateMainScreen(); super.onPostExecute(result); @@ -462,8 +469,8 @@ public class Rule implements Comparable boolean doToggle = ruleToggle && isActuallyToggable; //if(notLastActive || force || doToggle) - if(force || doToggle) - { +// if(force || doToggle) +// { String message; if(!doToggle) message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName()); @@ -492,6 +499,7 @@ public class Rule implements Comparable { Rule.ruleRunHistory.add(0, Rule.this); // add at beginning for better visualization Rule.lastActivatedRuleActivationTime = new Date(); + while(ruleRunHistory.size() > Settings.rulesThatHaveBeenRanHistorySize) ruleRunHistory.remove(ruleRunHistory.size()-1); String history = ""; @@ -507,12 +515,12 @@ public class Rule implements Comparable } Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2); - } - else - { - Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3); - return false; - } +// } +// else +// { +// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3); +// return false; +// } return true; } diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index 46259d821..d38a0ca5f 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -1,7 +1,10 @@ package com.jens.automation2; +import static android.content.Context.DEVICE_POLICY_SERVICE; + import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.service.notification.StatusBarNotification; @@ -15,6 +18,7 @@ import com.jens.automation2.location.WifiBroadcastReceiver; import com.jens.automation2.receivers.BatteryReceiver; import com.jens.automation2.receivers.BluetoothReceiver; import com.jens.automation2.receivers.ConnectivityReceiver; +import com.jens.automation2.receivers.DevicePositionListener; import com.jens.automation2.receivers.HeadphoneJackListener; import com.jens.automation2.receivers.NfcReceiver; import com.jens.automation2.receivers.NoiseListener; @@ -109,7 +113,13 @@ public class Trigger result = false; break; case devicePosition: - and others + if(!checkDevicePosition()) + result = false; + break; + case activityDetection: + if(!getParentRule().checkActivityDetection(this)) + result = false; + break; default: break; } @@ -266,6 +276,55 @@ public class Trigger return true; } + boolean checkDevicePosition() + { + String devicePositionPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split); + float desiredAzimuth = Float.parseFloat(devicePositionPieces[0]); + float desiredAzimuthTolerance = Float.parseFloat(devicePositionPieces[1]); + float desiredPitch = Float.parseFloat(devicePositionPieces[2]); + float desiredPitchTolerance = Float.parseFloat(devicePositionPieces[3]); + float desiredRoll = Float.parseFloat(devicePositionPieces[4]); + float desiredRollTolerance = Float.parseFloat(devicePositionPieces[5]); + float currentAzimuth = DevicePositionListener.getInstance().getAzimuth(); + float currentPitch = DevicePositionListener.getInstance().getPitch(); + float currentRoll = DevicePositionListener.getInstance().getRoll(); + + if( + !( + currentAzimuth <= desiredAzimuth + desiredAzimuthTolerance + && + currentAzimuth >= desiredAzimuth - desiredAzimuthTolerance + ) + ) + { + return false; + } + + if( + !( + currentPitch <= desiredPitch + desiredPitchTolerance + && + currentPitch >= desiredPitch - desiredPitchTolerance + ) + ) + { + return false; + } + + if( + !( + currentRoll <= desiredRoll + desiredRollTolerance + && + currentRoll >= desiredRoll - desiredRollTolerance + ) + ) + { + return false; + } + + return true; + } + boolean checkHeadsetPlugged() { if(HeadphoneJackListener.isHeadsetConnected() != this.getTriggerParameter()) diff --git a/app/src/main/java/com/jens/automation2/receivers/DevicePositionListener.java b/app/src/main/java/com/jens/automation2/receivers/DevicePositionListener.java index b233dd156..ccef6ac84 100644 --- a/app/src/main/java/com/jens/automation2/receivers/DevicePositionListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/DevicePositionListener.java @@ -49,6 +49,21 @@ public class DevicePositionListener implements SensorEventListener, AutomationLi return instance; } + public float getAzimuth() + { + return azimuth; + } + + public float getPitch() + { + return pitch; + } + + public float getRoll() + { + return roll; + } + public void startSensorFromConfigActivity(Context context, ActivityManageTriggerDevicePosition activityManageTriggerDevicePositionInstance) { this.activityManageTriggerDevicePositionInstance = activityManageTriggerDevicePositionInstance; @@ -129,7 +144,15 @@ public class DevicePositionListener implements SensorEventListener, AutomationLi ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.devicePosition); for (int i = 0; i < ruleCandidates.size(); i++) { - if (ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) + boolean applies = ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()); + boolean flipped = ruleCandidates.get(i).hasNotAppliedSinceLastExecution(); + +// if ( +// ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()) +// && +// ruleCandidates.get(i).hasNotAppliedSinceLastExecution() +// ) + if(applies && flipped) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } } From 8b29dd0985c8f4afb854fed071eb3e35ba4f1715 Mon Sep 17 00:00:00 2001 From: jens Date: Sun, 5 Dec 2021 14:51:00 +0100 Subject: [PATCH 4/8] Rework --- .../receivers/ActivityDetectionReceiver.java | 2 +- .../java/com/jens/automation2/Rule.java | 48 +++++----- .../java/com/jens/automation2/Rule.java | 95 ++++++++++--------- .../ActivityManageTriggerDevicePosition.java | 26 ++++- .../com/jens/automation2/PointOfInterest.java | 4 +- .../location/LocationProvider.java | 2 +- .../location/WifiBroadcastReceiver.java | 2 +- .../receivers/BatteryReceiver.java | 10 +- .../receivers/BluetoothReceiver.java | 2 +- .../receivers/ConnectivityReceiver.java | 4 +- .../receivers/DateTimeListener.java | 2 +- .../receivers/DevicePositionListener.java | 17 ++-- .../receivers/HeadphoneJackListener.java | 2 +- .../automation2/receivers/NfcReceiver.java | 2 +- .../automation2/receivers/NoiseListener.java | 2 +- .../receivers/NotificationListener.java | 19 ++-- .../receivers/PhoneStatusListener.java | 6 +- .../receivers/ProcessListener.java | 45 ++++----- app/src/main/res/values/strings.xml | 3 +- 19 files changed, 157 insertions(+), 136 deletions(-) diff --git a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java index f20ec6879..8dd7755fa 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java +++ b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java @@ -294,7 +294,7 @@ public class ActivityDetectionReceiver extends IntentService implements Automati ArrayList allRulesWithActivityDetection = Rule.findRuleCandidatesByActivityDetection(); for(int i=0; i Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3); return false; } - + + /** + * This is actually a function of the class Trigger, but Rule is already distinguished by flavors, Trigger is not. + * Hence it is here. + * @param oneTrigger + * @return + */ + boolean checkActivityDetection(Trigger oneTrigger) + { + /* + Feature not present in FOSS edition. + */ + return false; + } + private class ActivateRuleTask extends AsyncTask { boolean wasActivated = false; @@ -393,7 +396,8 @@ public class Rule implements Comparable if (Looper.myLooper() == null) Looper.prepare(); - + + setLastExecution(Calendar.getInstance()); wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]); return null; @@ -418,7 +422,7 @@ public class Rule implements Comparable */ if(wasActivated) { - setLastExecution(Calendar.getInstance()); +// setLastExecution(Calendar.getInstance()); AutomationService.updateNotification(); ActivityMainScreen.updateMainScreen(); super.onPostExecute(result); @@ -437,8 +441,8 @@ public class Rule implements Comparable boolean doToggle = ruleToggle && isActuallyToggable; //if(notLastActive || force || doToggle) - if(force || doToggle) - { +// if(force || doToggle) +// { String message; if(!doToggle) message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName()); @@ -482,12 +486,12 @@ public class Rule implements Comparable } Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2); - } - else - { - Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3); - return false; - } +// } +// else +// { +// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3); +// return false; +// } return true; } diff --git a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java index 4a4fa69b6..63d07eb40 100644 --- a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java @@ -358,40 +358,8 @@ public class Rule implements Comparable { for(Trigger oneTrigger : this.getTriggerSet()) { - if(oneTrigger.getTriggerType().equals(Trigger.Trigger_Enum.activityDetection)) - { - if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) - { - boolean found = false; - for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) - found = true; - } - - if (!found) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); - return false; - } - else - { - for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) - { - if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) - { - Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); - return false; - } - } - } - } - } - else - { - if (!oneTrigger.applies(null, context)) - return false; - } + if (!oneTrigger.applies(null, context)) + return false; } return true; @@ -400,6 +368,44 @@ public class Rule implements Comparable Miscellaneous.logEvent("i", String.format(context.getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(context.getResources().getString(R.string.ruleIsDeactivatedCantApply), this.getName()), 3); return false; } + + /** + * This is actually a function of the class Trigger, but Rule is already distinguished by flavors, Trigger is not. + * Hence it is here. + * @param oneTrigger + * @return + */ + boolean checkActivityDetection(Trigger oneTrigger) + { + if (ActivityDetectionReceiver.getActivityDetectionLastResult() != null) + { + boolean found = false; + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType()) + found = true; + } + + if (!found) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyActivityNotPresent), ActivityDetectionReceiver.getDescription(oneTrigger.getActivityDetectionType())), 3); + return false; + } + else + { + for (DetectedActivity oneDetectedActivity : ActivityDetectionReceiver.getActivityDetectionLastResult().getProbableActivities()) + { + if (oneDetectedActivity.getType() == oneTrigger.getActivityDetectionType() && oneDetectedActivity.getConfidence() < Settings.activityDetectionRequiredProbability) + { + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyActivityGivenButTooLowProbability), ActivityDetectionReceiver.getDescription(oneDetectedActivity.getType()), String.valueOf(oneDetectedActivity.getConfidence()), String.valueOf(Settings.activityDetectionRequiredProbability)), 3); + return false; + } + } + } + } + + return true; + } private class ActivateRuleTask extends AsyncTask { @@ -418,7 +424,8 @@ public class Rule implements Comparable if (Looper.myLooper() == null) Looper.prepare(); - + + setLastExecution(Calendar.getInstance()); wasActivated = activateInternally((AutomationService)params[0], (Boolean)params[1]); return null; @@ -443,7 +450,7 @@ public class Rule implements Comparable */ if(wasActivated) { - setLastExecution(Calendar.getInstance()); +// setLastExecution(Calendar.getInstance()); AutomationService.updateNotification(); ActivityMainScreen.updateMainScreen(); super.onPostExecute(result); @@ -462,8 +469,8 @@ public class Rule implements Comparable boolean doToggle = ruleToggle && isActuallyToggable; //if(notLastActive || force || doToggle) - if(force || doToggle) - { +// if(force || doToggle) +// { String message; if(!doToggle) message = String.format(automationService.getResources().getString(R.string.ruleActivate), Rule.this.getName()); @@ -507,12 +514,12 @@ public class Rule implements Comparable } Miscellaneous.logEvent("i", "Rule", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleActivationComplete), Rule.this.getName()), 2); - } - else - { - Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3); - return false; - } +// } +// else +// { +// Miscellaneous.logEvent("i", "Rule", "Request to activate rule " + Rule.this.getName() + ", but it is the last one that was activated. Won't do it again.", 3); +// return false; +// } return true; } diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java index 69fd71da2..42634bfa7 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java @@ -28,6 +28,8 @@ public class ActivityManageTriggerDevicePosition extends Activity boolean editMode = false; + boolean messageDisplayed = false; + float desiredAzimuth, desiredPitch, desiredRoll, desiredAzimuthTolerance, desiredPitchTolerance, desiredRollTolerance; public void updateFields(float azimuth, float pitch, float roll) @@ -185,8 +187,28 @@ public class ActivityManageTriggerDevicePosition extends Activity float dp = Float.parseFloat(etDesiredPitch.getText().toString()); float dr = Float.parseFloat(etDesiredRoll.getText().toString()); - if(Math.abs(da) <= 180 || Math.abs(dp) <= 180 || Math.abs(dr) <= 180) - return true; + if(Math.abs(da) > 180 || Math.abs(dp) > 180 || Math.abs(dr) > 180) + { + return false; + } + + if(!messageDisplayed) + { + float dat = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString()); + float dpt = Float.parseFloat(etDesiredPitchTolerance.getText().toString()); + float drt = Float.parseFloat(etDesiredRollTolerance.getText().toString()); + + /* + The user may enter a tolerance of 180° for two directions, but not all three. + Otherwise this trigger would always apply. + */ + if (Math.abs(dat) >= 180 && Math.abs(dpt) >= 180 && Math.abs(drt) >= 180) + { + messageDisplayed = true; + Miscellaneous.messageBox(getResources().getString(R.string.warning), getResources().getString(R.string.toleranceOf180OnlyAllowedIn2Fields), ActivityManageTriggerDevicePosition.this).show(); + return false; + } + } } return false; diff --git a/app/src/main/java/com/jens/automation2/PointOfInterest.java b/app/src/main/java/com/jens/automation2/PointOfInterest.java index edf395970..2788541c0 100644 --- a/app/src/main/java/com/jens/automation2/PointOfInterest.java +++ b/app/src/main/java/com/jens/automation2/PointOfInterest.java @@ -264,7 +264,7 @@ public class PointOfInterest implements Comparable for(int i=0; i Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesBySpeed(); for (Rule oneRule : ruleCandidates) { - if (oneRule.applies(this.getParentService()) && oneRule.hasNotAppliedSinceLastExecution()) + if ((oneRule.applies(this.getParentService()) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) oneRule.activate(getParentService(), false); } } diff --git a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java index b8a9a8c70..b1673b80b 100644 --- a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java @@ -147,7 +147,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver ArrayList ruleCandidates = Rule.findRuleCandidatesByWifiConnection(); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(automationServiceInstance) && oneRule.hasNotAppliedSinceLastExecution()) + if((oneRule.applies(automationServiceInstance) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) oneRule.activate(automationServiceInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java index 9d2de54ed..2fd8db3ea 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java @@ -206,7 +206,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByCharging(true); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByBatteryLevel(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByCharging(false); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByUsbHost(true); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) + if((oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) oneRule.activate(automationServiceRef, false); } @@ -278,7 +278,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByUsbHost(false); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) + if((oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) oneRule.activate(automationServiceRef, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java index 0abc46b9e..2fc23ce16 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java @@ -127,7 +127,7 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi ArrayList ruleCandidates = Rule.findRuleCandidatesByBluetoothConnection(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming); for(int i=0; i allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime); for(int i=0; i ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.devicePosition); for (int i = 0; i < ruleCandidates.size(); i++) { - boolean applies = ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()); - boolean flipped = ruleCandidates.get(i).hasNotAppliedSinceLastExecution(); + applies = ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()); + flipped = ruleCandidates.get(i).hasNotAppliedSinceLastExecution(); + toggable = ruleCandidates.get(i).isActuallyToggable(); -// if ( -// ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()) -// && -// ruleCandidates.get(i).hasNotAppliedSinceLastExecution() -// ) - if(applies && flipped) + if((applies && flipped) || toggable) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java index 807fcd417..748f083f5 100644 --- a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java @@ -77,7 +77,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati ArrayList ruleCandidates = Rule.findRuleCandidatesByHeadphoneJack(isHeadsetConnected()); for(int i=0; i allRulesWithNfcTags = Rule.findRuleCandidatesByNfc(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByNoiseLevel(); for(Rule oneRule : ruleCandidates) { - if(oneRule.applies(automationService) && oneRule.hasNotAppliedSinceLastExecution()) + if((oneRule.applies(automationService) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) oneRule.activate(automationService, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java index f3d97b068..efffeed61 100644 --- a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java @@ -89,19 +89,12 @@ public class NotificationListener extends NotificationListenerService lastNotification.title = title; lastNotification.text = text; -// if(lastResponseToNotification == null || lastResponseToNotification.getTimeInMillis() < lastNotification.publishTime.getTimeInMillis()) -// { -// lastResponseToNotification = Calendar.getInstance(); - - ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification); - for (int i = 0; i < ruleCandidates.size(); i++) - { - if (ruleCandidates.get(i).applies(NotificationListener.this) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) - ruleCandidates.get(i).activate(AutomationService.getInstance(), false); - } -// } -// else -// Miscellaneous.logEvent("e", "NotificationCheck", "Ignoring notification as it is old.", 5); + ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification); + for (int i = 0; i < ruleCandidates.size(); i++) + { + if ((ruleCandidates.get(i).applies(NotificationListener.this) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) + ruleCandidates.get(i).activate(AutomationService.getInstance(), false); + } } return false; diff --git a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java index 9e9f41005..98e633c02 100644 --- a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java @@ -114,7 +114,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if(ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) + if((ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) ruleCandidates.get(i).activate(asInstance, false); } } @@ -146,7 +146,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if (asInstance != null) - if (ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) + if ((ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) ruleCandidates.get(i).activate(asInstance, false); } } @@ -183,7 +183,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if(ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) + if((ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) ruleCandidates.get(i).activate(asInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java index 4390ea0bd..a0eec0aaf 100644 --- a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java @@ -43,34 +43,27 @@ public class ProcessListener implements AutomationListenerInterface @Override public void handleMessage(Message msg) { -// try -// { - Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.messageReceivedStatingProcessMonitoringIsComplete), 5); - // This will take care of results delivered by the actual monitoring instance - - for(String entry : getRunningApps()) - Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.runningApp), entry, 5); - - // execute matching rules containing processes - if(getRecentlyStartedApps().size()>0 | getRecentlyStoppedApps().size()>0) + Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.processMonitoring), automationService.getResources().getString(R.string.messageReceivedStatingProcessMonitoringIsComplete), 5); + // This will take care of results delivered by the actual monitoring instance + + for(String entry : getRunningApps()) + Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.runningApp), entry, 5); + + // execute matching rules containing processes + if(getRecentlyStartedApps().size()>0 | getRecentlyStoppedApps().size()>0) + { + for(String entry : getRecentlyStartedApps()) + Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStarted), entry, 3); + for(String entry : getRecentlyStoppedApps()) + Miscellaneous.logEvent("i", automationService.getResources().getString(R.string.appStopped), entry, 3); + + ArrayList ruleCandidates = Rule.findRuleCandidatesByProcess(); + for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByProcess(); - for(int i=0; ihandleMessage(): " + e.getMessage()); -// } + } } }; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4f521d58..5c0a5d59c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -719,7 +719,8 @@ Pitch: Roll: Enter valid numbers in all fields. - When you move your device the below numbers should update. What you can see there, is the current \"position\" of your device. If it is in the desired position, click the apply button to copy the current values to the desired fields.\nBecause you will probably not be able to reach this exact position ever again, enter a tolerance. The is amount to which the position can deviate in one direction or the other. + When you move your device the below numbers will update. What you can see there, is the current \"position\" of your device measured in degrees. If it is in the desired position, click the apply button to copy the current values to the desired fields.\nBecause reaching this exact position ever again is highly unlikely you must also enter a tolerance. The is amount of degrees to which the position can deviate in either direction. If you only care about one specific axis, specify a tolerance of 180° for the two other ones. Would currently apply? the device is in a certain position + A tolerance of 180 is allowed for 2 tolerance fields only, not all 3. Otherwise the trigger would ALWAYS apply. \ No newline at end of file From 8e5ad15c343ae120b0414e1c31ba76b264e060e8 Mon Sep 17 00:00:00 2001 From: jens Date: Sun, 5 Dec 2021 17:24:47 +0100 Subject: [PATCH 5/8] Rework --- .../ActivityManageTriggerDevicePosition.java | 17 +++++++---------- .../activity_manage_trigger_device_position.xml | 9 ++++++++- app/src/main/res/values/strings.xml | 4 +++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java index 42634bfa7..b0a6b6283 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java @@ -28,8 +28,6 @@ public class ActivityManageTriggerDevicePosition extends Activity boolean editMode = false; - boolean messageDisplayed = false; - float desiredAzimuth, desiredPitch, desiredRoll, desiredAzimuthTolerance, desiredPitchTolerance, desiredRollTolerance; public void updateFields(float azimuth, float pitch, float roll) @@ -38,7 +36,7 @@ public class ActivityManageTriggerDevicePosition extends Activity currentPitch.setText(Float.toString(pitch)); currentRoll.setText(Float.toString(roll)); - if(checkInputs()) + if(checkInputs(false)) { desiredAzimuth = Float.parseFloat(etDesiredAzimuth.getText().toString()); desiredAzimuthTolerance = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString()); @@ -107,9 +105,9 @@ public class ActivityManageTriggerDevicePosition extends Activity // etDesiredAzimuth.setFilters(new InputFilter[]{new InputFilterMinMax(-180, 180)}); // etDesiredPitch.setFilters(new InputFilter[]{new InputFilterMinMax(-180, 180)}); // etDesiredRoll.setFilters(new InputFilter[]{new InputFilterMinMax(-180, 180)}); - etDesiredAzimuthTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 359)}); - etDesiredPitchTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 359)}); - etDesiredRollTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 359)}); + etDesiredAzimuthTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 180)}); + etDesiredPitchTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 180)}); + etDesiredRollTolerance.setFilters(new InputFilter[]{new InputFilterMinMax(0, 180)}); if(getIntent().hasExtra(vectorFieldName)) { @@ -144,7 +142,7 @@ public class ActivityManageTriggerDevicePosition extends Activity @Override public void onClick(View v) { - if(!checkInputs()) + if(!checkInputs(true)) { Toast.makeText(ActivityManageTriggerDevicePosition.this, getResources().getString(R.string.enterValidNumbersIntoAllFields), Toast.LENGTH_LONG).show(); } @@ -167,7 +165,7 @@ public class ActivityManageTriggerDevicePosition extends Activity }); } - boolean checkInputs() + boolean checkInputs(boolean showMessages) { if( !StringUtils.isEmpty(etDesiredAzimuth.getText().toString()) && Miscellaneous.isNumeric(etDesiredAzimuth.getText().toString()) @@ -192,7 +190,7 @@ public class ActivityManageTriggerDevicePosition extends Activity return false; } - if(!messageDisplayed) + if(showMessages) { float dat = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString()); float dpt = Float.parseFloat(etDesiredPitchTolerance.getText().toString()); @@ -204,7 +202,6 @@ public class ActivityManageTriggerDevicePosition extends Activity */ if (Math.abs(dat) >= 180 && Math.abs(dpt) >= 180 && Math.abs(drt) >= 180) { - messageDisplayed = true; Miscellaneous.messageBox(getResources().getString(R.string.warning), getResources().getString(R.string.toleranceOf180OnlyAllowedIn2Fields), ActivityManageTriggerDevicePosition.this).show(); return false; } diff --git a/app/src/main/res/layout/activity_manage_trigger_device_position.xml b/app/src/main/res/layout/activity_manage_trigger_device_position.xml index 98a927b11..4d82753d6 100644 --- a/app/src/main/res/layout/activity_manage_trigger_device_position.xml +++ b/app/src/main/res/layout/activity_manage_trigger_device_position.xml @@ -97,13 +97,14 @@ android:layout_height="wrap_content" /> @@ -146,6 +147,8 @@ @@ -178,6 +181,8 @@ @@ -210,6 +215,8 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5c0a5d59c..925c4d3f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -714,7 +714,7 @@ This feature is confirmed to work up until Android 8.0. From some higher version upwards it ceases to work, but due to a lack of physical devices I cannot tell which one that is. On Android 11 it definitely ain\'t working anymore. If you have a version in between please let me know if it\'s working or not. Notice Device position (Gyroscope) - Tolerance + Tolerance\n(0-180) Azimuth: Pitch: Roll: @@ -723,4 +723,6 @@ Would currently apply? the device is in a certain position A tolerance of 180 is allowed for 2 tolerance fields only, not all 3. Otherwise the trigger would ALWAYS apply. + unknown + Position \ No newline at end of file From 128116025f70ec35652a419d8af105e6bd487646 Mon Sep 17 00:00:00 2001 From: jens Date: Tue, 7 Dec 2021 16:45:05 +0100 Subject: [PATCH 6/8] Rework --- .../java/com/jens/automation2/Trigger.java | 26 ++++++++++++------- app/src/main/res/values/strings.xml | 18 ++++++------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index d38a0ca5f..14c9523d9 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -297,6 +297,7 @@ public class Trigger ) ) { + Miscellaneous.logEvent("i", "DevicePosition", "Trigger doesn\'t apply. Azimuth outside of tolerance area.", 5); return false; } @@ -308,6 +309,7 @@ public class Trigger ) ) { + Miscellaneous.logEvent("i", "DevicePosition", "Trigger doesn\'t apply. Pitch outside of tolerance area.", 5); return false; } @@ -319,6 +321,7 @@ public class Trigger ) ) { + Miscellaneous.logEvent("i", "DevicePosition", "Trigger doesn\'t apply. Roll outside of tolerance area.", 5); return false; } @@ -453,19 +456,19 @@ public class Trigger } else { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong direction. Demanded: " + String.valueOf(this.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); + Miscellaneous.logEvent("i", "Rule", "A trigger of rule " + getParentRule().getName() + " doesn't apply. Wrong direction. Demanded: " + String.valueOf(this.getPhoneDirection()) + ", got: " + String.valueOf(PhoneStatusListener.getLastPhoneDirection()), 4); return false; } } else { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong call status. Demanded: " + String.valueOf(this.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); + Miscellaneous.logEvent("i", "Rule", "A trigger of rule " + getParentRule().getName() + " doesn't apply. Wrong call status. Demanded: " + String.valueOf(this.getTriggerParameter()) + ", got: " + String.valueOf(PhoneStatusListener.isInACall()), 4); return false; } } else { - Miscellaneous.logEvent("i", "Rule", "Rule doesn't apply. Wrong phone number. Demanded: " + this.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); + Miscellaneous.logEvent("i", "Rule", "A trigger of rule " + getParentRule().getName() + " doesn't apply. Wrong phone number. Demanded: " + this.getPhoneNumber() + ", got: " + PhoneStatusListener.getLastPhoneNumber(), 4); return false; } @@ -522,7 +525,7 @@ public class Trigger Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), "Wifi name specified, checking that.", 4); if(!WifiBroadcastReceiver.getLastWifiSsid().equals(this.getTriggerParameter2())) { - Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); + Miscellaneous.logEvent("i", String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleCheckOf), this.getParentRule().getName()), String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.ruleDoesntApplyNotTheCorrectSsid), getParentRule().getName(), this.getTriggerParameter2(), WifiBroadcastReceiver.getLastWifiSsid()), 3); return false; } else @@ -690,6 +693,7 @@ public class Trigger } } + Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " may apply currently, but has not NOT applied since the rule\'s last execution.", 5); return false; } @@ -1387,21 +1391,25 @@ public class Trigger } catch(NullPointerException e) { - device = Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice); - Miscellaneous.logEvent("w", "Trigger", Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice), 3); + device = Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice) + ": " + device; + Miscellaneous.logEvent("w", "Trigger", Miscellaneous.getAnyContext().getResources().getString(R.string.invalidDevice) + ": " + device, 3); } } - if(bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_CONNECTED) | bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) - if(this.triggerParameter) + if(bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_CONNECTED) || bluetoothEvent.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) + { + if (this.triggerParameter) returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothConnectionTo), device)); else returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothDisconnectFrom), device)); + } else if(bluetoothEvent.equals(BluetoothDevice.ACTION_FOUND)) - if(this.triggerParameter) + { + if (this.triggerParameter) returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothDeviceInRange), device)); else returnString.append(String.format(Miscellaneous.getAnyContext().getResources().getString(R.string.bluetoothDeviceOutOfRange), device)); + } // } break; case headsetPlugged: diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 925c4d3f1..689963f8e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -212,15 +212,15 @@ Wifi name Enter a wifi name. Leave empty for any wifi. Cancel - Rule doesn\'t apply. We are slower than - Rule doesn\'t apply. We are faster than - Rule doesn\'t apply. It\'s quieter than - Rule doesn\'t apply. It\'s louder than - Rule doesn\'t apply. Battery level is lower than - Rule doesn\'t apply. Battery level is higher than - Rule doesn\'t apply. Not the correct SSID (demanded: \"%1$s\", given: \"%2$s\"). - Rule doesn\'t apply. There is no tag label or not tag at all. - Rule doesn\'t apply. Wrong tag label. + Rule %1$s doesn\'t apply. We are slower than + Rule %1$s doesn\'t apply. We are faster than + Rule %1$s doesn\'t apply. It\'s quieter than + Rule %1$s doesn\'t apply. It\'s louder than + Rule %1$s doesn\'t apply. Battery level is lower than + Rule %1$s doesn\'t apply. Battery level is higher than + Rule %1$s doesn\'t apply. Not the correct SSID (demanded: \"%2$s\", given: \"%3$s\"). + Rule %1$s doesn\'t apply. There is no tag label or not tag at all. + Rule %1$s doesn\'t apply. Wrong tag label. Rule %1$s is deactivated, can\'t apply. starting stopping From b88801500f8ee117233735431d03d1a8a7c96956 Mon Sep 17 00:00:00 2001 From: Jens Date: Tue, 7 Dec 2021 23:10:37 +0100 Subject: [PATCH 7/8] Refactoring --- app/src/apkFlavor/java/com/jens/automation2/Rule.java | 5 +++++ .../receivers/ActivityDetectionReceiver.java | 2 +- .../java/com/jens/automation2/PointOfInterest.java | 4 ++-- app/src/main/java/com/jens/automation2/Trigger.java | 8 ++++++-- .../jens/automation2/location/LocationProvider.java | 2 +- .../automation2/location/WifiBroadcastReceiver.java | 2 +- .../jens/automation2/receivers/BatteryReceiver.java | 10 +++++----- .../jens/automation2/receivers/BluetoothReceiver.java | 2 +- .../automation2/receivers/ConnectivityReceiver.java | 4 ++-- .../jens/automation2/receivers/DateTimeListener.java | 2 +- .../automation2/receivers/DevicePositionListener.java | 6 +----- .../automation2/receivers/HeadphoneJackListener.java | 2 +- .../com/jens/automation2/receivers/NfcReceiver.java | 2 +- .../com/jens/automation2/receivers/NoiseListener.java | 2 +- .../automation2/receivers/NotificationListener.java | 2 +- .../automation2/receivers/PhoneStatusListener.java | 6 +++--- .../jens/automation2/receivers/ProcessListener.java | 2 +- 17 files changed, 34 insertions(+), 29 deletions(-) diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index 731df84c8..8253480f3 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -345,6 +345,11 @@ public class Rule implements Comparable return false; } + + public boolean getsGreenLight(Context context) + { + return isRuleActive() && applies(context) && (hasNotAppliedSinceLastExecution() || isActuallyToggable()); + } public boolean applies(Context context) { diff --git a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java index 8dd7755fa..91ac35011 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java +++ b/app/src/apkFlavor/java/com/jens/automation2/receivers/ActivityDetectionReceiver.java @@ -294,7 +294,7 @@ public class ActivityDetectionReceiver extends IntentService implements Automati ArrayList allRulesWithActivityDetection = Rule.findRuleCandidatesByActivityDetection(); for(int i=0; i for(int i=0; i Miscellaneous.logEvent("i", "POI", "POI " + this.getName() + " found in " + ruleCandidates.size() + " rule(s).", 2); for(int i=0; i getParentRule().getLastExecution().getTimeInMillis()) { + Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " has NOT applied since the parent rule\'s last activation.", 4); return true; } } - Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " may apply currently, but has not NOT applied since the rule\'s last execution.", 5); + Miscellaneous.logEvent("i", "Trigger", "Trigger " + this.toString() + " of rule " + getParentRule().getName() + " may apply currently, but has not NOT applied since the rule\'s last execution.", 4); return false; } diff --git a/app/src/main/java/com/jens/automation2/location/LocationProvider.java b/app/src/main/java/com/jens/automation2/location/LocationProvider.java index d8e44f317..c67643e3d 100644 --- a/app/src/main/java/com/jens/automation2/location/LocationProvider.java +++ b/app/src/main/java/com/jens/automation2/location/LocationProvider.java @@ -201,7 +201,7 @@ public class LocationProvider ArrayList ruleCandidates = Rule.findRuleCandidatesBySpeed(); for (Rule oneRule : ruleCandidates) { - if ((oneRule.applies(this.getParentService()) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) + if(oneRule.getsGreenLight(this.getParentService())) oneRule.activate(getParentService(), false); } } diff --git a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java index b1673b80b..c354e9a42 100644 --- a/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java +++ b/app/src/main/java/com/jens/automation2/location/WifiBroadcastReceiver.java @@ -147,7 +147,7 @@ public class WifiBroadcastReceiver extends BroadcastReceiver ArrayList ruleCandidates = Rule.findRuleCandidatesByWifiConnection(); for(Rule oneRule : ruleCandidates) { - if((oneRule.applies(automationServiceInstance) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) + if(oneRule.getsGreenLight(automationServiceInstance)) oneRule.activate(automationServiceInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java index 2fd8db3ea..0a457548c 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BatteryReceiver.java @@ -206,7 +206,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByCharging(true); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByBatteryLevel(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByCharging(false); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByUsbHost(true); for(Rule oneRule : ruleCandidates) { - if((oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) + if(oneRule.getsGreenLight(context)) oneRule.activate(automationServiceRef, false); } @@ -278,7 +278,7 @@ public class BatteryReceiver extends BroadcastReceiver implements AutomationList ArrayList ruleCandidates = Rule.findRuleCandidatesByUsbHost(false); for(Rule oneRule : ruleCandidates) { - if((oneRule.applies(context) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) + if(oneRule.getsGreenLight(context)) oneRule.activate(automationServiceRef, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java index 2fc23ce16..91c6dbff8 100644 --- a/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java +++ b/app/src/main/java/com/jens/automation2/receivers/BluetoothReceiver.java @@ -127,7 +127,7 @@ public class BluetoothReceiver extends BroadcastReceiver implements AutomationLi ArrayList ruleCandidates = Rule.findRuleCandidatesByBluetoothConnection(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByAirplaneMode(isAirplaneMode); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByRoaming(isRoaming); for(int i=0; i allRulesWithNowInTimeFrame = Rule.findRuleCandidatesByTime(passTime); for(int i=0; i ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.devicePosition); for (int i = 0; i < ruleCandidates.size(); i++) { - applies = ruleCandidates.get(i).applies(Miscellaneous.getAnyContext()); - flipped = ruleCandidates.get(i).hasNotAppliedSinceLastExecution(); - toggable = ruleCandidates.get(i).isActuallyToggable(); - - if((applies && flipped) || toggable) + if(ruleCandidates.get(i).getsGreenLight(Miscellaneous.getAnyContext())) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java index 748f083f5..83a8865af 100644 --- a/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/HeadphoneJackListener.java @@ -77,7 +77,7 @@ public class HeadphoneJackListener extends BroadcastReceiver implements Automati ArrayList ruleCandidates = Rule.findRuleCandidatesByHeadphoneJack(isHeadsetConnected()); for(int i=0; i allRulesWithNfcTags = Rule.findRuleCandidatesByNfc(); for(int i=0; i ruleCandidates = Rule.findRuleCandidatesByNoiseLevel(); for(Rule oneRule : ruleCandidates) { - if((oneRule.applies(automationService) && oneRule.hasNotAppliedSinceLastExecution()) || oneRule.isActuallyToggable()) + if(oneRule.getsGreenLight(automationService)) oneRule.activate(automationService, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java index efffeed61..28ef525b3 100644 --- a/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/NotificationListener.java @@ -92,7 +92,7 @@ public class NotificationListener extends NotificationListenerService ArrayList ruleCandidates = Rule.findRuleCandidates(Trigger.Trigger_Enum.notification); for (int i = 0; i < ruleCandidates.size(); i++) { - if ((ruleCandidates.get(i).applies(NotificationListener.this) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) + if(ruleCandidates.get(i).getsGreenLight(NotificationListener.this)) ruleCandidates.get(i).activate(AutomationService.getInstance(), false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java index 98e633c02..a0c9baa5c 100644 --- a/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/PhoneStatusListener.java @@ -114,7 +114,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if((ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) + if(ruleCandidates.get(i).getsGreenLight(asInstance)) ruleCandidates.get(i).activate(asInstance, false); } } @@ -146,7 +146,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if (asInstance != null) - if ((ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) + if (ruleCandidates.get(i).getsGreenLight(asInstance)) ruleCandidates.get(i).activate(asInstance, false); } } @@ -183,7 +183,7 @@ public class PhoneStatusListener implements AutomationListenerInterface { AutomationService asInstance = AutomationService.getInstance(); if(asInstance != null) - if((ruleCandidates.get(i).applies(asInstance) && ruleCandidates.get(i).hasNotAppliedSinceLastExecution()) || ruleCandidates.get(i).isActuallyToggable()) + if(ruleCandidates.get(i).getsGreenLight(asInstance)) ruleCandidates.get(i).activate(asInstance, false); } } diff --git a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java index a0eec0aaf..be3771447 100644 --- a/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java +++ b/app/src/main/java/com/jens/automation2/receivers/ProcessListener.java @@ -60,7 +60,7 @@ public class ProcessListener implements AutomationListenerInterface ArrayList ruleCandidates = Rule.findRuleCandidatesByProcess(); for(int i=0; i Date: Wed, 8 Dec 2021 17:22:18 +0100 Subject: [PATCH 8/8] Rework --- .idea/deploymentTargetDropDown.xml | 17 ------- .../java/com/jens/automation2/Rule.java | 2 +- .../java/com/jens/automation2/Rule.java | 5 ++ .../java/com/jens/automation2/Rule.java | 5 ++ .../java/com/jens/automation2/Actions.java | 47 ++++++++++++++----- .../jens/automation2/ActivityManageRule.java | 3 +- .../ActivityManageTriggerDevicePosition.java | 25 +++++++--- .../com/jens/automation2/PointOfInterest.java | 1 + .../java/com/jens/automation2/Trigger.java | 6 +++ app/src/main/res/values/strings.xml | 1 + 10 files changed, 74 insertions(+), 38 deletions(-) delete mode 100644 .idea/deploymentTargetDropDown.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index 9f3e9f1bb..000000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/apkFlavor/java/com/jens/automation2/Rule.java b/app/src/apkFlavor/java/com/jens/automation2/Rule.java index 8253480f3..23ed06f00 100644 --- a/app/src/apkFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/apkFlavor/java/com/jens/automation2/Rule.java @@ -348,7 +348,7 @@ public class Rule implements Comparable public boolean getsGreenLight(Context context) { - return isRuleActive() && applies(context) && (hasNotAppliedSinceLastExecution() || isActuallyToggable()); + return applies(context) && hasNotAppliedSinceLastExecution(); } public boolean applies(Context context) diff --git a/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java b/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java index 8ef83dee5..bb8229fee 100644 --- a/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/fdroidFlavor/java/com/jens/automation2/Rule.java @@ -341,6 +341,11 @@ public class Rule implements Comparable return false; } + + public boolean getsGreenLight(Context context) + { + return isRuleActive() && applies(context) && hasNotAppliedSinceLastExecution(); + } public boolean applies(Context context) { diff --git a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java index 63d07eb40..53a531173 100644 --- a/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java +++ b/app/src/googlePlayFlavor/java/com/jens/automation2/Rule.java @@ -345,6 +345,11 @@ public class Rule implements Comparable return false; } + + public boolean getsGreenLight(Context context) + { + return isRuleActive() && applies(context) && hasNotAppliedSinceLastExecution(); + } public boolean applies(Context context) { diff --git a/app/src/main/java/com/jens/automation2/Actions.java b/app/src/main/java/com/jens/automation2/Actions.java index 2437d7078..14373fa50 100644 --- a/app/src/main/java/com/jens/automation2/Actions.java +++ b/app/src/main/java/com/jens/automation2/Actions.java @@ -1094,23 +1094,48 @@ public class Actions @Override public void run() { - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - WakeLock wakeLock = pm.newWakeLock((WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Automation:Wakelock"); - wakeLock.acquire(); - try { - Thread.sleep(awakeTime); - } - catch (InterruptedException e) - { - Miscellaneous.logEvent("w", context.getResources().getString(R.string.wakeupDevice), "Error keeping device awake: " + Log.getStackTraceString(e), 4); - } + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + WakeLock wakeLock = pm.newWakeLock((WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "Automation:Wakelock"); + wakeLock.acquire(); - wakeLock.release(); + try + { + Thread.sleep(awakeTime); + } + catch (InterruptedException e) + { + Miscellaneous.logEvent("w", context.getResources().getString(R.string.wakeupDevice), "Error keeping device awake: " + Log.getStackTraceString(e), 4); + } + + wakeLock.release(); + } + catch(Exception e) + { + Miscellaneous.logEvent("e", "Wakeup device action", "Error while waking up device: " + Log.getStackTraceString(e), 1); + } } } + public void turnOnScreen() + { + // turn on screen + Log.v("ProximityActivity", "ON!"); + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + WakeLock wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag"); + wakeLock.acquire(); + } + + @TargetApi(21) //Suppress lint error for PROXIMITY_SCREEN_OFF_WAKE_LOCK + public void turnOffScreen(){ + // turn off screen + Log.v("ProximityActivity", "OFF!"); + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + WakeLock wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "tag"); + wakeLock.acquire(); + } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @SuppressLint("NewApi") public static boolean setAirplaneMode(boolean desiredState, boolean toggleActionIfPossible) diff --git a/app/src/main/java/com/jens/automation2/ActivityManageRule.java b/app/src/main/java/com/jens/automation2/ActivityManageRule.java index 30c0b94d4..d1e919044 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageRule.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageRule.java @@ -1375,8 +1375,7 @@ public class ActivityManageRule extends Activity { Trigger editedTrigger = new Trigger(); editedTrigger.setTriggerType(Trigger_Enum.devicePosition); -// newTrigger.setTriggerParameter(data.getBooleanExtra("wifiState", false)); - newTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageTriggerDevicePosition.vectorFieldName)); + editedTrigger.setTriggerParameter2(data.getStringExtra(ActivityManageTriggerDevicePosition.vectorFieldName)); ruleToEdit.getTriggerSet().set(editIndex, editedTrigger); this.refreshTriggerList(); } diff --git a/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java b/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java index b0a6b6283..13b1c3489 100644 --- a/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java +++ b/app/src/main/java/com/jens/automation2/ActivityManageTriggerDevicePosition.java @@ -6,6 +6,7 @@ import android.graphics.Color; import android.os.Bundle; import android.text.InputFilter; import android.text.Spanned; +import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; @@ -112,13 +113,21 @@ public class ActivityManageTriggerDevicePosition extends Activity if(getIntent().hasExtra(vectorFieldName)) { editMode = true; - String values[] = getIntent().getStringExtra(vectorFieldName).split(Trigger.triggerParameter2Split); - etDesiredAzimuth.setText(values[0]); - etDesiredAzimuthTolerance.setText(values[1]); - etDesiredPitch.setText(values[2]); - etDesiredPitchTolerance.setText(values[3]); - etDesiredRoll.setText(values[4]); - etDesiredRollTolerance.setText(values[5]); + try + { + String values[] = getIntent().getStringExtra(vectorFieldName).split(Trigger.triggerParameter2Split); + etDesiredAzimuth.setText(values[0]); + etDesiredAzimuthTolerance.setText(values[1]); + etDesiredPitch.setText(values[2]); + etDesiredPitchTolerance.setText(values[3]); + etDesiredRoll.setText(values[4]); + etDesiredRollTolerance.setText(values[5]); + } + catch(Exception e) + { + Toast.makeText(ActivityManageTriggerDevicePosition.this, getResources().getString(R.string.triggerWrong), Toast.LENGTH_SHORT).show(); + Miscellaneous.logEvent("e", "DevicePositionTrigger", "There\'s something wrong with a device position trigger. Content: " + getIntent().getStringExtra(vectorFieldName) + ", " + Log.getStackTraceString(e), 1); + } } bApplyPositionValues.setOnClickListener(new View.OnClickListener() @@ -206,6 +215,8 @@ public class ActivityManageTriggerDevicePosition extends Activity return false; } } + + return true; } return false; diff --git a/app/src/main/java/com/jens/automation2/PointOfInterest.java b/app/src/main/java/com/jens/automation2/PointOfInterest.java index ed641d4ea..bbe8b0a78 100644 --- a/app/src/main/java/com/jens/automation2/PointOfInterest.java +++ b/app/src/main/java/com/jens/automation2/PointOfInterest.java @@ -276,6 +276,7 @@ public class PointOfInterest implements Comparable ActivityMainScreen.updateMainScreen(); } } + public void deactivate(AutomationService parentService) { if(this.isActivated()) diff --git a/app/src/main/java/com/jens/automation2/Trigger.java b/app/src/main/java/com/jens/automation2/Trigger.java index c86b03a9d..8ca4fdae6 100644 --- a/app/src/main/java/com/jens/automation2/Trigger.java +++ b/app/src/main/java/com/jens/automation2/Trigger.java @@ -290,6 +290,8 @@ public class Trigger float currentRoll = DevicePositionListener.getInstance().getRoll(); if( + desiredAzimuthTolerance < 180 + && !( currentAzimuth <= desiredAzimuth + desiredAzimuthTolerance && @@ -302,6 +304,8 @@ public class Trigger } if( + desiredPitchTolerance < 180 + && !( currentPitch <= desiredPitch + desiredPitchTolerance && @@ -314,6 +318,8 @@ public class Trigger } if( + desiredRollTolerance < 180 + && !( currentRoll <= desiredRoll + desiredRollTolerance && diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 689963f8e..5258355f8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -725,4 +725,5 @@ A tolerance of 180 is allowed for 2 tolerance fields only, not all 3. Otherwise the trigger would ALWAYS apply. unknown Position + " There's something wrong with this trigger. It could not be loaded correctly." \ No newline at end of file