mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-27 21:24:42 +00:00
Use alarm clock for scheduling message sends.
This commit is contained in:
committed by
Greyson Parrelli
parent
56b35f3767
commit
3a0dbe6e67
@@ -4648,16 +4648,20 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Long getOldestScheduledSendTimestamp() {
|
||||
public @Nullable MessageRecord getOldestScheduledSendTimestamp() {
|
||||
String[] columns = new String[] { SCHEDULED_DATE };
|
||||
String selection = STORY_TYPE + " = ? AND " + PARENT_STORY_ID + " <= ? AND " + SCHEDULED_DATE + " != ?";
|
||||
String[] args = SqlUtil.buildArgs(0, 0, -1);
|
||||
String order = SCHEDULED_DATE + " ASC, " + ID + " ASC";
|
||||
String limit = "1";
|
||||
|
||||
try (Cursor cursor = getReadableDatabase().query(TABLE_NAME, columns, selection, args, null, null, order, limit)) {
|
||||
return cursor != null && cursor.moveToNext() ? cursor.getLong(0) : null;
|
||||
try (MmsReader reader = mmsReaderFor(getReadableDatabase().query(TABLE_NAME, MMS_PROJECTION, selection, args, null, null, order, limit))) {
|
||||
if (reader.getNext() != null) {
|
||||
return reader.getCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Cursor getMessagesForNotificationState(Collection<DefaultMessageNotifier.StickyThread> stickyThreads) {
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ViewOnceMessageManager extends TimedEventManager<ViewOnceExpiration
|
||||
|
||||
@AnyThread
|
||||
@Override
|
||||
protected void scheduleAlarm(@NonNull Application application, long delay) {
|
||||
protected void scheduleAlarm(@NonNull Application application, ViewOnceExpirationInfo event, long delay) {
|
||||
setAlarm(application, delay, ViewOnceAlarm.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class ExpiringStoriesManager(
|
||||
override fun getDelayForEvent(event: Event): Long = event.delay
|
||||
|
||||
@WorkerThread
|
||||
override fun scheduleAlarm(application: Application, delay: Long) {
|
||||
override fun scheduleAlarm(application: Application, event: Event, delay: Long) {
|
||||
setAlarm(application, delay, ExpireStoriesAlarm::class.java)
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public final class PendingRetryReceiptManager extends TimedEventManager<PendingR
|
||||
|
||||
@AnyThread
|
||||
@Override
|
||||
protected void scheduleAlarm(@NonNull Application application, long delay) {
|
||||
protected void scheduleAlarm(@NonNull Application application, PendingRetryReceiptModel event, long delay) {
|
||||
setAlarm(application, delay, PendingRetryReceiptAlarm.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package org.thoughtcrime.securesms.service
|
||||
|
||||
import android.app.Application
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.signal.core.util.PendingIntentFlags
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.IndividualSendJob
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupSendJob
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
@@ -32,12 +38,12 @@ class ScheduledMessageManager(
|
||||
@Suppress("UsePropertyAccessSyntax")
|
||||
@WorkerThread
|
||||
override fun getNextClosestEvent(): Event? {
|
||||
val oldestTimestamp = messagesTable.getOldestScheduledSendTimestamp() ?: return null
|
||||
val oldestMessage = messagesTable.getOldestScheduledSendTimestamp() as? MediaMmsMessageRecord ?: return null
|
||||
|
||||
val delay = (oldestTimestamp - System.currentTimeMillis()).coerceAtLeast(0)
|
||||
val delay = (oldestMessage.scheduledDate - System.currentTimeMillis()).coerceAtLeast(0)
|
||||
Log.i(TAG, "The next scheduled message needs to be sent in $delay ms.")
|
||||
|
||||
return Event(delay)
|
||||
return Event(delay, oldestMessage.recipient.id, oldestMessage.threadId)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@@ -60,11 +66,20 @@ class ScheduledMessageManager(
|
||||
override fun getDelayForEvent(event: Event): Long = event.delay
|
||||
|
||||
@WorkerThread
|
||||
override fun scheduleAlarm(application: Application, delay: Long) {
|
||||
trySetExactAlarm(application, System.currentTimeMillis() + delay, ScheduledMessagesAlarm::class.java)
|
||||
override fun scheduleAlarm(application: Application, event: Event, delay: Long) {
|
||||
val conversationIntent = ConversationIntents.createBuilder(application, event.recipientId, event.threadId).build()
|
||||
|
||||
ServiceUtil.getAlarmManager(application)
|
||||
|
||||
trySetExactAlarm(
|
||||
application,
|
||||
System.currentTimeMillis() + delay,
|
||||
ScheduledMessagesAlarm::class.java,
|
||||
PendingIntent.getActivity(application, 0, conversationIntent, PendingIntentFlags.mutable())
|
||||
)
|
||||
}
|
||||
|
||||
data class Event(val delay: Long)
|
||||
data class Event(val delay: Long, val recipientId: RecipientId, val threadId: Long)
|
||||
|
||||
class ScheduledMessagesAlarm : BroadcastReceiver() {
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.service;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Application;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
@@ -54,7 +55,7 @@ public abstract class TimedEventManager<E> {
|
||||
scheduleIfNecessary();
|
||||
}, delay);
|
||||
|
||||
scheduleAlarm(application, delay);
|
||||
scheduleAlarm(application, event, delay);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -82,12 +83,12 @@ public abstract class TimedEventManager<E> {
|
||||
* use {@link #setAlarm(Context, long, Class)} as a helper method.
|
||||
*/
|
||||
@AnyThread
|
||||
protected abstract void scheduleAlarm(@NonNull Application application, long delay);
|
||||
protected abstract void scheduleAlarm(@NonNull Application application, E event, long delay);
|
||||
|
||||
/**
|
||||
* Helper method to set an alarm.
|
||||
*/
|
||||
protected static void setAlarm(@NonNull Context context, long delay, @NonNull Class alarmClass) {
|
||||
protected static void setAlarm(@NonNull Context context, long delay, @NonNull Class<? extends BroadcastReceiver> alarmClass) {
|
||||
Intent intent = new Intent(context, alarmClass);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.mutable());
|
||||
AlarmManager alarmManager = ServiceUtil.getAlarmManager(context);
|
||||
@@ -96,7 +97,7 @@ public abstract class TimedEventManager<E> {
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
|
||||
}
|
||||
|
||||
protected static void trySetExactAlarm(@NonNull Context context, long timestamp, @NonNull Class alarmClass) {
|
||||
protected static void trySetExactAlarm(@NonNull Context context, long timestamp, @NonNull Class<? extends BroadcastReceiver> alarmClass, @NonNull PendingIntent showIntent) {
|
||||
Intent intent = new Intent(context, alarmClass);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.mutable());
|
||||
AlarmManager alarmManager = ServiceUtil.getAlarmManager(context);
|
||||
@@ -106,11 +107,7 @@ public abstract class TimedEventManager<E> {
|
||||
boolean hasManagerPermission = Build.VERSION.SDK_INT < 31 || alarmManager.canScheduleExactAlarms();
|
||||
if (hasManagerPermission) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timestamp, pendingIntent);
|
||||
} else {
|
||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP, timestamp, pendingIntent);
|
||||
}
|
||||
alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(timestamp, showIntent), pendingIntent);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, e);
|
||||
|
||||
@@ -75,7 +75,7 @@ public class TrimThreadsByDateManager extends TimedEventManager<TrimThreadsByDat
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduleAlarm(@NonNull Application application, long delay) {
|
||||
protected void scheduleAlarm(@NonNull Application application, TrimEvent event, long delay) {
|
||||
setAlarm(application, delay, TrimThreadsByDateAlarm.class);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user