pull/1706/head
Al Lansley 4 months ago
parent 2ec50b576f
commit fa20d7d5e8

@ -406,7 +406,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
@SuppressWarnings("CodeBlock2Expr")
@SuppressLint("InlinedApi")
private void saveToDisk() {
Log.w("ACL", "Asked to save to disk!");
MediaItem mediaItem = getCurrentMediaItem();
if (mediaItem == null) return;

@ -146,11 +146,8 @@ public abstract class MessageRecord extends DisplayRecord {
} else if (isOutgoingCall()) {
callType = CallMessageType.CALL_OUTGOING;
} else if (isMissedCall()) {
Log.w("ACL", "We think CALL_MISSSED");
callType = CallMessageType.CALL_MISSED;
} else {
Log.w("ACL", "We think CALL_FIRST_MISSSED");
callType = CallMessageType.CALL_FIRST_MISSED;
}
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildCallMessage(context, callType, getIndividualRecipient().getAddress().serialize()));

@ -235,7 +235,6 @@ public class KeyCachingService extends Service {
private void foregroundService() {
if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) {
Log.w("ACL", "Stopping foreground service in KeyCachingService");
stopForeground(true);
return;
}

@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.service
import android.app.ForegroundServiceStartNotAllowedException
import android.app.KeyguardManager
import android.content.BroadcastReceiver
import android.content.Context
@ -22,6 +21,12 @@ import androidx.lifecycle.LifecycleService
import androidx.lifecycle.lifecycleScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.hilt.android.AndroidEntryPoint
import java.util.UUID
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import org.session.libsession.messaging.calls.CallMessageType
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.FutureTaskListener
@ -49,6 +54,7 @@ import org.thoughtcrime.securesms.webrtc.UncaughtExceptionHandlerManager
import org.thoughtcrime.securesms.webrtc.WiredHeadsetStateReceiver
import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger
import org.thoughtcrime.securesms.webrtc.data.Event
import org.thoughtcrime.securesms.webrtc.data.State as CallState
import org.thoughtcrime.securesms.webrtc.locks.LockManager
import org.webrtc.DataChannel
import org.webrtc.IceCandidate
@ -59,13 +65,6 @@ import org.webrtc.PeerConnection.IceConnectionState.DISCONNECTED
import org.webrtc.PeerConnection.IceConnectionState.FAILED
import org.webrtc.RtpReceiver
import org.webrtc.SessionDescription
import java.util.UUID
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import org.thoughtcrime.securesms.webrtc.data.State as CallState
@AndroidEntryPoint
class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
@ -333,32 +332,8 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
registerUncaughtExceptionHandler()
networkChangedReceiver = NetworkChangeReceiver(::networkChange)
networkChangedReceiver!!.register(this)
//Log.w("ACL", "Lesssgo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
//if (appIsBackground(this)) {
// ServiceCompat.startForeground(this,
// CallNotificationBuilder.WEBRTC_NOTIFICATION,
// CallNotificationBuilder.getFirstCallNotification(this, "Initialising"),
// if (Build.VERSION.SDK_INT >= 30) ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL else 0
// )
// If the screen is off or phone is locked, wake it up
//if (!isScreenAwake || isPhoneLocked) { wakeUpDevice() }
// ServiceCompat.startForeground(
// this,
// CallNotificationBuilder.WEBRTC_NOTIFICATION,
// Not
// CallNotificationBuilder.getCallInProgressNotification(this, type, recipient),
// if (Build.VERSION.SDK_INT >= 30) ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL else 0
// )
}
private fun registerUncaughtExceptionHandler() {
uncaughtExceptionHandlerManager = UncaughtExceptionHandlerManager().apply {
registerHandler(ProximityLockRelease(lockManager))
@ -660,6 +635,20 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
}
}
/**
* Handles remote ICE candidates received from a signaling server.
*
* This function is called when a new ICE candidate is received for a specific call.
* It extracts the candidate information from the intent, creates IceCandidate objects,
* and passes them to the CallManager to be added to the PeerConnection.
*
* @param intent The intent containing the remote ICE candidate information.
* The intent should contain the following extras:
* - EXTRA_CALL_ID: The ID of the call.
* - EXTRA_ICE_SDP_MID: An array of SDP media stream identification strings.
* - EXTRA_ICE_SDP_LINE_INDEX: An array of SDP media line indexes.
* - EXTRA_ICE_SDP: An array of SDP candidate strings.
*/
private fun handleRemoteIceCandidate(intent: Intent) {
val callId = getCallId(intent)
val sdpMids = intent.getStringArrayExtra(EXTRA_ICE_SDP_MID) ?: return
@ -754,7 +743,6 @@ 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
@ -766,9 +754,6 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
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
@ -777,70 +762,47 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
)
// Acquire the wake lock to wake up the device
wakeLock.acquire(3000) // Wake up for 3 seconds
wakeLock.acquire(3000)
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")
while (!powerManager.isInteractive) {
/* Busy wait until we're awake - typically takes less than ~10ms */
}
}
// 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 phone call this method is called multiple times with `types`
// of PRE_OFFER -> RING_INCOMING -> ICE_MESSAGE
private fun setCallInProgressNotification(type: Int, recipient: Recipient?) {
wakeUpDeviceIfLocked()
val typeString = when (type) {
TYPE_INCOMING_RINGING -> "TYPE_INCOMING_RINGING"
TYPE_OUTGOING_RINGING -> "TYPE_OUTGOING_RINGING"
TYPE_ESTABLISHED -> "TYPE_ESTABLISHED"
TYPE_INCOMING_CONNECTING -> "TYPE_INCOMING_CONNECTING"
TYPE_INCOMING_PRE_OFFER -> "TYPE_INCOMING_PRE_OFFER"
WEBRTC_NOTIFICATION -> "WEBRTC_NOTIFICATION"
else -> "We have no idea!"
}
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
var failedToStartForegroundService = false
if (CallNotificationBuilder.areNotificationsEnabled(this)) {
Log.w("ACL", "Notifications are ENABLED! About to try to call startForeground")
try {
ServiceCompat.startForeground(
this,
CallNotificationBuilder.WEBRTC_NOTIFICATION,
WEBRTC_NOTIFICATION,
CallNotificationBuilder.getCallInProgressNotification(this, type, recipient),
if (Build.VERSION.SDK_INT >= 30) ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL else 0
)
Log.w("ACL", "Successfully called startForeground - about to bail.")
return
} catch (e: IllegalStateException) {
Log.e(TAG, "Failed to setCallInProgressNotification as a foreground service for type: ${type}, trying to update instead", e)
failedToStartForegroundService = true
}
} else {
Log.w("ACL", "Notifications are NOT enabled! Skipped attempt at startForeground and going straight to fullscreen intent attempt!")
// Notifications are NOT enabled! Skipped attempt at startForeground and going straight to fullscreen intent attempt!
}
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()
// Start an intent for the fullscreen call activity
val foregroundIntent = Intent(this, WebRtcCallActivity::class.java)
.setFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_BROUGHT_TO_FRONT or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
@ -848,8 +810,6 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
startActivity(foregroundIntent)
return
}
Log.w("ACL", "type wasn't TYPE_INCOMING_PRE_OFFER - doing nothing =/")
}
private fun getOptionalRemoteRecipient(intent: Intent): Recipient? =

@ -51,31 +51,24 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
// TODO: While fine if the app is in the foreground, you cannot do this in modern Android if the
// While fine if the app is in the foreground, you cannot do this in modern Android if the
// device is locked (i.e., if you get a call when the device is locked & attempt start the
// foreground service) it will throw an error like:
// Unable to start CallMessage intent: startForegroundService() not allowed due to mAllowStartForeground false:
// service network.loki.messenger/org.thoughtcrime.securesms.service.WebRtcCallService
fun safeStartForegroundService(context: Context, intent: Intent) {
Log.w("ACL", "Hit safeStartForegroundService for intent action: " + intent.action)
// 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
// 'BackgroundServiceStartNotAllowedException' exception) so catch that case and try
// to re-start the service in the foreground
// Attempt to start the call service..
try { context.startService(intent) }
catch(e: Exception) {
// ..however due to tightened restrictions in Android 12 and above this will not
// work (BackgroundServiceStartNotAllowedException) if the device is asleep / locked
// so we have to wake the device first and then try to start it as a foreground service.
// Note: Attempting to start a foreground service while the device is asleep / locked
// will also cause an exception.
wakeUpDeviceIfLocked(context)
try { ContextCompat.startForegroundService(context, intent) }
catch (e2: Exception) {
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)
}
}
}
@ -92,23 +85,11 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
notificationManager?.createNotificationChannel(channel)
}
// Wake the device up if it's asleep / locked - used when we receive an incoming call
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
@ -116,41 +97,9 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
"${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")
// We only need the wake lock briefly
wakeLock.acquire(3000)
}
// Dismiss the keyguard
//val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
//val keyguardLock = keyguardManager.newKeyguardLock("MyApp:KeyguardLock")
//keyguardLock.disableKeyguard()
}
@SuppressLint("MissingPermission")
fun showIncomingCallNotification(context: Context) {
wakeUpDeviceIfLocked(context)
createNotificationChannel(context)
val notificationIntent = Intent(context, WebRtcCallActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context,
0,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notificationBuilder = NotificationCompat.Builder(context, "WakeUpChannelID")
.setContentTitle("Incoming Call")
.setContentText("Tap to answer")
.setSmallIcon(R.drawable.ic_baseline_call_24)
.setPriority(NotificationCompat.PRIORITY_MAX) // Used for devices below API 26
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(pendingIntent, true)
NotificationManagerCompat.from(context).notify(999, notificationBuilder.build())
}
}
@ -164,8 +113,7 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
Log.i("Loki", "Contact is approved?: $approvedContact")
if (!approvedContact && storage.getUserPublicKey() != sender) continue
// if the user has not enabled voice/video calls
// or if the user has not granted audio/microphone permissions
// If the user has not enabled voice/video calls or if the user has not granted audio/microphone permissions
if (
!textSecurePreferences.isCallNotificationsEnabled() ||
!Permissions.hasAll(context, Manifest.permission.RECORD_AUDIO)

Loading…
Cancel
Save