From a135e7efa2822ced8e73548189c3d389286b4a4c Mon Sep 17 00:00:00 2001 From: alex-signal Date: Wed, 16 Oct 2019 13:26:26 -0300 Subject: [PATCH] Check DND settings before show activity or play ring or vibrate. --- .../securesms/database/MmsSmsDatabase.java | 5 +- .../securesms/database/SmsDatabase.java | 14 +++ .../securesms/database/ThreadDatabase.java | 4 + .../notifications/DoNotDisturbUtil.java | 92 +++++++++++++++++++ .../securesms/service/WebRtcCallService.java | 10 +- 5 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/notifications/DoNotDisturbUtil.java diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index 37de59cef..e2f356ec6 100644 --- a/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -29,7 +29,6 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.util.Util; import java.util.HashSet; import java.util.Set; @@ -204,6 +203,10 @@ public class MmsSmsDatabase extends Database { return -1; } + boolean hasReceivedAnyCallsSince(long threadId, long timestamp) { + return DatabaseFactory.getSmsDatabase(context).hasReceivedAnyCallsSince(threadId, timestamp); + } + /** * Retrieves the position of the message with the provided timestamp in the query results you'd * get from calling {@link #getConversation(long)}. diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java index 0f63d8b44..3005ff010 100644 --- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -487,6 +487,20 @@ public class SmsDatabase extends MessagingDatabase { } } + boolean hasReceivedAnyCallsSince(long threadId, long timestamp) { + SQLiteDatabase db = databaseHelper.getReadableDatabase(); + String[] projection = new String[]{SmsDatabase.TYPE}; + String selection = THREAD_ID + " = ? AND " + DATE_RECEIVED + " > ? AND (" + TYPE + " = ? OR " + TYPE + " = ?)"; + String[] selectionArgs = new String[]{String.valueOf(threadId), + String.valueOf(timestamp), + String.valueOf(Types.INCOMING_CALL_TYPE), + String.valueOf(Types.MISSED_CALL_TYPE)}; + + try (Cursor cursor = db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, null)) { + return cursor != null && cursor.moveToFirst(); + } + } + public @NonNull Pair insertReceivedCall(@NonNull RecipientId address) { return insertCallLog(address, Types.INCOMING_CALL_TYPE, false); } diff --git a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java index 5b245f9a1..0b948e316 100644 --- a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -285,6 +285,10 @@ public class ThreadDatabase extends Database { }}; } + public boolean hasCalledSince(@NonNull Recipient recipient, long timestamp) { + return DatabaseFactory.getMmsSmsDatabase(context).hasReceivedAnyCallsSince(getThreadIdFor(recipient), timestamp); + } + public List setRead(long threadId, boolean lastSeen) { ContentValues contentValues = new ContentValues(1); contentValues.put(READ, 1); diff --git a/src/org/thoughtcrime/securesms/notifications/DoNotDisturbUtil.java b/src/org/thoughtcrime/securesms/notifications/DoNotDisturbUtil.java new file mode 100644 index 000000000..50e96ca4b --- /dev/null +++ b/src/org/thoughtcrime/securesms/notifications/DoNotDisturbUtil.java @@ -0,0 +1,92 @@ +package org.thoughtcrime.securesms.notifications; + +import android.app.NotificationManager; +import android.content.Context; +import android.database.Cursor; +import android.os.Build; +import android.provider.ContactsContract; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.annotation.WorkerThread; + +import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.ServiceUtil; + +import java.util.concurrent.TimeUnit; + +public final class DoNotDisturbUtil { + + private static final String TAG = Log.tag(DoNotDisturbUtil.class); + + private DoNotDisturbUtil() { + } + + @WorkerThread + public static boolean shouldDisturbUserWithCall(@NonNull Context context, @NonNull Recipient recipient) { + if (Build.VERSION.SDK_INT <= 23) return true; + + NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); + + switch (notificationManager.getCurrentInterruptionFilter()) { + case NotificationManager.INTERRUPTION_FILTER_PRIORITY: + return handlePriority(context, notificationManager, recipient); + case NotificationManager.INTERRUPTION_FILTER_NONE: + case NotificationManager.INTERRUPTION_FILTER_ALARMS: + return false; + default: + return true; + } + } + + @RequiresApi(23) + private static boolean handlePriority(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Recipient recipient) { + final NotificationManager.Policy policy = notificationManager.getNotificationPolicy(); + final boolean areCallsPrioritized = (policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) != 0; + final boolean isRepeatCallerEnabled = (policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) != 0; + + if (!areCallsPrioritized && !isRepeatCallerEnabled) { + return false; + } + + if (areCallsPrioritized && !isRepeatCallerEnabled) { + return isContactPriority(context, recipient, policy.priorityCallSenders); + } + + if (!areCallsPrioritized) { + return isRepeatCaller(context, recipient); + } + + return isContactPriority(context, recipient, policy.priorityCallSenders) || isRepeatCaller(context, recipient); + } + + private static boolean isContactPriority(@NonNull Context context, @NonNull Recipient recipient, int priority) { + switch (priority) { + case NotificationManager.Policy.PRIORITY_SENDERS_ANY: + return true; + case NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS: + return recipient.resolve().isSystemContact(); + case NotificationManager.Policy.PRIORITY_SENDERS_STARRED: + return isContactStarred(context, recipient); + } + + Log.w(TAG, "Unknown priority " + priority); + return true; + } + + private static boolean isContactStarred(@NonNull Context context, @NonNull Recipient recipient) { + if (!recipient.resolve().isSystemContact()) return false; + + try (Cursor cursor = context.getContentResolver().query(recipient.resolve().getContactUri(), new String[]{ContactsContract.Contacts.STARRED}, null, null, null)) { + if (cursor == null || !cursor.moveToFirst()) return false; + return cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.STARRED)) == 1; + } + } + + private static boolean isRepeatCaller(@NonNull Context context, @NonNull Recipient recipient) { + return DatabaseFactory.getThreadDatabase(context).hasCalledSince(recipient, System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(15)); + } + +} diff --git a/src/org/thoughtcrime/securesms/service/WebRtcCallService.java b/src/org/thoughtcrime/securesms/service/WebRtcCallService.java index 8e312d4e0..2ca3d37d9 100644 --- a/src/org/thoughtcrime/securesms/service/WebRtcCallService.java +++ b/src/org/thoughtcrime/securesms/service/WebRtcCallService.java @@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.events.WebRtcViewModel; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.notifications.DoNotDisturbUtil; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.recipients.Recipient; @@ -499,10 +500,15 @@ public class WebRtcCallService extends Service implements CallConnection.Observe this.lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE); sendMessage(WebRtcViewModel.State.CALL_INCOMING, recipient, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled); - startCallCardActivityIfPossible(); + + boolean shouldDisturbUserWithCall = DoNotDisturbUtil.shouldDisturbUserWithCall(getApplicationContext(), recipient); + if (shouldDisturbUserWithCall) { + startCallCardActivityIfPossible(); + } + audioManager.initializeAudioForCall(); - if (TextSecurePreferences.isCallNotificationsEnabled(this)) { + if (shouldDisturbUserWithCall && TextSecurePreferences.isCallNotificationsEnabled(this)) { Uri ringtone = recipient.resolve().getCallRingtone(); VibrateState vibrateState = recipient.resolve().getCallVibrate();