Fix DeadObjectException when bind fails.

There is a window of time during install when the service is deleted and
installed. During this time, binding to the service may cause a silent
service not found error in the log. But this error does not propagate to
our application.  Check for this case by querying the package manager
before trying to bind to the service.

Bug: 10569795
Change-Id: Ia58fde001603d0c716a2d1d91890dc31f78034a7
diff --git a/src/com/android/phone/CallHandlerServiceProxy.java b/src/com/android/phone/CallHandlerServiceProxy.java
index a85f9da..38373d7 100644
--- a/src/com/android/phone/CallHandlerServiceProxy.java
+++ b/src/com/android/phone/CallHandlerServiceProxy.java
@@ -20,6 +20,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -216,6 +218,7 @@
                 Log.d(TAG, "Service Connected");
             }
             onCallHandlerServiceConnected(ICallHandlerService.Stub.asInterface(service));
+            mBindRetryCount = 0;
         }
 
         @Override public void onServiceDisconnected (ComponentName className){
@@ -251,17 +254,37 @@
      * Sets up the connection with ICallHandlerService
      */
     private void setupServiceConnection() {
+        final Intent serviceIntent = new Intent(ICallHandlerService.class.getName());
+        final ComponentName component = new ComponentName(mContext.getResources().getString(
+                R.string.incall_ui_default_package), mContext.getResources().getString(
+                R.string.incall_ui_default_class));
+        serviceIntent.setComponent(component);
+
+        if (DBG) {
+            Log.d(TAG, "binding to service " + serviceIntent);
+        }
+
+        final PackageManager packageManger = mContext.getPackageManager();
+        final List<ResolveInfo> services = packageManger.queryIntentServices(serviceIntent, 0);
+        if (services.size() == 0) {
+            // Service not found, retry again after some delay
+            // This can happen if the service is being installed by the package manager.  Between
+            // deletes and installs, bindService could get a silent service not found error.
+            mBindRetryCount++;
+            if (mBindRetryCount < MAX_RETRY_COUNT) {
+                Log.w(TAG, "InCallUI service not found. " + serviceIntent + ". This happens if " +
+                                "the service is being installed and should be transient. Retrying" +
+                                RETRY_DELAY_MILLIS + " ms.");
+                sendMessageDelayed(Message.obtain(this, BIND_RETRY_MSG), RETRY_DELAY_MILLIS);
+            } else {
+                Log.e(TAG, "Tried to bind to in-call UI " + MAX_RETRY_COUNT + " times."
+                        + " Giving up.");
+            }
+            return;
+        }
+
         synchronized (mServiceAndQueueLock) {
             if (mCallHandlerServiceGuarded == null) {
-                final Intent serviceIntent = new Intent(ICallHandlerService.class.getName());
-                final ComponentName component = new ComponentName(mContext.getResources().getString(
-                        R.string.incall_ui_default_package), mContext.getResources().getString(
-                        R.string.incall_ui_default_class));
-                serviceIntent.setComponent(component);
-
-                if (DBG) {
-                    Log.d(TAG, "binding to service " + serviceIntent);
-                }
                 if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) {
                     // This happens when the in-call package is in the middle of being installed.
                     // Delay the retry.