Ignore repeating events

This commit is contained in:
xynngh 2020-09-10 14:14:15 +04:00
parent 29f36b883a
commit 24f4dd5881
6 changed files with 80 additions and 22 deletions

View File

@ -26,7 +26,7 @@ public class CallMonitoringService extends Service {
private static final Logger LOG = LoggerFactory.getLogger(CallMonitoringService.class);
private final MyPhoneStateListener phoneStateListener = new MyPhoneStateListener(this);
private final MyPhoneStateListener phoneStateListener = new MyPhoneStateListener();
private final CallReceiver callReceiver = new CallReceiver(true);
private boolean monitoringStarted;
@ -122,12 +122,6 @@ public class CallMonitoringService extends Service {
private static final Logger LOG = LoggerFactory.getLogger(MyPhoneStateListener.class);
private final Context context;
public MyPhoneStateListener(Context context) {
this.context = context;
}
@Override
public void onCallStateChanged(int state, String phoneNumber) {
LOG.info("onCallStateChanged({}, \"{}\")", state, phoneNumber);
@ -143,13 +137,13 @@ public class CallMonitoringService extends Service {
PhoneStateHandler phoneStateHandler = YacbHolder.getPhoneStateHandler();
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
phoneStateHandler.onIdle(context, phoneNumber);
phoneStateHandler.onIdle(phoneNumber);
break;
case TelephonyManager.CALL_STATE_RINGING:
phoneStateHandler.onRinging(context, phoneNumber);
phoneStateHandler.onRinging(phoneNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
phoneStateHandler.onOffHook(context, phoneNumber);
phoneStateHandler.onOffHook(phoneNumber);
break;
}
}

View File

@ -58,11 +58,11 @@ public class CallReceiver extends BroadcastReceiver {
PhoneStateHandler phoneStateHandler = YacbHolder.getPhoneStateHandler();
if (TelephonyManager.EXTRA_STATE_RINGING.equals(telephonyExtraState)) {
phoneStateHandler.onRinging(context, incomingNumber);
phoneStateHandler.onRinging(incomingNumber);
} else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(telephonyExtraState)) {
phoneStateHandler.onOffHook(context, incomingNumber);
phoneStateHandler.onOffHook(incomingNumber);
} else if (TelephonyManager.EXTRA_STATE_IDLE.equals(telephonyExtraState)) {
phoneStateHandler.onIdle(context, incomingNumber);
phoneStateHandler.onIdle(incomingNumber);
}
}

View File

@ -1,10 +1,16 @@
package dummydomain.yetanothercallblocker;
import android.content.Context;
import android.text.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.TimeUnit;
import dummydomain.yetanothercallblocker.data.NumberInfo;
import dummydomain.yetanothercallblocker.data.NumberInfoService;
import dummydomain.yetanothercallblocker.event.CallEndedEvent;
@ -17,30 +23,50 @@ public class PhoneStateHandler {
private static final Logger LOG = LoggerFactory.getLogger(PhoneStateHandler.class);
private final Context context;
private final Settings settings;
private final NumberInfoService numberInfoService;
private final NotificationService notificationService;
private boolean isOffHook;
public PhoneStateHandler(Settings settings, NumberInfoService numberInfoService,
private List<CallEvent> lastEvents = new ArrayList<>();
private long lastEventTimestamp;
public PhoneStateHandler(Context context, Settings settings,
NumberInfoService numberInfoService,
NotificationService notificationService) {
this.context = context;
this.settings = settings;
this.numberInfoService = numberInfoService;
this.notificationService = notificationService;
}
public void onRinging(Context context, String phoneNumber) {
public void onRinging(String phoneNumber) {
LOG.debug("onRinging({})", phoneNumber);
boolean ignore = false;
if (phoneNumber == null) {
if (!PermissionHelper.hasNumberInfoPermissions(context)) {
LOG.warn("No info permissions");
LOG.warn("onRinging() no info permissions");
return;
}
return; // TODO: check
// TODO: check
LOG.debug("onRinging() ignoring null");
ignore = true;
}
if (!ignore && !shouldProcess(phoneNumber)) {
LOG.debug("onRinging() ignoring repeated event");
ignore = true;
}
recordEvent(phoneNumber);
if (ignore) return;
boolean blockingEnabled = settings.getCallBlockingEnabled();
boolean showNotifications = settings.getIncomingCallNotifications();
@ -53,7 +79,7 @@ public class PhoneStateHandler {
boolean blocked = false;
if (blockingEnabled && !isOffHook && numberInfoService.shouldBlock(numberInfo)) {
blocked = PhoneUtils.rejectCall(context);
blocked = PhoneUtils.endCall(context);
if (blocked) {
notificationService.notifyCallBlocked(numberInfo);
@ -69,7 +95,7 @@ public class PhoneStateHandler {
}
}
public void onOffHook(Context context, String phoneNumber) {
public void onOffHook(String phoneNumber) {
LOG.debug("onOffHook({})", phoneNumber);
isOffHook = true;
@ -77,7 +103,7 @@ public class PhoneStateHandler {
postEvent(new CallOngoingEvent());
}
public void onIdle(Context context, String phoneNumber) {
public void onIdle(String phoneNumber) {
LOG.debug("onIdle({})", phoneNumber);
isOffHook = false;
@ -87,4 +113,41 @@ public class PhoneStateHandler {
postEvent(new CallEndedEvent());
}
private boolean shouldProcess(String phoneNumber) {
// using 1 second ago as the cutoff point - consider everything older as unrelated events
long cutoff = System.nanoTime() - TimeUnit.SECONDS.toNanos(1);
if (lastEventTimestamp - cutoff < 0) { // no events in the last second
lastEvents.clear();
return true;
}
for (ListIterator<CallEvent> it = lastEvents.listIterator(); it.hasNext(); ) {
CallEvent event = it.next();
if (event.timestamp - cutoff < 0) { // event is older than the cutoff point
it.remove();
} else if (TextUtils.equals(event.number, phoneNumber)) {
return false; // don't process same event
}
}
return true;
}
private void recordEvent(String phoneNumber) {
long currentTimestamp = System.nanoTime();
lastEvents.add(new CallEvent(phoneNumber, currentTimestamp));
lastEventTimestamp = currentTimestamp;
}
private static class CallEvent {
final String number;
final long timestamp;
public CallEvent(String number, long timestamp) {
this.number = number;
this.timestamp = timestamp;
}
}
}

View File

@ -153,7 +153,7 @@ public class Config {
YacbHolder.setNotificationService(notificationService);
YacbHolder.setPhoneStateHandler(
new PhoneStateHandler(settings, numberInfoService, notificationService));
new PhoneStateHandler(context, settings, numberInfoService, notificationService));
}
}

View File

@ -29,6 +29,7 @@ public class YacbHolder {
@SuppressLint("StaticFieldLeak")
private static NotificationService notificationService;
@SuppressLint("StaticFieldLeak")
private static PhoneStateHandler phoneStateHandler;
static void setWebService(WebService webService) {

View File

@ -22,7 +22,7 @@ public class PhoneUtils {
private static final Logger LOG = LoggerFactory.getLogger(PhoneUtils.class);
public static boolean rejectCall(@NonNull Context context) {
public static boolean endCall(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
TelecomManager telecomManager = requireNonNull(