Simplify deallocation/unbinding of services.

Call counts of call services and selectors are kept current during call
and during the outgoing call process. This allows us to unbind simply
when the call-count goes down to 0.

A second optimization that can be made is to remove associated-call
counts from ServiceBinder and use the callIdMapper to maintain counts of
the associated calls. This binds the call count to the mapper items,
however there are two small roadblocks:
1. It isn't as easy to deal with the replace() scenario, but doable
2. The caller-ID mapper implementations between CS and selectors are
   separate and it's nice to keep a single associated count implementation
   for all ServiceBinders...this is also addressable, just not that
   important at the moment.

Change-Id: Ibbf894ed5b7dd9ede1b088e530dd9cc2e0e649c2
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 024d7d4..e21f3de 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -278,9 +278,17 @@
      */
     void clearCallService() {
         if (mCallService != null) {
-            decrementAssociatedCallCount(mCallService);
-            mCallService.removeCall(this);
+            CallServiceWrapper callServiceTemp = mCallService;
             mCallService = null;
+            callServiceTemp.removeCall(this);
+
+            // Decrementing the count can cause the service to unbind, which itself can trigger the
+            // service-death code.  Since the service death code tries to clean up any associated
+            // calls, we need to make sure to remove that information (e.g., removeCall()) before
+            // we decrement. Technically, invoking removeCall() prior to decrementing is all that is
+            // necessary, but cleaning up mCallService prior to triggering an unbind is good to do.
+            // If you change this, make sure to update {@link clearCallServiceSelector} as well.
+            decrementAssociatedCallCount(callServiceTemp);
         }
     }
 
@@ -293,16 +301,19 @@
 
         clearCallServiceSelector();
 
+        selector.incrementAssociatedCallCount();
         mCallServiceSelector = selector;
         mCallServiceSelector.addCall(this);
     }
 
     void clearCallServiceSelector() {
         if (mCallServiceSelector != null) {
-            // TODO(sail): Stop leaking selectors.
-            // decrementAssociatedCallCount(mCallServiceSelector);
-            mCallServiceSelector.removeCall(this);
+            CallServiceSelectorWrapper selectorTemp = mCallServiceSelector;
             mCallServiceSelector = null;
+            selectorTemp.removeCall(this);
+
+            // See comment on {@link #clearCallService}.
+            decrementAssociatedCallCount(selectorTemp);
         }
     }