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 87145 a9eb2cfdebd81907d14f0a4f35c3cfd2679a1bad
parent 87144 4abbedf5b4ca3e532f84c7c020fa2629f6e542e1
child 87146 4c0a14d58397f07543c80262ccd81319e1807fe7
push id129
push userffxbld
push dateFri, 20 Apr 2012 19:40:49 +0000
treeherdermozilla-release@5bcfa0da3be9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs717158
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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__