Skip to content

Commit

Permalink
repeated burst protection
Browse files Browse the repository at this point in the history
  • Loading branch information
lucky committed Aug 30, 2022
1 parent ecc243e commit bdeefdf
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 19 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ android {
applicationId "me.lucky.silence"
minSdk 29
targetSdk 32
versionCode 49
versionName "1.11.5"
versionCode 50
versionName "1.11.6"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/me/lucky/silence/Preferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Preferences(ctx: Context) {
private const val GROUPS = "groups"
private const val REPEATED_COUNT = "repeated_count"
private const val REPEATED_MINUTES = "repeated_minutes"
private const val REPEATED_BURST_TIMEOUT = "repeated_burst_timeout"
private const val MESSAGES = "messages"
private const val MESSAGES_TEXT_TTL = "messages_text_ttl"

Expand Down Expand Up @@ -71,6 +72,10 @@ class Preferences(ctx: Context) {
get() = prefs.getInt(REPEATED_MINUTES, DEFAULT_REPEATED_MINUTES)
set(value) = prefs.edit { putInt(REPEATED_MINUTES, value) }

var repeatedBurstTimeout: Int
get() = prefs.getInt(REPEATED_BURST_TIMEOUT, 0)
set(value) = prefs.edit { putInt(REPEATED_BURST_TIMEOUT, value) }

var isMessagesChecked: Boolean
get() = prefs.getBoolean(MESSAGES_CHECKED, false)
set(value) = prefs.edit { putBoolean(MESSAGES_CHECKED, value) }
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/me/lucky/silence/fragment/RepeatedFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ class RepeatedFragment : Fragment() {
binding.apply {
count.editText?.setText(prefs.repeatedCount.toString())
minutes.editText?.setText(prefs.repeatedMinutes.toString())
burstTimeout.editText?.setText(prefs.repeatedBurstTimeout.toString())
}
}

private fun setup() = binding.apply {
count.editText?.doAfterTextChanged {
try {
prefs.repeatedCount = it?.toString()?.toInt() ?: return@doAfterTextChanged
} catch (exc: NumberFormatException) {}
prefs.repeatedCount = it?.toString()?.toIntOrNull() ?: return@doAfterTextChanged
}
minutes.editText?.doAfterTextChanged {
try {
prefs.repeatedMinutes = it?.toString()?.toInt() ?: return@doAfterTextChanged
} catch (exc: NumberFormatException) {}
prefs.repeatedMinutes = it?.toString()?.toIntOrNull() ?: return@doAfterTextChanged
}
burstTimeout.editText?.doAfterTextChanged {
prefs.repeatedBurstTimeout = it?.toString()?.toIntOrNull() ?: return@doAfterTextChanged
}
}
}
35 changes: 25 additions & 10 deletions app/src/main/java/me/lucky/silence/screening/CallScreeningHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.net.Uri
import android.provider.CallLog
import android.provider.ContactsContract
import android.provider.Telephony
import android.telecom.Call
import android.telephony.TelephonyManager

import com.google.i18n.phonenumbers.PhoneNumberUtil
Expand All @@ -18,12 +19,12 @@ class CallScreeningHelper(private val ctx: Context) {
private val phoneNumberUtil = PhoneNumberUtil.getInstance()
private val db = AppDatabase.getInstance(ctx).allowNumberDao()

fun check(number: Phonenumber.PhoneNumber): Boolean {
fun check(number: Phonenumber.PhoneNumber, callDetails: Call.Details): Boolean {
return (
(prefs.isContactsChecked && checkContacts(number)) ||
(prefs.isContactedChecked && checkContacted(number)) ||
(prefs.isGroupsChecked && checkGroups(number)) ||
(prefs.isRepeatedChecked && checkRepeated(number)) ||
(prefs.isRepeatedChecked && checkRepeated(number, callDetails)) ||
(prefs.isMessagesChecked && checkMessages(number))
)
}
Expand Down Expand Up @@ -54,7 +55,7 @@ class CallScreeningHelper(private val ctx: Context) {
)
} catch (exc: SecurityException) {}
cursor?.apply {
if (moveToFirst()) { result = true }
if (moveToFirst()) result = true
close()
}
return result
Expand All @@ -76,7 +77,7 @@ class CallScreeningHelper(private val ctx: Context) {
)
} catch (exc: SecurityException) {}
cursor?.apply {
if (moveToFirst()) { result = true }
if (moveToFirst()) result = true
close()
}
return result
Expand Down Expand Up @@ -104,23 +105,37 @@ class CallScreeningHelper(private val ctx: Context) {
return result
}

private fun checkRepeated(number: Phonenumber.PhoneNumber): Boolean {
private fun checkRepeated(number: Phonenumber.PhoneNumber, callDetails: Call.Details): Boolean {
val cursor: Cursor?
try {
cursor = ctx.contentResolver.query(
makeContentUri(CallLog.Calls.CONTENT_FILTER_URI, number),
arrayOf(CallLog.Calls._ID),
arrayOf(CallLog.Calls._ID, CallLog.Calls.DATE),
"${CallLog.Calls.TYPE} = ? AND ${CallLog.Calls.DATE} > ?",
arrayOf(
CallLog.Calls.BLOCKED_TYPE.toString(),
(System.currentTimeMillis() - prefs.repeatedMinutes * 60 * 1000).toString(),
),
null,
CallLog.Calls.DEFAULT_SORT_ORDER,
)
} catch (exc: SecurityException) { return false }
var result = false
cursor?.apply {
if (count >= prefs.repeatedCount - 1) { result = true }
val i: Int
val burstTimeout = prefs.repeatedBurstTimeout * 1000L
if (burstTimeout == 0L) {
i = count
} else {
var j = 0
var tm = callDetails.creationTimeMillis
while (moveToNext()) {
val date = getLong(getColumnIndexOrThrow(CallLog.Calls.DATE))
if (tm - date >= burstTimeout) j++
tm = date
}
i = j
}
if (i >= prefs.repeatedCount - 1) result = true
close()
}
return result
Expand Down Expand Up @@ -157,7 +172,7 @@ class CallScreeningHelper(private val ctx: Context) {
)
} catch (exc: SecurityException) {}
cursor?.apply {
if (moveToFirst()) { result = true }
if (moveToFirst()) result = true
close()
}
return result
Expand Down Expand Up @@ -187,7 +202,7 @@ class CallScreeningHelper(private val ctx: Context) {
} catch (exc: SecurityException) { return false }
var result = false
cursor?.apply {
if (moveToFirst()) { result = true }
if (moveToFirst()) result = true
close()
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class CallScreeningService : CallScreeningService() {
respondNotAllow(callDetails)
return
}
if (callScreeningHelper.check(number)) respondAllow(callDetails)
if (callScreeningHelper.check(number, callDetails)) respondAllow(callDetails)
else respondNotAllow(callDetails)
}

Expand Down
21 changes: 21 additions & 0 deletions app/src/main/res/layout/fragment_repeated.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.RepeatedFragment">
Expand Down Expand Up @@ -64,6 +65,26 @@
android:text="@string/repeated_settings_description"
android:textAppearance="?attr/textAppearanceBodySmall" />

<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/burstTimeout"
android:hint="@string/repeated_burst_timeout_hint"
app:helperText="@string/repeated_burst_timeout_helper_text"
app:helperTextEnabled="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />

</com.google.android.material.textfield.TextInputLayout>

</LinearLayout>
</ScrollView>
</FrameLayout>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
<string name="repeated_count">Count</string>
<string name="repeated_minutes">Minutes</string>
<string name="repeated_settings_description">Count has to be lower than minutes. Because Android caches the result, calls have to be out of the cache interval.</string>
<string name="repeated_burst_timeout_hint">Timeout</string>
<string name="repeated_burst_timeout_helper_text">Minimal timeout in seconds between repeated calls.</string>
<string name="messages_main">Messages</string>
<string name="messages_description">Allow calls from numbers found in messages.</string>
<string name="messages_inbox">Inbox</string>
Expand Down
10 changes: 10 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/50.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add repeated burst protection
update Arabic, Turkish, French, Japanese, English, Norwegian Bokmål, Italian translations

Thanks to:
DJEBBARI.ABDELHAMID (@dxing96)
Oğuz Ersen (@ersen0)
Nathanaël Gagnepain (@Ilithy)
Guillaume BOEHM (@guillaumeboehm)
Allan Nordhøy (@comradekingu)
Giovanni Donisi (@gdonisi + @giovannidonisi)

0 comments on commit bdeefdf

Please sign in to comment.