Bug 717158 - 'B2G telephony: unknown (outgoing) call index is assumed to be incoming later'. r=cjones.
authorBen Turner <bent.mozilla@gmail.com>
Wed, 11 Jan 2012 18:17:26 -0800
changeset 84326 a9eb2cfdebd81907d14f0a4f35c3cfd2679a1bad
parent 84325 4abbedf5b4ca3e532f84c7c020fa2629f6e542e1
child 84327 4c0a14d58397f07543c80262ccd81319e1807fe7
push idunknown
push userunknown
push dateunknown
reviewerscjones
bugs717158
milestone12.0a1
Bug 717158 - 'B2G telephony: unknown (outgoing) call index is assumed to be incoming later'. r=cjones.
dom/telephony/Telephony.cpp
dom/telephony/TelephonyCall.cpp
dom/telephony/TelephonyCall.h
dom/telephony/TelephonyCommon.h
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -197,16 +197,27 @@ DOMCI_DATA(Telephony, Telephony)
 
 NS_IMPL_ISUPPORTS1(Telephony::TelephoneCallback, nsITelephoneCallback)
 
 NS_IMETHODIMP
 Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
 {
   NS_ENSURE_ARG(!aNumber.IsEmpty());
 
+  for (PRUint32 index = 0; index < mCalls.Length(); index++) {
+    const nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
+    if (tempCall->IsOutgoing() &&
+        tempCall->CallState() < nsITelephone::CALL_STATE_CONNECTED) {
+      // One call has been dialed already and we only support one outgoing call
+      // at a time.
+      NS_WARNING("Only permitted to dial one call at a time!");
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+  }
+
   nsresult rv = mTelephone->Dial(aNumber);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<TelephonyCall> call =
     TelephonyCall::Create(this, aNumber, nsITelephone::CALL_STATE_DIALING);
   NS_ASSERTION(call, "This should never fail!");
 
   NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
@@ -352,32 +363,59 @@ Telephony::SendTones(const nsAString& aT
 }
 
 NS_IMPL_EVENT_HANDLER(Telephony, incoming)
 
 NS_IMETHODIMP
 Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
                             const nsAString& aNumber)
 {
-  // If we already know about this call then just update its state.
+  NS_ASSERTION(aCallIndex != kOutgoingPlaceholderCallIndex,
+               "This should never happen!");
+
+  nsRefPtr<TelephonyCall> modifiedCall;
+  nsRefPtr<TelephonyCall> outgoingCall;
+
   for (PRUint32 index = 0; index < mCalls.Length(); index++) {
     nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
-    if (tempCall->CallIndex() == aCallIndex) {
-      // This can call back and modify the array... Grab a real ref here.
-      nsRefPtr<TelephonyCall> call = tempCall;
+    if (tempCall->CallIndex() == kOutgoingPlaceholderCallIndex) {
+      NS_ASSERTION(!outgoingCall, "More than one outgoing call not supported!");
+      NS_ASSERTION(tempCall->CallState() == nsITelephone::CALL_STATE_DIALING,
+                   "Something really wrong here!");
+      // Stash this for later, we may need it if aCallIndex doesn't match one of
+      // our other calls.
+      outgoingCall = tempCall;
+    } else if (tempCall->CallIndex() == aCallIndex) {
+      // We already know about this call so just update its state.
+      modifiedCall = tempCall;
+      outgoingCall = nsnull;
+      break;
+    }
+  }
 
-      // See if this should replace our current active call.
-      if (aCallState == nsITelephone::CALL_STATE_CONNECTED) {
-        SwitchActiveCall(call);
-      }
+  // If nothing matched above and the call state isn't incoming but we do have
+  // an outgoing call then we must be seeing a status update for our outgoing
+  // call.
+  if (!modifiedCall &&
+      aCallState != nsITelephone::CALL_STATE_INCOMING &&
+      outgoingCall) {
+    outgoingCall->UpdateCallIndex(aCallIndex);
+    modifiedCall.swap(outgoingCall);
+  }
 
-      // Change state.
-      call->ChangeState(aCallState);
-      return NS_OK;
+  if (modifiedCall) {
+    // Change state.
+    modifiedCall->ChangeState(aCallState);
+
+    // See if this should replace our current active call.
+    if (aCallState == nsITelephone::CALL_STATE_CONNECTED) {
+      SwitchActiveCall(modifiedCall);
     }
+
+    return NS_OK;
   }
 
   // Didn't know anything about this call before now, must be incoming.
   NS_ASSERTION(aCallState == nsITelephone::CALL_STATE_INCOMING,
                "Serious logic problem here!");
 
   nsRefPtr<TelephonyCall> call =
     TelephonyCall::Create(this, aNumber, aCallState, aCallIndex);
--- a/dom/telephony/TelephonyCall.cpp
+++ b/dom/telephony/TelephonyCall.cpp
@@ -110,16 +110,20 @@ TelephonyCall::ChangeStateInternal(PRUin
       break;
     default:
       NS_NOTREACHED("Unknown state!");
   }
 
   mState = stateString;
   mCallState = aCallState;
 
+  if (aCallState == nsITelephone::CALL_STATE_DIALING) {
+    mOutgoing = true;
+  }
+
   if (aCallState == nsITelephone::CALL_STATE_DISCONNECTED) {
     NS_ASSERTION(mLive, "Should be live!");
     mTelephony->RemoveCall(this);
     mLive = false;
   } else if (!mLive) {
     mTelephony->AddCall(this);
     mLive = true;
   }
--- a/dom/telephony/TelephonyCall.h
+++ b/dom/telephony/TelephonyCall.h
@@ -65,27 +65,28 @@ class TelephonyCall : public nsDOMEventT
   nsRefPtr<Telephony> mTelephony;
 
   nsString mNumber;
   nsString mState;
 
   PRUint32 mCallIndex;
   PRUint16 mCallState;
   bool mLive;
+  bool mOutgoing;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMTELEPHONYCALL
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetWrapperCache::)
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TelephonyCall,
                                            nsDOMEventTargetWrapperCache)
 
   static already_AddRefed<TelephonyCall>
   Create(Telephony* aTelephony, const nsAString& aNumber, PRUint16 aCallState,
-         PRUint32 aCallIndex = PR_UINT32_MAX);
+         PRUint32 aCallIndex = kOutgoingPlaceholderCallIndex);
 
   nsIDOMEventTarget*
   ToIDOMEventTarget() const
   {
     return static_cast<nsDOMEventTargetWrapperCache*>(
              const_cast<TelephonyCall*>(this));
   }
 
@@ -102,26 +103,40 @@ public:
   }
 
   PRUint32
   CallIndex() const
   {
     return mCallIndex;
   }
 
+  void
+  UpdateCallIndex(PRUint32 aCallIndex)
+  {
+    NS_ASSERTION(mCallIndex == kOutgoingPlaceholderCallIndex,
+                 "Call index should not be set!");
+    mCallIndex = aCallIndex;
+  }
+
   PRUint16
   CallState() const
   {
     return mCallState;
   }
 
+  bool
+  IsOutgoing() const
+  {
+    return mOutgoing;
+  }
+
 private:
   TelephonyCall()
-  : mCallIndex(PR_UINT32_MAX), mCallState(nsITelephone::CALL_STATE_UNKNOWN),
-    mLive(false)
+  : mCallIndex(kOutgoingPlaceholderCallIndex),
+    mCallState(nsITelephone::CALL_STATE_UNKNOWN), mLive(false), mOutgoing(false)
   { }
 
   ~TelephonyCall()
   { }
 
   void
   ChangeStateInternal(PRUint16 aCallState, bool aFireEvents);
 };
--- a/dom/telephony/TelephonyCommon.h
+++ b/dom/telephony/TelephonyCommon.h
@@ -55,14 +55,18 @@
 #define USING_TELEPHONY_NAMESPACE \
   using namespace mozilla::dom::telephony;
 
 class nsIDOMTelephony;
 class nsIDOMTelephonyCall;
 
 BEGIN_TELEPHONY_NAMESPACE
 
+enum {
+  kOutgoingPlaceholderCallIndex = PR_UINT32_MAX
+};
+
 class Telephony;
 class TelephonyCall;
 
 END_TELEPHONY_NAMESPACE
 
 #endif // mozilla_dom_telephony_telephonycommon_h__