Use callId for all call commands.

Change-Id: I988643cdaaffb1abf2689844d119d5e382b9791b
diff --git a/src/com/android/phone/CallCommandService.java b/src/com/android/phone/CallCommandService.java
index ff12063..f216a48 100644
--- a/src/com/android/phone/CallCommandService.java
+++ b/src/com/android/phone/CallCommandService.java
@@ -20,6 +20,8 @@
 import android.util.Log;
 
 import com.android.internal.telephony.CallManager;
+import com.android.phone.CallModeler.CallResult;
+import com.android.services.telephony.common.Call;
 import com.android.services.telephony.common.ICallCommandService;
 
 /**
@@ -30,12 +32,14 @@
 
     private static final String TAG = CallCommandService.class.getSimpleName();
 
-    private Context mContext;
-    private CallManager mCallManager;
+    private final Context mContext;
+    private final CallManager mCallManager;
+    private final CallModeler mCallModeler;
 
-    public CallCommandService(Context context, CallManager callManager) {
+    public CallCommandService(Context context, CallManager callManager, CallModeler callModeler) {
         mContext = context;
         mCallManager = callManager;
+        mCallModeler = callModeler;
     }
 
     /**
@@ -44,8 +48,10 @@
     @Override
     public void answerCall(int callId) {
         try {
-            // TODO(klp): Change to using the callId and logic from InCallScreen::internalAnswerCall
-            PhoneUtils.answerCall(mCallManager.getFirstActiveRingingCall());
+            CallResult result = mCallModeler.getCallWithId(callId);
+            if (result != null) {
+                PhoneUtils.answerCall(result.getConnection().getCall());
+            }
         } catch (Exception e) {
             Log.e(TAG, "Error during answerCall().", e);
         }
@@ -57,8 +63,10 @@
     @Override
     public void rejectCall(int callId) {
         try {
-            // TODO(klp): Change to using the callId
-            PhoneUtils.hangupRingingCall(mCallManager.getFirstActiveRingingCall());
+            CallResult result = mCallModeler.getCallWithId(callId);
+            if (result != null) {
+                PhoneUtils.hangupRingingCall(result.getConnection().getCall());
+            }
         } catch (Exception e) {
             Log.e(TAG, "Error during rejectCall().", e);
         }
@@ -67,8 +75,13 @@
     @Override
     public void disconnectCall(int callId) {
         try {
-            // TODO(klp): Change to using the callId
-            PhoneUtils.hangup(mCallManager);
+            CallResult result = mCallModeler.getCallWithId(callId);
+            if (result != null) {
+                int state = result.getCall().getState();
+                if (Call.State.ACTIVE == state || Call.State.ONHOLD == state) {
+                    result.getConnection().getCall().hangup();
+                }
+            }
         } catch (Exception e) {
             Log.e(TAG, "Error during disconnectCall().", e);
         }
@@ -77,8 +90,15 @@
     @Override
     public void hold(int callId, boolean hold) {
         try {
-            // TODO(klp): Change to use the callId/hold
-            PhoneUtils.switchHoldingAndActive(mCallManager.getFirstActiveBgCall());
+            CallResult result = mCallModeler.getCallWithId(callId);
+            if (result != null) {
+                int state = result.getCall().getState();
+                if (hold && Call.State.ACTIVE == state ) {
+                    PhoneUtils.switchHoldingAndActive(mCallManager.getFirstActiveBgCall());
+                } else if (!hold && Call.State.ONHOLD == state) {
+                    PhoneUtils.switchHoldingAndActive(result.getConnection().getCall());
+                }
+            }
         } catch (Exception e) {
             Log.e(TAG, "Error trying to place call on hold.", e);
         }
diff --git a/src/com/android/phone/CallModeler.java b/src/com/android/phone/CallModeler.java
index ee96dbf..01f571f 100644
--- a/src/com/android/phone/CallModeler.java
+++ b/src/com/android/phone/CallModeler.java
@@ -34,6 +34,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -116,6 +117,16 @@
         return retval;
     }
 
+    public CallResult getCallWithId(int callId) {
+        // max 8 connections, so this should be fast even through we are traversing the entire map.
+        for (Entry<Connection, Call> entry : mCallMap.entrySet()) {
+            if (entry.getValue().getCallId() == callId) {
+                return new CallResult(entry.getValue(), entry.getKey());
+            }
+        }
+        return null;
+    }
+
     private void onNewRingingConnection(AsyncResult r) {
         final Connection conn = (Connection) r.result;
         final Call call = getCallFromConnection(conn, true);
@@ -249,4 +260,25 @@
         void onDisconnect(Call call);
         void onUpdate(List<Call> calls, boolean fullUpdate);
     }
+
+    /**
+     * Result class for accessing a call by connection.
+     */
+    public static class CallResult {
+        public Call mCall;
+        public Connection mConnection;
+
+        private CallResult(Call call, Connection connection) {
+            mCall = call;
+            mConnection = connection;
+        }
+
+        public Call getCall() {
+            return mCall;
+        }
+
+        public Connection getConnection() {
+            return mConnection;
+        }
+    }
 }
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 36687ce..650e2eb 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -542,12 +542,12 @@
             // Monitors call activity from the telephony layer
             callStateMonitor = new CallStateMonitor(mCM);
 
-            // Service used by in-call UI to control calls
-            callCommandService = new CallCommandService(this, mCM);
-
             // Creates call models for use with CallHandlerService.
             callModeler = new CallModeler(callStateMonitor, mCM);
 
+            // Service used by in-call UI to control calls
+            callCommandService = new CallCommandService(this, mCM, callModeler);
+
             // Sends call state to the UI
             callHandlerServiceProxy = new CallHandlerServiceProxy(this, callModeler,
                     callCommandService);