Only unbind if bind() returned success

ServiceConnection may become disconnected asynchonously for various
reasons so calling unbind() on a disconnected SC is actually handled by
the framework. What we don't want to do is call unbind() on a service
which we never successfully called bindService() on, so in this CL we
will track the client-side binding instead of the connection status
through callbacks. This is less racy and handles the root cause of the
exception.

Bug: 145661922
Test: testUnbindWhenNotBound
Change-Id: Ia9bd746440faa047523a750afcae84c347de86d6
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index b953245..0b9cae1 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -69,6 +69,9 @@
     public SparseArray<String> mLastSimState = new SparseArray<>();
     private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor();
 
+    // whether we have successfully bound to the service
+    private boolean mServiceBound = false;
+
     private BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -279,6 +282,7 @@
                                 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                                 (r) -> mHandler.post(r),
                                 connection)) {
+                    mServiceBound = true;
                     return;
                 }
 
@@ -333,11 +337,12 @@
             carrierServiceClass = null;
 
             // Actually unbind
-            if (connection != null && connection.connected) {
+            if (mServiceBound) {
                 log("Unbinding from carrier app");
+                mServiceBound = false;
                 mContext.unbindService(connection);
             } else {
-                log("Already unbound, skipping unbindService call");
+                log("Not bound, skipping unbindService call");
             }
             connection = null;
             mUnbindScheduledUptimeMillis = -1;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
index 034423e..10b31a5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
@@ -84,7 +84,7 @@
     }
 
     @Test
-    public void testUnbindWhenNotConnected() throws Exception {
+    public void testUnbindWhenNotBound() throws Exception {
         mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
 
         // Try unbinding without binding and make sure we don't throw an Exception