Trying to prevent or understand issues with incoming call activity

This commit is contained in:
Sylvain Berfini 2020-05-26 20:50:14 +02:00
parent fe8524da14
commit b6934e02fd
10 changed files with 106 additions and 30 deletions

View file

@ -101,14 +101,11 @@
<activity android:name=".activities.call.CallActivity"
android:launchMode="singleTop"
android:showWhenLocked="true"
android:supportsPictureInPicture="true" />
<activity android:name=".activities.call.IncomingCallActivity"
android:launchMode="singleTop"
android:noHistory="true"
android:showWhenLocked="true"
android:turnScreenOn="true" />
android:noHistory="true" />
<activity android:name=".activities.call.OutgoingCallActivity"
android:launchMode="singleTop"

View file

@ -49,6 +49,7 @@ class CallActivity : ProximitySensorActivity() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
Compatibility.setShowWhenLocked(this, true)
Compatibility.setTurnScreenOn(this, true)
binding = DataBindingUtil.setContentView(this, R.layout.call_activity)
binding.lifecycleOwner = this

View file

@ -22,6 +22,7 @@ package org.linphone.activities.call
import android.annotation.TargetApi
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.WindowManager
import androidx.databinding.DataBindingUtil
@ -47,22 +48,16 @@ class IncomingCallActivity : GenericActivity() {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
Compatibility.setShowWhenLocked(this, true)
Compatibility.setTurnScreenOn(this, true)
Compatibility.setShowWhenLocked(this, true)
Compatibility.requestDismissKeyguard(this)
binding = DataBindingUtil.setContentView(this, R.layout.call_incoming_activity)
binding.lifecycleOwner = this
var incomingCall: Call? = null
for (call in coreContext.core.calls) {
if (call.state == Call.State.IncomingReceived ||
call.state == Call.State.IncomingEarlyMedia) {
incomingCall = call
}
}
var incomingCall: Call? = findIncomingCall()
if (incomingCall == null) {
Log.e("[Incoming Call] Couldn't find call in state Incoming")
Log.e("[Incoming Call Activity] Couldn't find call in state Incoming")
finish()
return
}
@ -75,6 +70,14 @@ class IncomingCallActivity : GenericActivity() {
viewModel.callEndedEvent.observe(this, Observer {
it.consume {
Log.i("[Incoming Call Activity] Call ended, finish activity")
finish()
}
})
viewModel.callConnectedEvent.observe(this, Observer {
it.consume {
Log.i("[Incoming Call Activity] Call connected, finish activity")
finish()
}
})
@ -89,15 +92,25 @@ class IncomingCallActivity : GenericActivity() {
}
}
override fun onResume() {
super.onResume()
var incomingCall: Call? = findIncomingCall()
if (incomingCall == null) {
Log.e("[Incoming Call Activity] Couldn't find call in state Incoming")
finish()
}
}
@TargetApi(Version.API23_MARSHMALLOW_60)
private fun checkPermissions() {
val permissionsRequiredList = arrayListOf<String>()
if (!PermissionHelper.get().hasRecordAudioPermission()) {
Log.i("[Incoming Call] Asking for RECORD_AUDIO permission")
Log.i("[Incoming Call Activity] Asking for RECORD_AUDIO permission")
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
}
if (viewModel.call.currentParams.videoEnabled() && !PermissionHelper.get().hasCameraPermission()) {
Log.i("[Incoming Call] Asking for CAMERA permission")
Log.i("[Incoming Call Activity] Asking for CAMERA permission")
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
}
if (permissionsRequiredList.isNotEmpty()) {
@ -106,4 +119,14 @@ class IncomingCallActivity : GenericActivity() {
requestPermissions(permissionsRequired, 0)
}
}
private fun findIncomingCall(): Call? {
for (call in coreContext.core.calls) {
if (call.state == Call.State.IncomingReceived ||
call.state == Call.State.IncomingEarlyMedia) {
return call
}
}
return null
}
}

View file

@ -49,17 +49,9 @@ class OutgoingCallActivity : ProximitySensorActivity() {
binding = DataBindingUtil.setContentView(this, R.layout.call_outgoing_activity)
binding.lifecycleOwner = this
var outgoingCall: Call? = null
for (call in coreContext.core.calls) {
if (call.state == Call.State.OutgoingInit ||
call.state == Call.State.OutgoingProgress ||
call.state == Call.State.OutgoingRinging) {
outgoingCall = call
}
}
var outgoingCall: Call? = findOutgoingCall()
if (outgoingCall == null) {
Log.e("[Outgoing Call] Couldn't find call in state Outgoing")
Log.e("[Outgoing Call Activity] Couldn't find call in state Outgoing")
finish()
return
}
@ -91,6 +83,14 @@ class OutgoingCallActivity : ProximitySensorActivity() {
viewModel.callEndedEvent.observe(this, Observer {
it.consume {
Log.i("[Outgoing Call Activity] Call ended, finish activity")
finish()
}
})
viewModel.callConnectedEvent.observe(this, Observer {
it.consume {
Log.i("[Outgoing Call Activity] Call connected, finish activity")
finish()
}
})
@ -100,15 +100,25 @@ class OutgoingCallActivity : ProximitySensorActivity() {
}
}
override fun onResume() {
super.onResume()
var outgoingCall: Call? = findOutgoingCall()
if (outgoingCall == null) {
Log.e("[Outgoing Call Activity] Couldn't find call in state Outgoing")
finish()
}
}
@TargetApi(Version.API23_MARSHMALLOW_60)
private fun checkPermissions() {
val permissionsRequiredList = arrayListOf<String>()
if (!PermissionHelper.get().hasRecordAudioPermission()) {
Log.i("[Outgoing Call] Asking for RECORD_AUDIO permission")
Log.i("[Outgoing Call Activity] Asking for RECORD_AUDIO permission")
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
}
if (viewModel.call.currentParams.videoEnabled() && !PermissionHelper.get().hasCameraPermission()) {
Log.i("[Outgoing Call] Asking for CAMERA permission")
Log.i("[Outgoing Call Activity] Asking for CAMERA permission")
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
}
if (permissionsRequiredList.isNotEmpty()) {
@ -117,4 +127,15 @@ class OutgoingCallActivity : ProximitySensorActivity() {
requestPermissions(permissionsRequired, 0)
}
}
private fun findOutgoingCall(): Call? {
for (call in coreContext.core.calls) {
if (call.state == Call.State.OutgoingInit ||
call.state == Call.State.OutgoingProgress ||
call.state == Call.State.OutgoingRinging) {
return call
}
}
return null
}
}

View file

@ -50,6 +50,10 @@ open class CallViewModel(val call: Call) : GenericContactViewModel(call.remoteAd
MutableLiveData<Event<Boolean>>()
}
val callConnectedEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
private val listener = object : CallListenerStub() {
override fun onStateChanged(call: Call, state: Call.State, message: String) {
if (call != this@CallViewModel.call) return
@ -62,6 +66,8 @@ open class CallViewModel(val call: Call) : GenericContactViewModel(call.remoteAd
if (state == Call.State.Error) {
Log.e("[Call View Model] Error state reason is ${call.reason}")
}
} else if (call.state == Call.State.Connected) {
callConnectedEvent.value = Event(true)
}
}
}

View file

@ -169,5 +169,9 @@ class Api21Compatibility {
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
}
}
fun requestDismissKeyguard(activity: Activity) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
}
}
}

View file

@ -21,6 +21,7 @@ package org.linphone.compatibility
import android.annotation.TargetApi
import android.app.*
import android.content.Context
@TargetApi(27)
class Api27Compatibility {
@ -32,5 +33,10 @@ class Api27Compatibility {
fun setTurnScreenOn(activity: Activity, enable: Boolean) {
activity.setTurnScreenOn(enable)
}
fun requestDismissKeyguard(activity: Activity) {
val keyguardManager = activity.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
keyguardManager.requestDismissKeyguard(activity, null)
}
}
}

View file

@ -64,6 +64,14 @@ class Compatibility {
}
}
fun requestDismissKeyguard(activity: Activity) {
if (Version.sdkStrictlyBelow(Version.API27_OREO_81)) {
Api21Compatibility.requestDismissKeyguard(activity)
} else {
Api27Compatibility.requestDismissKeyguard(activity)
}
}
/* Notifications */
fun createNotificationChannels(

View file

@ -30,7 +30,6 @@ import android.telephony.PhoneStateListener
import android.telephony.TelephonyManager
import android.view.*
import java.io.File
import java.util.*
import kotlin.math.abs
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.activities.call.CallActivity
@ -435,6 +434,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
/* Start call related activities */
private fun onIncomingReceived() {
Log.i("[Context] Starting IncomingCallActivity")
val intent = Intent(context, IncomingCallActivity::class.java)
// This flag is required to start an Activity from a Service context
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@ -442,6 +442,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
}
private fun onOutgoingStarted() {
Log.i("[Context] Starting OutgoingCallActivity")
val intent = Intent(context, OutgoingCallActivity::class.java)
// This flag is required to start an Activity from a Service context
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@ -449,6 +450,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
}
private fun onCallStarted() {
Log.i("[Context] Starting CallActivity")
val intent = Intent(context, CallActivity::class.java)
// This flag is required to start an Activity from a Service context
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)

View file

@ -343,6 +343,11 @@ class NotificationsManager(private val context: Context) {
val address = call.remoteAddress.asStringUriOnly()
val notifiable = getNotifiableForCall(call)
if (notifiable.notificationId == currentForegroundServiceNotificationId) {
Log.w("[Notifications Manager] Incoming call notification already displayed by foreground service, skipping")
return
}
val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
val pictureUri = contact?.getContactThumbnailPictureUri()
val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri)
@ -380,10 +385,13 @@ class NotificationsManager(private val context: Context) {
.addAction(getCallAnswerAction(notifiable.notificationId))
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
.build()
notify(notifiable.notificationId, notification)
if (useAsForeground) {
Log.i("[Notifications Manager] Notifying incoming call notification for foreground service")
startForeground(notifiable.notificationId, notification)
} else {
Log.i("[Notifications Manager] Notifying incoming call notification")
notify(notifiable.notificationId, notification)
}
}