pull/1706/head
alansley 5 months ago
parent af602df969
commit c4644e52bd

@ -169,7 +169,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
@Inject LokiAPIDatabase apiDB; @Inject LokiAPIDatabase apiDB;
@Inject EmojiSearchDatabase emojiSearchDb; @Inject EmojiSearchDatabase emojiSearchDb;
private volatile boolean isAppVisible; public static volatile boolean isAppVisible;
@Override @Override
public Object getSystemService(String name) { public Object getSystemService(String name) {

@ -32,6 +32,7 @@ import org.session.libsession.messaging.utilities.UpdateMessageData;
import org.session.libsession.utilities.IdentityKeyMismatch; import org.session.libsession.utilities.IdentityKeyMismatch;
import org.session.libsession.utilities.NetworkFailure; import org.session.libsession.utilities.NetworkFailure;
import org.session.libsession.utilities.recipients.Recipient; import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import java.util.List; import java.util.List;
@ -145,8 +146,11 @@ public abstract class MessageRecord extends DisplayRecord {
} else if (isOutgoingCall()) { } else if (isOutgoingCall()) {
callType = CallMessageType.CALL_OUTGOING; callType = CallMessageType.CALL_OUTGOING;
} else if (isMissedCall()) { } else if (isMissedCall()) {
Log.w("ACL", "We think CALL_MISSSED");
callType = CallMessageType.CALL_MISSED; callType = CallMessageType.CALL_MISSED;
} else { } else {
Log.w("ACL", "We think CALL_FIRST_MISSSED");
callType = CallMessageType.CALL_FIRST_MISSED; callType = CallMessageType.CALL_FIRST_MISSED;
} }
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildCallMessage(context, callType, getIndividualRecipient().getAddress().serialize())); return new SpannableString(UpdateMessageBuilder.INSTANCE.buildCallMessage(context, callType, getIndividualRecipient().getAddress().serialize()));

@ -105,7 +105,7 @@ public class ThreadRecord extends DisplayRecord {
@Override @Override
public CharSequence getDisplayBody(@NonNull Context context) { public CharSequence getDisplayBody(@NonNull Context context) {
// no need to display anything if there are no messages // no need to display anything if there are no messages
if(lastMessage == null){ if (lastMessage == null){
return ""; return "";
} }
else if (isGroupUpdateMessage()) { else if (isGroupUpdateMessage()) {

@ -45,6 +45,7 @@ import org.session.libsession.messaging.utilities.SodiumUtilities.blindedKeyPair
import org.session.libsession.utilities.Address.Companion.fromSerialized import org.session.libsession.utilities.Address.Companion.fromSerialized
import org.session.libsession.utilities.ServiceUtil import org.session.libsession.utilities.ServiceUtil
import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY
import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY
import org.session.libsession.utilities.TextSecurePreferences.Companion.getLocalNumber import org.session.libsession.utilities.TextSecurePreferences.Companion.getLocalNumber
import org.session.libsession.utilities.TextSecurePreferences.Companion.getNotificationPrivacy import org.session.libsession.utilities.TextSecurePreferences.Companion.getNotificationPrivacy
import org.session.libsession.utilities.TextSecurePreferences.Companion.getRepeatAlertsCount import org.session.libsession.utilities.TextSecurePreferences.Companion.getRepeatAlertsCount
@ -280,12 +281,21 @@ class DefaultMessageNotifier : MessageNotifier {
builder.putStringExtra(LATEST_MESSAGE_ID_TAG, messageIdTag) builder.putStringExtra(LATEST_MESSAGE_ID_TAG, messageIdTag)
val text = notifications[0].text val notificationText = notifications[0].text
// TODO: We get missed call notifications whenever we get a call - I have no idea why, and it would be better to strip them out
// TODO: at the source - but I'll stop them here if we recognise the notification text and the home screen is visible
// For some reason, even when we're starting a call we get a missed call notification - so we'll bail before that happens.
// TODO: Probably better to fix this at the source so that this never gets called rather then here - do this.
val missedCallString = Phrase.from(context, R.string.callsMissedCallFrom).put(NAME_KEY, notifications[0].recipient.name).format()
if (ApplicationContext.isAppVisible && notificationText == missedCallString) { return }
builder.setThread(notifications[0].recipient) builder.setThread(notifications[0].recipient)
builder.setMessageCount(notificationState.messageCount) builder.setMessageCount(notificationState.messageCount)
val builderCS = text ?: "" val builderCS = notificationText ?: ""
val ss = highlightMentions( val ss = highlightMentions(
builderCS, builderCS,
false, false,
@ -331,7 +341,6 @@ class DefaultMessageNotifier : MessageNotifier {
} }
val iterator: ListIterator<NotificationItem> = notifications.listIterator(notifications.size) val iterator: ListIterator<NotificationItem> = notifications.listIterator(notifications.size)
while (iterator.hasPrevious()) { while (iterator.hasPrevious()) {
val item = iterator.previous() val item = iterator.previous()
builder.addMessageBody(item.recipient, item.individualRecipient, item.text) builder.addMessageBody(item.recipient, item.individualRecipient, item.text)
@ -363,6 +372,8 @@ class DefaultMessageNotifier : MessageNotifier {
// for ActivityCompat#requestPermissions for more details. // for ActivityCompat#requestPermissions for more details.
return return
} }
NotificationManagerCompat.from(context).notify(notificationId, notification) NotificationManagerCompat.from(context).notify(notificationId, notification)
Log.i(TAG, "Posted notification. $notification") Log.i(TAG, "Posted notification. $notification")
} }

@ -235,6 +235,7 @@ public class KeyCachingService extends Service {
private void foregroundService() { private void foregroundService() {
if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) { if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) {
Log.w("ACL", "Stopping foreground service in KeyCachingService");
stopForeground(true); stopForeground(true);
return; return;
} }
@ -248,8 +249,6 @@ public class KeyCachingService extends Service {
.put(APP_NAME_KEY, c.getString(R.string.app_name)) .put(APP_NAME_KEY, c.getString(R.string.app_name))
.format().toString(); .format().toString();
builder.setContentTitle(unlockedTxt); builder.setContentTitle(unlockedTxt);
builder.setContentText(getString(R.string.lockAppUnlock));
builder.setSmallIcon(R.drawable.icon_cached); builder.setSmallIcon(R.drawable.icon_cached);
builder.setWhen(0); builder.setWhen(0);
builder.setPriority(Notification.PRIORITY_MIN); builder.setPriority(Notification.PRIORITY_MIN);

@ -334,7 +334,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
networkChangedReceiver = NetworkChangeReceiver(::networkChange) networkChangedReceiver = NetworkChangeReceiver(::networkChange)
networkChangedReceiver!!.register(this) networkChangedReceiver!!.register(this)
Log.w("ACL", "Lesssgo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") //Log.w("ACL", "Lesssgo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
//if (appIsBackground(this)) { //if (appIsBackground(this)) {
// ServiceCompat.startForeground(this, // ServiceCompat.startForeground(this,
// CallNotificationBuilder.WEBRTC_NOTIFICATION, // CallNotificationBuilder.WEBRTC_NOTIFICATION,
@ -342,18 +342,10 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
// if (Build.VERSION.SDK_INT >= 30) ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL else 0 // if (Build.VERSION.SDK_INT >= 30) ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL else 0
// ) // )
// Get the KeyguardManager and PowerManager
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
// Check if the phone is locked
val isPhoneLocked = keyguardManager.isKeyguardLocked
// Check if the screen is awake
val isScreenAwake = powerManager.isInteractive
// If the screen is off or phone is locked, wake it up // If the screen is off or phone is locked, wake it up
if (!isScreenAwake || isPhoneLocked) { wakeUpDevice() } //if (!isScreenAwake || isPhoneLocked) { wakeUpDevice() }
// ServiceCompat.startForeground( // ServiceCompat.startForeground(
@ -365,23 +357,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
// ) // )
} }
private fun wakeUpDevice() {
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
val wakeLock = powerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK or
PowerManager.ACQUIRE_CAUSES_WAKEUP or
PowerManager.ON_AFTER_RELEASE,
"${NonTranslatableStringConstants.APP_NAME}:WakeLock"
)
// Acquire the wake lock to wake up the device
wakeLock.acquire(3000) // Wake up for 3 seconds
// Dismiss the keyguard
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val keyguardLock = keyguardManager.newKeyguardLock("MyApp:KeyguardLock")
keyguardLock.disableKeyguard()
}
private fun registerUncaughtExceptionHandler() { private fun registerUncaughtExceptionHandler() {
uncaughtExceptionHandlerManager = UncaughtExceptionHandlerManager().apply { uncaughtExceptionHandlerManager = UncaughtExceptionHandlerManager().apply {
@ -777,9 +753,51 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
} }
} }
private fun wakeUpDeviceIfLocked() {
// Get the KeyguardManager and PowerManager
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
// Check if the phone is locked
val isPhoneLocked = keyguardManager.isKeyguardLocked
// Check if the screen is awake
val isScreenAwake = powerManager.isInteractive
if (!isScreenAwake) {
Log.w("ACL", "Screen is NOT awake - waking it up!")
val wakeLock = powerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK or
PowerManager.ACQUIRE_CAUSES_WAKEUP or
PowerManager.ON_AFTER_RELEASE,
"${NonTranslatableStringConstants.APP_NAME}:WakeLock"
)
// Acquire the wake lock to wake up the device
wakeLock.acquire(3000) // Wake up for 3 seconds
val startTime = System.currentTimeMillis()
while (!powerManager.isInteractive) { /* Busy wait until we're awake */ }
val endTime = System.currentTimeMillis()
val duration = endTime - startTime
Log.w("ACL", "Woken up in $duration ms")
} else {
Log.w("ACL", "Screen is awake - doing nothing")
}
// Dismiss the keyguard
val keyguardLock = keyguardManager.newKeyguardLock("MyApp:KeyguardLock")
keyguardLock.disableKeyguard()
}
// Over the course of setting up a phonecall this method is called multiple times with `types` of PRE_OFFER -> RING_INCOMING -> ICE_MESSAGE // Over the course of setting up a phonecall this method is called multiple times with `types` of PRE_OFFER -> RING_INCOMING -> ICE_MESSAGE
private fun setCallInProgressNotification(type: Int, recipient: Recipient?) { private fun setCallInProgressNotification(type: Int, recipient: Recipient?) {
wakeUpDeviceIfLocked()
val typeString = when (type) { val typeString = when (type) {
TYPE_INCOMING_RINGING -> "TYPE_INCOMING_RINGING" TYPE_INCOMING_RINGING -> "TYPE_INCOMING_RINGING"
TYPE_OUTGOING_RINGING -> "TYPE_OUTGOING_RINGING" TYPE_OUTGOING_RINGING -> "TYPE_OUTGOING_RINGING"
@ -789,7 +807,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
WEBRTC_NOTIFICATION -> "WEBRTC_NOTIFICATION" WEBRTC_NOTIFICATION -> "WEBRTC_NOTIFICATION"
else -> "We have no idea!" else -> "We have no idea!"
} }
Log.w("ACL", "Hit setCallInProgressNotification with type: $typeString") Log.w("ACL", "NOOOOOOOOOOTIFICATION - Hit setCallInProgressNotification with type: $typeString")
// If notifications are enabled we'll try and start a foreground service to show the notification // If notifications are enabled we'll try and start a foreground service to show the notification
var failedToStartForegroundService = false var failedToStartForegroundService = false
@ -815,9 +833,13 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
if (type == TYPE_INCOMING_PRE_OFFER && failedToStartForegroundService) { if ((type == TYPE_INCOMING_PRE_OFFER || type == TYPE_INCOMING_RINGING) && failedToStartForegroundService) {
//if (failedToStartForegroundService) {
Log.w("ACL", "DID SOMETHING - foregroundIntent to WebRtcCallActivity for TYPE_INCOMING_PRE_OFFER")
wakeUpDeviceIfLocked()
Log.w("ACL", "About to create foregroundIntent and try to start the WebRtcCallActivity with type TYPE_INCOMING_PRE_OFFER")
// Start an intent for the fullscreen call activity // Start an intent for the fullscreen call activity
val foregroundIntent = Intent(this, WebRtcCallActivity::class.java) val foregroundIntent = Intent(this, WebRtcCallActivity::class.java)

@ -37,30 +37,30 @@ class CallNotificationBuilder {
return notificationManager.areNotificationsEnabled() return notificationManager.areNotificationsEnabled()
} }
@JvmStatic // @JvmStatic
fun getFirstCallNotification(context: Context, callerName: String): Notification { // fun getFirstCallNotification(context: Context, callerName: String): Notification {
val contentIntent = Intent(context, SettingsActivity::class.java) // val contentIntent = Intent(context, SettingsActivity::class.java)
//
val pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) // val pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
//
val titleTxt = context.getSubbedString(R.string.callsMissedCallFrom, NAME_KEY to callerName) // val titleTxt = context.getSubbedString(R.string.callsMissedCallFrom, NAME_KEY to callerName)
val bodyTxt = context.getSubbedCharSequence( // val bodyTxt = context.getSubbedCharSequence(
R.string.callsYouMissedCallPermissions, // R.string.callsYouMissedCallPermissions,
NAME_KEY to callerName // NAME_KEY to callerName
) // )
//
val builder = NotificationCompat.Builder(context, NotificationChannels.CALLS) // val builder = NotificationCompat.Builder(context, NotificationChannels.CALLS)
.setSound(null) // .setSound(null)
.setSmallIcon(R.drawable.ic_baseline_call_24) // .setSmallIcon(R.drawable.ic_baseline_call_24)
.setContentIntent(pendingIntent) // .setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH) // .setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentTitle(titleTxt) // .setContentTitle(titleTxt)
.setContentText(bodyTxt) // .setContentText(bodyTxt)
.setStyle(NotificationCompat.BigTextStyle().bigText(bodyTxt)) // .setStyle(NotificationCompat.BigTextStyle().bigText(bodyTxt))
.setAutoCancel(true) // .setAutoCancel(true)
//
return builder.build() // return builder.build()
} // }
@JvmStatic @JvmStatic
fun getCallInProgressNotification(context: Context, type: Int, recipient: Recipient?): Notification { fun getCallInProgressNotification(context: Context, type: Int, recipient: Recipient?): Notification {

@ -2,15 +2,18 @@ package org.thoughtcrime.securesms.webrtc
import android.Manifest import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.KeyguardManager
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import android.os.PowerManager
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope import androidx.lifecycle.coroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
@ -36,7 +39,7 @@ import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.service.WebRtcCallService import org.thoughtcrime.securesms.service.WebRtcCallService
import org.webrtc.IceCandidate import org.webrtc.IceCandidate
import network.loki.messenger.R import network.loki.messenger.R
import org.session.libsession.utilities.NonTranslatableStringConstants
class CallMessageProcessor(private val context: Context, private val textSecurePreferences: TextSecurePreferences, lifecycle: Lifecycle, private val storage: StorageProtocol) { class CallMessageProcessor(private val context: Context, private val textSecurePreferences: TextSecurePreferences, lifecycle: Lifecycle, private val storage: StorageProtocol) {
@ -56,11 +59,7 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
fun safeStartForegroundService(context: Context, intent: Intent) { fun safeStartForegroundService(context: Context, intent: Intent) {
Log.w("ACL", "Hit safeStartForegroundService for intent action: " + intent.action) Log.w("ACL", "Hit safeStartForegroundService for intent action: " + intent.action)
// TODO: This is super-ugly - we're forcing a full-screen intent to wake the device up so we can
// TODO: successfully call `startForegroundService` in the second catch block below. This works
// TODO: even if the device is locked and Session has been closed down - but it's UUUUGLY. Need
// TODO: to find a better way.
showIncomingCallNotification(context)
// If the foreground service crashes then it's possible for one of these intents to // If the foreground service crashes then it's possible for one of these intents to
// be started in the background (in which case 'startService' will throw a // be started in the background (in which case 'startService' will throw a
@ -71,6 +70,12 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
try { ContextCompat.startForegroundService(context, intent) } try { ContextCompat.startForegroundService(context, intent) }
catch (e2: Exception) { catch (e2: Exception) {
Log.e("Loki", "Unable to start CallMessage intent: ${e2.message}") Log.e("Loki", "Unable to start CallMessage intent: ${e2.message}")
// TODO: This is super-ugly - we're forcing a full-screen intent to wake the device up so we can
// TODO: successfully call `startForegroundService` in the second catch block below. This works
// TODO: even if the device is locked and Session has been closed down - but it's UUUUGLY. Need
// TODO: to find a better way.
showIncomingCallNotification(context)
} }
} }
} }
@ -87,8 +92,46 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
notificationManager?.createNotificationChannel(channel) notificationManager?.createNotificationChannel(channel)
} }
private fun wakeUpDeviceIfLocked(context: Context) {
// Get the KeyguardManager and PowerManager
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
// Check if the phone is locked
val isPhoneLocked = keyguardManager.isKeyguardLocked
// Check if the screen is awake
val isScreenAwake = powerManager.isInteractive
if (!isScreenAwake) {
Log.w("ACL", "CMP: Screen is NOT awake - waking it up!")
val wakeLock = powerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK or
PowerManager.ACQUIRE_CAUSES_WAKEUP or
PowerManager.ON_AFTER_RELEASE,
"${NonTranslatableStringConstants.APP_NAME}:WakeLock"
)
// Acquire the wake lock to wake up the device
wakeLock.acquire(3000) // Wake up for 3 seconds
} else {
Log.w("ACL", "CMP: Screen is awake - doing nothing")
}
// Dismiss the keyguard
//val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
//val keyguardLock = keyguardManager.newKeyguardLock("MyApp:KeyguardLock")
//keyguardLock.disableKeyguard()
}
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
fun showIncomingCallNotification(context: Context) { fun showIncomingCallNotification(context: Context) {
wakeUpDeviceIfLocked(context)
createNotificationChannel(context) createNotificationChannel(context)
val notificationIntent = Intent(context, WebRtcCallActivity::class.java) val notificationIntent = Intent(context, WebRtcCallActivity::class.java)
@ -108,7 +151,8 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
.setFullScreenIntent(pendingIntent, true) .setFullScreenIntent(pendingIntent, true)
NotificationManagerCompat.from(context).notify(999, notificationBuilder.build()) NotificationManagerCompat.from(context).notify(999, notificationBuilder.build())
} } }
}
init { init {
lifecycle.coroutineScope.launch(IO) { lifecycle.coroutineScope.launch(IO) {

Loading…
Cancel
Save