From b2d5e04292cdd38c01e34eb7ea2ac3b059ca6c73 Mon Sep 17 00:00:00 2001 From: Sandeep Kunta Date: Mon, 1 Sep 2014 17:18:43 +0530 Subject: MSIM: Add support for DSDA. Add support to show calls from both subscriptions in a tabbed view format to user. when ever user switches sub, inform telecomm service that subscription is switched. Change-Id: I3bea71501ce159e189f75db58e710ffc94e8137c --- src/com/android/incallui/CallList.java | 208 +++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) (limited to 'src/com/android/incallui/CallList.java') diff --git a/src/com/android/incallui/CallList.java b/src/com/android/incallui/CallList.java index c0014bdf..5b1855d7 100644 --- a/src/com/android/incallui/CallList.java +++ b/src/com/android/incallui/CallList.java @@ -24,8 +24,12 @@ import android.telecom.PhoneAccount; import com.android.contacts.common.testing.NeededForTesting; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import android.telecom.PhoneAccountHandle; +import android.telephony.SubscriptionManager; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -46,6 +50,8 @@ public class CallList { private static final int DISCONNECTED_CALL_LONG_TIMEOUT_MS = 5000; private static final int EVENT_DISCONNECTED_TIMEOUT = 1; + private static final int EVENT_NOTIFY_CHANGE = 2; + private static CallList sInstance = new CallList(); @@ -63,6 +69,9 @@ public class CallList { .newHashMap(); private final Set mPendingDisconnectCalls = Collections.newSetFromMap( new ConcurrentHashMap(8, 0.9f, 1)); + private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private final ArrayList mActiveSubChangeListeners = + Lists.newArrayList(); /** * Static singleton accessor method. @@ -102,6 +111,18 @@ public class CallList { } } + int getPhoneId(int subId) { + int phoneId = SubscriptionManager.getPhoneId(subId); + if (phoneId >= InCallServiceImpl.sPhoneCount || phoneId < 0) { + phoneId = 0; + } + return phoneId; + } + + int[] getSubId(int phoneId) { + return SubscriptionManager.getSubId(phoneId); + } + /** * Called when a single call disconnects. */ @@ -119,6 +140,18 @@ public class CallList { * Called when a single call has changed. */ public void onIncoming(Call call, List textMessages) { + Log.d(this, "onIncoming - " + call); + + // Update active subscription from call object. it will be set by + // Telecomm service for incoming call and whenever active sub changes. + if (call.mIsActiveSub) { + int sub = Integer.parseInt(call.getAccountHandle().getId()); + Log.d(this, "onIncoming - sub:" + sub + " mSubId:" + mSubId); + if (sub != mSubId) { + setActiveSubId(sub); + } + } + if (updateCallInMap(call)) { Log.i(this, "onIncoming - " + call); } @@ -140,6 +173,19 @@ public class CallList { */ public void onUpdate(Call call) { Trace.beginSection("onUpdate"); + PhoneAccountHandle ph = call.getAccountHandle(); + Log.d(this, "onUpdate - " + call + " ph:" + ph); + try { + if (call.mIsActiveSub && ph != null) { + int sub = Integer.parseInt(ph.getId()); + Log.d(this, "onUpdate - sub:" + sub + " mSubId:" + mSubId); + if(sub != mSubId) { + setActiveSubId(sub); + } + } + } catch (NumberFormatException e) { + Log.w(this,"Sub Id is not a number " + e); + } onUpdateCall(call); notifyGenericListeners(); Trace.endSection(); @@ -356,6 +402,13 @@ public class CallList { * TODO: Improve this logic to sort by call time. */ public Call getCallWithState(int state, int positionToFind) { + // if DSDA is enabled call getCallWithState with active subscription. + if (state != Call.State.SELECT_PHONE_ACCOUNT && getActiveSubId() + != SubscriptionManager.INVALID_SUBSCRIPTION_ID + && InCallServiceImpl.isDsdaEnabled()) { + return getCallWithState(state, positionToFind, getActiveSubId()); + } + Call retval = null; int position = 0; for (Call call : mCallById.values()) { @@ -559,6 +612,13 @@ public class CallList { Log.d(this, "EVENT_DISCONNECTED_TIMEOUT ", msg.obj); finishDisconnectedCall((Call) msg.obj); break; + case EVENT_NOTIFY_CHANGE: + Log.d(this, "EVENT_NOTIFY_CHANGE: "); + notifyGenericListeners(); + for (ActiveSubChangeListener listener : mActiveSubChangeListeners) { + listener.onActiveSubChanged(getActiveSubId()); + } + break; default: Log.wtf(this, "Message not expected: " + msg.what); break; @@ -612,4 +672,152 @@ public class CallList { */ public void onSessionModificationStateChange(int sessionModificationState); } + + /** + * Called when active subscription changes. + */ + void onActiveSubChanged(int activeSub) { + Log.d(this, "onActiveSubChanged = " + activeSub); + if (hasAnyLiveCall(activeSub)) { + setActiveSubId(activeSub); + } + } + + int getActiveSubId() { + return mSubId; + } + + /** + * Called to update the latest active subscription id, and also it + * notifies the registred clients about subscription change information. + */ + void setActiveSubId(int subId) { + if (subId != mSubId) { + Log.d(this, "setActiveSubId, oldActiveSubId = " + mSubId + + " newActiveSubId = " + subId); + mSubId = subId; + final Message msg = mHandler.obtainMessage(EVENT_NOTIFY_CHANGE, null); + mHandler.sendMessage(msg); + } + } + + /** + * Returns true, if any voice call is ACTIVE on the provided subscription. + */ + boolean hasAnyLiveCall(int subId) { + for (Call call : mCallById.values()) { + PhoneAccountHandle ph = call.getAccountHandle(); + try { + if (!isCallDead(call) && ph != null && (Integer.parseInt(ph.getId()) == subId)) { + Log.d(this, "hasAnyLiveCall sub = " + subId); + return true; + } + } catch (NumberFormatException e) { + Log.w(this,"Sub Id is not a number " + e); + } + } + Log.d(this, "no active call "); + return false; + } + + /** + * Returns true, if any call is ACTIVE + */ + boolean hasAnyLiveCall() { + for (Call call : mCallById.values()) { + if (!isCallDead(call)) { + Log.d(this, "hasAnyLiveCall call = " + call); + return true; + } + } + Log.d(this, "no active call "); + return false; + } + + /** + * This method checks whether any other subscription currently has active voice + * call other than current active subscription, if yes it makes that other + * subscription as active subscription i.e user visible subscription. + * @param retainLch whether to retain the LCH state of the other active sub + */ + boolean switchToOtherActiveSub() { + int activeSub = getActiveSubId(); + boolean subSwitched = false; + + for (int i = 0; i < InCallServiceImpl.sPhoneCount; i++) { + int[] subId = getSubId(i); + if ((subId[0] != activeSub) && hasAnyLiveCall(subId[0])) { + Log.d(this, "switchToOtherActiveSub, subId = " + subId[0]); + subSwitched = true; + TelecomAdapter.getInstance().switchToOtherActiveSub( + String.valueOf(subId[0])); + setActiveSubId(subId[0]); + break; + } + } + return subSwitched; + } + + /** + * Method to check if there is any live call in a sub other than the one supplied. + * @param currentSub The subscription to exclude while checking for active calls. + */ + boolean isAnyOtherSubActive(int currentSub) { + boolean result = false; + if(!InCallServiceImpl.isDsdaEnabled()) { + return false; + } + + for (int phoneId = 0; phoneId < InCallServiceImpl.sPhoneCount; + phoneId++) { + int[] subId = getSubId(phoneId); + + if ((subId[0] != currentSub) && hasAnyLiveCall(subId[0])) { + Log.d(this, "Live call found on another sub = " + subId[0]); + result = true; + break; + } + } + return result; + } + + /** + * Returns the [position]th call which belongs to provided subscription and + * found in the call map with the specified state. + */ + Call getCallWithState(int state, int positionToFind, int subId) { + Call retval = null; + int position = 0; + for (Call call : mCallById.values()) { + PhoneAccountHandle ph = call.getAccountHandle(); + try { + if ((call.getState() == state) && ((ph == null) || + (ph != null && (Integer.parseInt(ph.getId()) == subId)))) { + if (position >= positionToFind) { + retval = call; + break; + } else { + position++; + } + } + } catch (NumberFormatException e) { + Log.w(this,"Sub Id is not a number " + e); + } + } + return retval; + } + + void addActiveSubChangeListener(ActiveSubChangeListener listener) { + Preconditions.checkNotNull(listener); + mActiveSubChangeListeners.add(listener); + } + + void removeActiveSubChangeListener(ActiveSubChangeListener listener) { + Preconditions.checkNotNull(listener); + mActiveSubChangeListeners.remove(listener); + } + + interface ActiveSubChangeListener { + public void onActiveSubChanged(int subId); + } } -- cgit v1.2.3