Adds State to the Call Objects.

Also, updates the onUpdate method of ICallHandlerService to get called
when a call changes state.

Change-Id: I8fe830cdd8c7f4b92e985c518b5e1a60d6552284
diff --git a/src/com/android/phone/CallHandlerServiceProxy.java b/src/com/android/phone/CallHandlerServiceProxy.java
index c4d1468..24641c0 100644
--- a/src/com/android/phone/CallHandlerServiceProxy.java
+++ b/src/com/android/phone/CallHandlerServiceProxy.java
@@ -32,6 +32,8 @@
 import com.android.services.telephony.common.ICallHandlerService;
 import com.android.services.telephony.common.ICallCommandService;
 
+import java.util.List;
+
 /**
  * This class is responsible for passing through call state changes to the CallHandlerService.
  */
@@ -82,6 +84,17 @@
         }
     }
 
+    @Override
+    public void onUpdate(List<Call> calls) {
+        if (mCallHandlerService != null) {
+            try {
+                mCallHandlerService.onUpdate(calls);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Remote exception handling onUpdate", e);
+            }
+        }
+    }
+
     /**
      * Sets up the connection with ICallHandlerService
      */
diff --git a/src/com/android/phone/CallModeler.java b/src/com/android/phone/CallModeler.java
index b6504eb..5d735a4 100644
--- a/src/com/android/phone/CallModeler.java
+++ b/src/com/android/phone/CallModeler.java
@@ -25,8 +25,11 @@
 import android.os.Message;
 import android.util.Log;
 
+import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.services.telephony.common.Call;
+import com.android.services.telephony.common.Call.State;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -68,12 +71,14 @@
     private static final int CALL_ID_START_VALUE = 1;
 
     private CallStateMonitor mCallStateMonitor;
+    private CallManager mCallManager;
     private HashMap<Connection, Call> mCallMap = Maps.newHashMap();
     private List<Listener> mListeners = Lists.newArrayList();
     private AtomicInteger mNextCallId = new AtomicInteger(CALL_ID_START_VALUE);
 
-    public CallModeler(CallStateMonitor callStateMonitor) {
+    public CallModeler(CallStateMonitor callStateMonitor, CallManager callManager) {
         mCallStateMonitor = callStateMonitor;
+        mCallManager = callManager;
 
         mCallStateMonitor.addListener(this);
     }
@@ -104,6 +109,7 @@
     private void onNewRingingConnection(AsyncResult r) {
         final Connection conn = (Connection) r.result;
         final Call call = getCallFromConnection(conn, true);
+        call.setState(Call.State.INCOMING);
 
         if (call != null) {
             for (Listener l : mListeners) {
@@ -125,7 +131,63 @@
         }
     }
 
+    /**
+     * Called when the phone state changes.
+     * The telephony layer maintains a certain amount of preallocated telephony::Call instances
+     * that change throughout the lifetime of the phone.  When we get an alert that the state
+     * changes, we need to go through the telephony::Calls and determine what changed.
+     */
     private void onPhoneStateChanged(AsyncResult r) {
+        final List<com.android.internal.telephony.Call> telephonyCalls = Lists.newArrayList();
+        telephonyCalls.addAll(mCallManager.getRingingCalls());
+        telephonyCalls.addAll(mCallManager.getForegroundCalls());
+        telephonyCalls.addAll(mCallManager.getBackgroundCalls());
+
+        final List<Call> updatedCalls = Lists.newArrayList();
+
+        // Cycle through all the Connections on all the Calls. Update our Call objects
+        // to reflect any new state and send the updated Call objects to the handler service.
+        for (com.android.internal.telephony.Call telephonyCall : telephonyCalls) {
+            final int state = translateStateFromTelephony(telephonyCall.getState());
+
+            for (Connection connection : telephonyCall.getConnections()) {
+                final Call call = getCallFromConnection(connection, true);
+
+                if (call.getState() != state) {
+                    call.setState(state);
+                    updatedCalls.add(call);
+                }
+            }
+        }
+
+        for (Listener l : mListeners) {
+            l.onUpdate(updatedCalls);
+        }
+    }
+
+    private int translateStateFromTelephony(com.android.internal.telephony.Call.State teleState) {
+        int retval = State.IDLE;
+        switch (teleState) {
+            case ACTIVE:
+                retval = State.ACTIVE;
+                break;
+            case INCOMING:
+                retval = State.INCOMING;
+                break;
+            case DIALING:
+            case ALERTING:
+                retval = State.DIALING;
+                break;
+            case WAITING:
+                retval = State.CALL_WAITING;
+                break;
+            case HOLDING:
+                retval = State.ONHOLD;
+                break;
+            default:
+        }
+
+        return retval;
     }
 
     /**
@@ -168,5 +230,6 @@
     public interface Listener {
         void onNewCall(Call call);
         void onDisconnect(Call call);
+        void onUpdate(List<Call> calls);
     }
 }
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index d96bfce..36687ce 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -546,7 +546,7 @@
             callCommandService = new CallCommandService(this, mCM);
 
             // Creates call models for use with CallHandlerService.
-            callModeler = new CallModeler(callStateMonitor);
+            callModeler = new CallModeler(callStateMonitor, mCM);
 
             // Sends call state to the UI
             callHandlerServiceProxy = new CallHandlerServiceProxy(this, callModeler,