Adding call state to the Call object.

Change-Id: I2369a040a41cc37488a23dda8a72d4456248ac62
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index ef72cd0..587214a 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -16,6 +16,9 @@
 
 package com.android.telecomm;
 
+import android.telecomm.CallInfo;
+import android.telecomm.CallState;
+
 import java.util.Date;
 
 /**
@@ -30,6 +33,11 @@
      */
     private final String mId;
 
+    /**
+     * The state of the call.
+     */
+    private CallState mState;
+
     /** The handle with which to establish this call. */
     private final String mHandle;
 
@@ -45,6 +53,11 @@
     private final Date mCreationTime;
 
     /**
+     * Read-only and parcelable version of this call.
+     */
+    private CallInfo mCallInfo;
+
+    /**
      * Persists the specified parameters and initializes the new instance.
      *
      * @param handle The handle to dial.
@@ -53,10 +66,9 @@
     Call(String handle, ContactInfo contactInfo) {
         // TODO(gilad): Pass this in etc.
         mId = "dummy";
-
+        mState = CallState.NEW;
         mHandle = handle;
         mContactInfo = contactInfo;
-
         mCreationTime = new Date();
     }
 
@@ -64,6 +76,21 @@
         return mId;
     }
 
+    CallState getState() {
+        return mState;
+    }
+
+    /**
+     * Sets the call state. Although there exists the notion of appropriate state transitions
+     * (see {@link CallState}), in practice those expectations break down when cellular systems
+     * misbehave and they do this very often. The result is that we do not enforce state transitions
+     * and instead keep the code resilient to unexpected state changes.
+     */
+    void setState(CallState state) {
+        mState = state;
+        clearCallInfo();
+    }
+
     String getHandle() {
         return mHandle;
     }
@@ -79,4 +106,21 @@
     long getAgeInMilliseconds() {
         return new Date().getTime() - mCreationTime.getTime();
     }
+
+    /**
+     * @return An object containing read-only information about this call.
+     */
+    CallInfo toCallInfo() {
+        if (mCallInfo == null) {
+            mCallInfo = new CallInfo(mId, mState, mHandle);
+        }
+        return mCallInfo;
+    }
+
+    /**
+     * Resets the cached read-only version of this call.
+     */
+    private void clearCallInfo() {
+        mCallInfo = null;
+    }
 }
diff --git a/src/com/android/telecomm/OutgoingCallProcessor.java b/src/com/android/telecomm/OutgoingCallProcessor.java
index 4059ad6..e7b0ff3 100644
--- a/src/com/android/telecomm/OutgoingCallProcessor.java
+++ b/src/com/android/telecomm/OutgoingCallProcessor.java
@@ -59,12 +59,6 @@
     private final Call mCall;
 
     /**
-     * The (read-only) object derived from mCall above to pass through outside of the Telecomm
-     * package.
-     */
-    private final CallInfo mCallInfo;
-
-    /**
      * The duplicate-free list of currently-available call-service IDs.
      */
     private final List<String> mCallServiceIds = Lists.newArrayList();
@@ -115,7 +109,6 @@
         Preconditions.checkNotNull(selectors);
 
         mCall = call;
-        mCallInfo = new CallInfo(call.getId(), call.getHandle());
         mSelectors = selectors;
         mSwitchboard = switchboard;
 
@@ -167,7 +160,7 @@
             ICallServiceSelector selector = mSelectorIterator.next();
             ICallServiceSelectionResponse.Stub response = createSelectionResponse();
             try {
-                selector.select(mCallInfo, mCallServiceIds, response);
+                selector.select(mCall.toCallInfo(), mCallServiceIds, response);
             } catch (RemoteException e) {
                 attemptNextSelector();
             }
@@ -225,8 +218,7 @@
             ICallService callService = mCallServicesById.get(id);
             if (callService != null) {
                 try {
-                    // TODO(gilad): Refactor to pass a CallInfo object instead.
-                    callService.call(mCallInfo);
+                    callService.call(mCall.toCallInfo());
                 } catch (RemoteException e) {
                     // TODO(gilad): Log etc.
                     attemptNextCallService();