diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 984deedb..3b25121b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -82,6 +82,12 @@
android:label="@string/speed_dial"
android:parentActivityName=".activities.SettingsActivity" />
+
+
1) {
accounts.forEachIndexed { index, account ->
- if (account == CallManager.call?.details?.accountHandle) {
+ if (account == CallManager.getPrimaryCall()?.details?.accountHandle) {
call_sim_id.text = "${index + 1}"
call_sim_id.beVisible()
call_sim_image.beVisible()
@@ -395,8 +406,9 @@ class CallActivity : SimpleActivity() {
}
}
- private fun updateCallState(call: Call?) {
- val state = call?.getStateCompat()
+ private fun updateCallState(call: Call) {
+ val state = call.getStateCompat()
+ Log.d(TAG, "updateCallState: $state")
when (state) {
Call.STATE_RINGING -> callRinging()
Call.STATE_ACTIVE -> callStarted()
@@ -407,17 +419,22 @@ class CallActivity : SimpleActivity() {
val statusTextId = when (state) {
Call.STATE_RINGING -> R.string.is_calling
- Call.STATE_DIALING -> R.string.dialing
+ Call.STATE_CONNECTING, Call.STATE_DIALING -> R.string.dialing
else -> 0
}
if (statusTextId != 0) {
call_status_label.text = getString(statusTextId)
}
+
+ call_manage.beVisibleIf(call.hasCapability(Call.Details.CAPABILITY_MANAGE_CONFERENCE))
+ setActionButtonEnabled(call_swap, state == Call.STATE_ACTIVE)
+ setActionButtonEnabled(call_merge, state == Call.STATE_ACTIVE)
}
private fun updateState() {
val phoneState = CallManager.getPhoneState()
+ Log.d(TAG, "updateState: $phoneState")
if (phoneState is SingleCall) {
updateCallState(phoneState.call)
updateCallOnHoldState(null)
@@ -426,7 +443,6 @@ class CallActivity : SimpleActivity() {
|| state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING)
setActionButtonEnabled(call_toggle_hold, isSingleCallActionsEnabled)
setActionButtonEnabled(call_add, isSingleCallActionsEnabled)
- call_manage.beVisibleIf(phoneState.call.isConference())
} else if (phoneState is TwoCalls) {
updateCallState(phoneState.active)
updateCallOnHoldState(phoneState.onHold)
@@ -436,7 +452,7 @@ class CallActivity : SimpleActivity() {
private fun updateCallOnHoldState(call: Call?) {
val hasCallOnHold = call != null
if (hasCallOnHold) {
- CallManager.getCallContact(applicationContext, call) { contact ->
+ getCallContact(applicationContext, call) { contact ->
runOnUiThread {
on_hold_caller_name.text = getContactNameOrNumber(contact)
}
@@ -448,18 +464,15 @@ class CallActivity : SimpleActivity() {
}
private fun updateCallContactInfo(call: Call?) {
- if (call.isConference()) {
- caller_avatar.setImageDrawable(null)
- caller_number.text = null
- caller_name_label.text = getString(R.string.conference)
- } else {
- CallManager.getCallContact(applicationContext, call) { contact ->
- callContact = contact
- val avatar = callContactAvatarHelper.getCallContactAvatar(contact)
- runOnUiThread {
- updateOtherPersonsInfo(avatar)
- checkCalledSIMCard()
- }
+ getCallContact(applicationContext, call) { contact ->
+ if (call != CallManager.getPrimaryCall()) {
+ return@getCallContact
+ }
+ callContact = contact
+ val avatar = if (!call.isConference()) callContactAvatarHelper.getCallContactAvatar(contact) else null
+ runOnUiThread {
+ updateOtherPersonsInfo(avatar)
+ checkCalledSIMCard()
}
}
}
@@ -489,7 +502,7 @@ class CallActivity : SimpleActivity() {
private fun showPhoneAccountPicker() {
if (callContact != null) {
getHandleToUse(intent, callContact!!.number) { handle ->
- CallManager.call?.phoneAccountSelected(handle, false)
+ CallManager.getPrimaryCall()?.phoneAccountSelected(handle, false)
}
}
}
@@ -523,11 +536,13 @@ class CallActivity : SimpleActivity() {
}
private val callCallback = object : CallManagerListener {
- override fun onStateChanged(call: Call, state: Int) {
+ override fun onStateChanged() {
updateState()
}
override fun onPrimaryCallChanged(call: Call) {
+ Log.d(TAG, "onPrimaryCallChanged: $call")
+ callDurationHandler.removeCallbacks(updateCallDurationTask)
updateCallContactInfo(call)
updateState()
}
@@ -535,7 +550,7 @@ class CallActivity : SimpleActivity() {
private val updateCallDurationTask = object : Runnable {
override fun run() {
- callDuration = CallManager.getCallDuration()
+ callDuration = CallManager.getPrimaryCall().getCallDuration()
if (!isCallEnded) {
call_status_label.text = callDuration.getFormattedDuration()
callDurationHandler.postDelayed(this, 1000)
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/activities/ConferenceActivity.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/activities/ConferenceActivity.kt
new file mode 100644
index 00000000..6ad3c2d1
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/activities/ConferenceActivity.kt
@@ -0,0 +1,18 @@
+package com.simplemobiletools.dialer.activities
+
+import android.os.Bundle
+import com.simplemobiletools.dialer.R
+import com.simplemobiletools.dialer.adapters.ConferenceCallsAdapter
+import com.simplemobiletools.dialer.helpers.CallManager
+import kotlinx.android.synthetic.main.activity_conference.*
+
+class ConferenceActivity : SimpleActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_conference)
+ supportActionBar
+
+ conference_calls_list.adapter = ConferenceCallsAdapter(this, conference_calls_list, ArrayList(CallManager.getConferenceCalls())) {}
+ }
+}
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/adapters/ConferenceCallsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/adapters/ConferenceCallsAdapter.kt
new file mode 100644
index 00000000..2d9b339d
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/adapters/ConferenceCallsAdapter.kt
@@ -0,0 +1,93 @@
+package com.simplemobiletools.dialer.adapters
+
+import android.telecom.Call
+import android.view.Menu
+import android.view.ViewGroup
+import com.bumptech.glide.Glide
+import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
+import com.simplemobiletools.commons.helpers.LOWER_ALPHA
+import com.simplemobiletools.commons.helpers.SimpleContactsHelper
+import com.simplemobiletools.commons.views.MyRecyclerView
+import com.simplemobiletools.dialer.R
+import com.simplemobiletools.dialer.activities.SimpleActivity
+import com.simplemobiletools.dialer.extensions.hasCapability
+import com.simplemobiletools.dialer.helpers.getCallContact
+import kotlinx.android.synthetic.main.item_conference_call.view.*
+
+class ConferenceCallsAdapter(
+ activity: SimpleActivity, recyclerView: MyRecyclerView, val data: ArrayList, itemClick: (Any) -> Unit
+) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
+
+ override fun actionItemPressed(id: Int) {
+ }
+
+ override fun getActionMenuId(): Int = 0
+
+ override fun getIsItemSelectable(position: Int): Boolean = false
+
+ override fun getItemCount(): Int = data.size
+
+ override fun getItemKeyPosition(key: Int): Int = -1
+
+ override fun getItemSelectionKey(position: Int): Int? = null
+
+ override fun getSelectableItemCount(): Int = data.size
+
+ override fun onActionModeCreated() {
+ }
+
+ override fun onActionModeDestroyed() {
+ }
+
+ override fun prepareActionMode(menu: Menu) {
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conference_call, parent)
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val call = data[position]
+ holder.bindView(call, allowSingleClick = false, allowLongClick = false) { itemView, _ ->
+ getCallContact(itemView.context, call) { callContact ->
+ itemView.post {
+ itemView.item_conference_call_name.text = callContact.name.ifEmpty { itemView.context.getString(R.string.unknown_caller) }
+ SimpleContactsHelper(activity).loadContactImage(
+ callContact.photoUri,
+ itemView.item_conference_call_image,
+ callContact.name,
+ activity.getDrawable(R.drawable.ic_person_vector)
+ )
+ }
+ }
+ val canSeparate = call.hasCapability(Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE)
+ val canDisconnect = call.hasCapability(Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE)
+ itemView.item_conference_call_split.isEnabled = canSeparate
+ itemView.item_conference_call_split.alpha = if (canSeparate) 1.0f else LOWER_ALPHA
+ itemView.item_conference_call_split.setOnClickListener {
+ call.splitFromConference()
+ data.removeAt(position)
+ notifyItemRemoved(position)
+ if (data.size == 1) {
+ activity.finish()
+ }
+ }
+ itemView.item_conference_call_end.isEnabled = canDisconnect
+ itemView.item_conference_call_end.alpha = if (canDisconnect) 1.0f else LOWER_ALPHA
+ itemView.item_conference_call_end.setOnClickListener {
+ call.disconnect()
+ data.removeAt(position)
+ notifyItemRemoved(position)
+ if (data.size == 1) {
+ activity.finish()
+ }
+ }
+ }
+ bindViewHolder(holder)
+ }
+
+ override fun onViewRecycled(holder: ViewHolder) {
+ super.onViewRecycled(holder)
+ if (!activity.isDestroyed && !activity.isFinishing) {
+ Glide.with(activity).clear(holder.itemView.item_conference_call_image)
+ }
+ }
+}
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/extensions/Call.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/extensions/Call.kt
index e66f1b16..80f1173f 100644
--- a/app/src/main/kotlin/com/simplemobiletools/dialer/extensions/Call.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/extensions/Call.kt
@@ -19,12 +19,22 @@ fun Call?.getStateCompat(): Int {
}
}
+fun Call?.getCallDuration(): Int {
+ return if (this != null) {
+ val connectTimeMillis = details.connectTimeMillis
+ if (connectTimeMillis == 0L) {
+ return 0
+ }
+ ((System.currentTimeMillis() - connectTimeMillis) / 1000).toInt()
+ } else {
+ 0
+ }
+}
+
fun Call.isOutgoing(): Boolean {
return OUTGOING_CALL_STATES.contains(getStateCompat())
}
-fun Call.hasCapability(capability: Int): Boolean = details.callCapabilities and capability != 0
-
-fun Call.hasProperty(property: Int): Boolean = details.hasProperty(property)
+fun Call.hasCapability(capability: Int): Boolean = (details.callCapabilities and capability) != 0
fun Call?.isConference(): Boolean = this?.details?.hasProperty(Call.Details.PROPERTY_CONFERENCE) == true
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallContactHelper.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallContactHelper.kt
new file mode 100644
index 00000000..3f234793
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallContactHelper.kt
@@ -0,0 +1,71 @@
+package com.simplemobiletools.dialer.helpers
+
+import android.content.Context
+import android.net.Uri
+import android.telecom.Call
+import com.simplemobiletools.commons.extensions.getMyContactsCursor
+import com.simplemobiletools.commons.extensions.getPhoneNumberTypeText
+import com.simplemobiletools.commons.helpers.MyContactsContentProvider
+import com.simplemobiletools.commons.helpers.SimpleContactsHelper
+import com.simplemobiletools.commons.helpers.ensureBackgroundThread
+import com.simplemobiletools.dialer.R
+import com.simplemobiletools.dialer.extensions.isConference
+import com.simplemobiletools.dialer.models.CallContact
+
+fun getCallContact(context: Context, call: Call?, callback: (CallContact) -> Unit) {
+ if (call.isConference()) {
+ callback(CallContact(context.getString(R.string.conference), "", "", ""))
+ return
+ }
+ val privateCursor = context.getMyContactsCursor(false, true)
+ ensureBackgroundThread {
+ val callContact = CallContact("", "", "", "")
+ val handle = try {
+ call?.details?.handle?.toString()
+ } catch (e: NullPointerException) {
+ null
+ }
+
+ if (handle == null) {
+ callback(callContact)
+ return@ensureBackgroundThread
+ }
+
+ val uri = Uri.decode(handle)
+ if (uri.startsWith("tel:")) {
+ val number = uri.substringAfter("tel:")
+ SimpleContactsHelper(context).getAvailableContacts(false) { contacts ->
+ val privateContacts = MyContactsContentProvider.getSimpleContacts(context, privateCursor)
+ if (privateContacts.isNotEmpty()) {
+ contacts.addAll(privateContacts)
+ }
+
+ val contactsWithMultipleNumbers = contacts.filter { it.phoneNumbers.size > 1 }
+ val numbersToContactIDMap = HashMap()
+ contactsWithMultipleNumbers.forEach { contact ->
+ contact.phoneNumbers.forEach { phoneNumber ->
+ numbersToContactIDMap[phoneNumber.value] = contact.contactId
+ numbersToContactIDMap[phoneNumber.normalizedNumber] = contact.contactId
+ }
+ }
+
+ callContact.number = number
+ val contact = contacts.firstOrNull { it.doesHavePhoneNumber(number) }
+ if (contact != null) {
+ callContact.name = contact.name
+ callContact.photoUri = contact.photoUri
+
+ if (contact.phoneNumbers.size > 1) {
+ val specificPhoneNumber = contact.phoneNumbers.firstOrNull { it.value == number }
+ if (specificPhoneNumber != null) {
+ callContact.numberLabel = context.getPhoneNumberTypeText(specificPhoneNumber.type, specificPhoneNumber.label)
+ }
+ }
+ } else {
+ callContact.name = number
+ }
+ callback(callContact)
+ }
+ }
+ }
+}
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt
index e8f7c996..ea3d1b40 100644
--- a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt
@@ -1,35 +1,31 @@
package com.simplemobiletools.dialer.helpers
-import android.content.Context
-import android.net.Uri
+import android.annotation.SuppressLint
import android.telecom.Call
import android.telecom.InCallService
import android.telecom.VideoProfile
import android.util.Log
-import com.simplemobiletools.commons.extensions.getMyContactsCursor
-import com.simplemobiletools.commons.extensions.getPhoneNumberTypeText
-import com.simplemobiletools.commons.helpers.MyContactsContentProvider
-import com.simplemobiletools.commons.helpers.SimpleContactsHelper
-import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.dialer.extensions.getStateCompat
import com.simplemobiletools.dialer.extensions.hasCapability
import com.simplemobiletools.dialer.extensions.isConference
-import com.simplemobiletools.dialer.models.CallContact
import java.util.concurrent.CopyOnWriteArraySet
const val TAG = "SimpleDialer:CallManager"
+const val TAG2 = TAG /*"SimpleDialer:CallState"*/
// inspired by https://github.com/Chooloo/call_manage
class CallManager {
companion object {
- var call: Call? = null
+ @SuppressLint("StaticFieldLeak")
var inCallService: InCallService? = null
- val calls = mutableListOf()
+ private var call: Call? = null
+ private val calls = mutableListOf()
private val listeners = CopyOnWriteArraySet()
fun onCallAdded(call: Call) {
this.call = call
calls.add(call)
+ Log.d(TAG, "onCallAdded (${calls.size}): $call")
for (listener in listeners) {
listener.onPrimaryCallChanged(call)
}
@@ -37,13 +33,15 @@ class CallManager {
override fun onStateChanged(call: Call, state: Int) {
Log.d(TAG, "onStateChanged: $call")
updateState()
- for (listener in listeners) {
- listener.onStateChanged(call, state)
- }
+ }
+
+ override fun onDetailsChanged(call: Call, details: Call.Details) {
+ Log.d(TAG, "onDetailsChanged")
+ updateState()
}
override fun onConferenceableCallsChanged(call: Call, conferenceableCalls: MutableList) {
- Log.d(TAG, "onConferenceableCallsChanged: $call, conferenceableCalls size=${conferenceableCalls.size}")
+ Log.d(TAG, "onConferenceableCallsChanged (${conferenceableCalls.size}): $call")
updateState()
}
})
@@ -51,34 +49,59 @@ class CallManager {
fun onCallRemoved(call: Call) {
calls.remove(call)
+ Log.d(TAG, "onCallRemoved (${calls.size}): $call")
updateState()
}
fun getPhoneState(): PhoneState {
return when (calls.size) {
0 -> {
+ Log.d(TAG2, "No call")
NoCall
}
1 -> {
+ Log.d(TAG2, "Single call")
SingleCall(calls.first())
}
2 -> {
+ Log.d(TAG2, "Two calls")
val active = calls.find { it.getStateCompat() == Call.STATE_ACTIVE }
val newCall = calls.find { it.getStateCompat() == Call.STATE_CONNECTING || it.getStateCompat() == Call.STATE_DIALING }
val onHold = calls.find { it.getStateCompat() == Call.STATE_HOLDING }
if (active != null && newCall != null) {
TwoCalls(newCall, active)
- } else if(newCall != null && onHold != null) {
+ } else if (newCall != null && onHold != null) {
TwoCalls(newCall, onHold)
- } else if(active != null && onHold != null) {
+ } else if (active != null && onHold != null) {
TwoCalls(active, onHold)
} else {
TwoCalls(calls[0], calls[1])
}
}
else -> {
- SingleCall(calls.find { it.isConference() }!!)
- // TODO handle the call on hold (outside the conference)
+ val conference = calls.find { it.isConference() }!!
+ val secondCall = if (conference.children.size + 1 != calls.size) {
+ calls.filter { !it.isConference() }
+ .subtract(conference.children.toSet())
+ .firstOrNull()
+ } else {
+ null
+ }
+ Log.d(TAG2, "Conference call (${conference.children.size} children)")
+ Log.d(TAG2, "secondCall: $secondCall")
+ if (secondCall == null) {
+ Log.d(TAG2, "Conference call (single)")
+ SingleCall(conference)
+ } else {
+ val newCallState = secondCall.getStateCompat()
+ if (newCallState == Call.STATE_ACTIVE || newCallState == Call.STATE_CONNECTING || newCallState == Call.STATE_DIALING) {
+ Log.d(TAG2, "Conference call and regular call (conference on hold)")
+ TwoCalls(secondCall, conference)
+ } else {
+ Log.d(TAG2, "Conference call and regular call (regular call on hold)")
+ TwoCalls(conference, secondCall)
+ }
+ }
}
}
}
@@ -89,6 +112,7 @@ class CallManager {
is SingleCall -> phoneState.call
is TwoCalls -> phoneState.active
}
+ var notify = true
if (primaryCall == null) {
call = null
} else if (primaryCall != call) {
@@ -96,6 +120,12 @@ class CallManager {
for (listener in listeners) {
listener.onPrimaryCallChanged(primaryCall)
}
+ notify = false
+ }
+ if (notify) {
+ for (listener in listeners) {
+ listener.onStateChanged()
+ }
}
}
@@ -103,11 +133,8 @@ class CallManager {
return call
}
- fun getSecondaryCall(): Call? {
- if (calls.size == 1) {
- return null
- }
- return calls.find { it.getStateCompat() == Call.STATE_HOLDING }
+ fun getConferenceCalls(): List {
+ return calls.find { it.isConference() }?.children ?: emptyList()
}
fun accept() {
@@ -134,11 +161,10 @@ class CallManager {
return !isOnHold
}
- val isConference: Boolean
- get() = call?.details?.hasProperty(Call.Details.PROPERTY_CONFERENCE) ?: false
-
fun swap() {
- getSecondaryCall()?.unhold()
+ if (calls.size > 1) {
+ calls.find { it.getStateCompat() == Call.STATE_HOLDING }?.unhold()
+ }
}
fun merge() {
@@ -166,85 +192,15 @@ class CallManager {
call?.playDtmfTone(c)
call?.stopDtmfTone()
}
-
- fun getCallContact(context: Context, callback: (CallContact?) -> Unit) {
- return getCallContact(context, call, callback)
- }
-
- fun getCallContact(context: Context, call: Call?, callback: (CallContact) -> Unit) {
- val privateCursor = context.getMyContactsCursor(false, true)
- ensureBackgroundThread {
- val callContact = CallContact("", "", "", "")
- val handle = try {
- call?.details?.handle?.toString()
- } catch (e: NullPointerException) {
- null
- }
-
- if (handle == null) {
- callback(callContact)
- return@ensureBackgroundThread
- }
-
- val uri = Uri.decode(handle)
- if (uri.startsWith("tel:")) {
- val number = uri.substringAfter("tel:")
- SimpleContactsHelper(context).getAvailableContacts(false) { contacts ->
- val privateContacts = MyContactsContentProvider.getSimpleContacts(context, privateCursor)
- if (privateContacts.isNotEmpty()) {
- contacts.addAll(privateContacts)
- }
-
- val contactsWithMultipleNumbers = contacts.filter { it.phoneNumbers.size > 1 }
- val numbersToContactIDMap = HashMap()
- contactsWithMultipleNumbers.forEach { contact ->
- contact.phoneNumbers.forEach { phoneNumber ->
- numbersToContactIDMap[phoneNumber.value] = contact.contactId
- numbersToContactIDMap[phoneNumber.normalizedNumber] = contact.contactId
- }
- }
-
- callContact.number = number
- val contact = contacts.firstOrNull { it.doesHavePhoneNumber(number) }
- if (contact != null) {
- callContact.name = contact.name
- callContact.photoUri = contact.photoUri
-
- if (contact.phoneNumbers.size > 1) {
- val specificPhoneNumber = contact.phoneNumbers.firstOrNull { it.value == number }
- if (specificPhoneNumber != null) {
- callContact.numberLabel = context.getPhoneNumberTypeText(specificPhoneNumber.type, specificPhoneNumber.label)
- }
- }
- } else {
- callContact.name = number
- }
- callback(callContact)
- }
- }
- }
- }
-
- fun getCallDuration(): Int {
- return if (call != null) {
- val connectTimeMillis = call!!.details.connectTimeMillis
- if (connectTimeMillis == 0L) {
- return 0
- }
- ((System.currentTimeMillis() - connectTimeMillis) / 1000).toInt()
- } else {
- 0
- }
- }
}
}
interface CallManagerListener {
- fun onStateChanged(call: Call, state: Int)
+ fun onStateChanged()
fun onPrimaryCallChanged(call: Call)
}
sealed class PhoneState
object NoCall : PhoneState()
-class SingleCall(val call: Call?) : PhoneState()
+class SingleCall(val call: Call) : PhoneState()
class TwoCalls(val active: Call, val onHold: Call) : PhoneState()
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallNotificationManager.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallNotificationManager.kt
index 324123b4..ecd286c6 100644
--- a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallNotificationManager.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallNotificationManager.kt
@@ -28,7 +28,7 @@ class CallNotificationManager(private val context: Context) {
@SuppressLint("NewApi")
fun setupNotification() {
- CallManager.getCallContact(context.applicationContext) { callContact ->
+ getCallContact(context.applicationContext, CallManager.getPrimaryCall()) { callContact ->
val callContactAvatar = callContactAvatarHelper.getCallContactAvatar(callContact)
val callState = CallManager.getState()
val isHighPriority = context.powerManager.isInteractive && callState == Call.STATE_RINGING
diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt
index b6ba9283..43315238 100644
--- a/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt
@@ -4,15 +4,13 @@ import android.app.KeyguardManager
import android.content.Context
import android.telecom.Call
import android.telecom.InCallService
-import android.util.Log
import com.simplemobiletools.dialer.activities.CallActivity
import com.simplemobiletools.dialer.extensions.getStateCompat
import com.simplemobiletools.dialer.extensions.isOutgoing
import com.simplemobiletools.dialer.extensions.powerManager
import com.simplemobiletools.dialer.helpers.CallManager
import com.simplemobiletools.dialer.helpers.CallNotificationManager
-
-const val TAG = "SimpleDialer:CallService"
+import com.simplemobiletools.dialer.helpers.NoCall
class CallService : InCallService() {
private val callNotificationManager by lazy { CallNotificationManager(this) }
@@ -45,18 +43,18 @@ class CallService : InCallService() {
override fun onCallRemoved(call: Call) {
super.onCallRemoved(call)
- Log.d(TAG, "onCallRemoved: $call")
call.unregisterCallback(callListener)
+ val wasPrimaryCall = call == CallManager.getPrimaryCall()
CallManager.onCallRemoved(call)
- if (CallManager.calls.isEmpty()) {
- CallManager.call = null
+ if (CallManager.getPhoneState() == NoCall) {
CallManager.inCallService = null
callNotificationManager.cancelNotification()
} else {
callNotificationManager.setupNotification()
- startActivity(CallActivity.getStartIntent(this))
+ if (wasPrimaryCall) {
+ startActivity(CallActivity.getStartIntent(this))
+ }
}
- Log.d(TAG, "onCallRemoved: calls=${CallManager.calls.size}")
}
override fun onDestroy() {
diff --git a/app/src/main/res/drawable/ic_call_split_vector.xml b/app/src/main/res/drawable/ic_call_split_vector.xml
new file mode 100644
index 00000000..5afba98d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_call_split_vector.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_call.xml b/app/src/main/res/layout/activity_call.xml
index bf927509..52e3ae73 100644
--- a/app/src/main/res/layout/activity_call.xml
+++ b/app/src/main/res/layout/activity_call.xml
@@ -207,9 +207,9 @@
android:contentDescription="@string/hold_call"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_pause_vector"
- app:layout_constraintEnd_toStartOf="@id/call_add"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/call_toggle_speaker" />
+ app:layout_constraintEnd_toEndOf="@+id/call_toggle_microphone"
+ app:layout_constraintStart_toStartOf="@+id/call_toggle_microphone"
+ app:layout_constraintTop_toBottomOf="@+id/call_toggle_microphone" />
+ app:layout_constraintEnd_toEndOf="@+id/call_dialpad"
+ app:layout_constraintStart_toStartOf="@+id/call_dialpad"
+ app:layout_constraintTop_toBottomOf="@+id/call_dialpad"
+ tools:visibility="visible" />
+ app:layout_constraintStart_toStartOf="@+id/call_toggle_microphone"
+ app:layout_constraintTop_toBottomOf="@+id/call_toggle_microphone" />
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_conference_call.xml b/app/src/main/res/layout/item_conference_call.xml
new file mode 100644
index 00000000..0833746b
--- /dev/null
+++ b/app/src/main/res/layout/item_conference_call.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+