Move IMS to a listener type model instead of a poll model

[RESUBMISSION AFTER REVERT aosp/1443077]

Pipe through new listen commands for components requiring
access to ImsFeature binders and refactor the RCS
controllers to use the new model.

Test: atest TeleServiceTests
Merged-In: I81629d32ab995a70d8d5795351890e6d89495664
Change-Id: I81629d32ab995a70d8d5795351890e6d89495664
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index f5f24d3..1d33514 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -29,14 +29,17 @@
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsUceControllerCallback;
 import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
+import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.RcsFeature;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
 import com.android.ims.ImsManager;
+import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.services.telephony.rcs.RcsFeatureController;
 import com.android.services.telephony.rcs.TelephonyRcsService;
@@ -55,6 +58,7 @@
 
     private PhoneGlobals mApp;
     private TelephonyRcsService mRcsService;
+    private ImsResolver mImsResolver;
 
     /**
      * Initialize the singleton ImsRcsController instance.
@@ -77,6 +81,7 @@
         mApp = app;
         TelephonyFrameworkInitializer
                 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
+        mImsResolver = mApp.getImsResolver();
     }
 
     /**
@@ -349,6 +354,46 @@
     }
 
     /**
+     * Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
+     * callback.
+     */
+    @Override
+    public void registerRcsFeatureCallback(int slotId, IImsServiceFeatureCallback callback,
+            boolean oneShot) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (mImsResolver == null) {
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "Device does not support IMS");
+            }
+            if (oneShot) {
+                mImsResolver.callBackIfExists(slotId, ImsFeature.FEATURE_RCS, callback);
+            } else {
+                mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_RCS, callback);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+    /**
+     * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
+     */
+    @Override
+    public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (mImsResolver == null) return;
+            mImsResolver.unregisterImsFeatureCallback(callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Make sure either called from same process as self (phone) or IPC caller has read privilege.
      *
      * @throws SecurityException if the caller does not have the required permission
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index bd2b2ed..509aa57 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -55,6 +55,7 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.ims.ImsFeatureBinderRepository;
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.MmiCode;
@@ -356,7 +357,8 @@
                 String defaultImsRcsPackage = getResources().getString(
                         R.string.config_ims_rcs_package);
                 mImsResolver = new ImsResolver(this, defaultImsMmtelPackage,
-                        defaultImsRcsPackage, PhoneFactory.getPhones().length);
+                        defaultImsRcsPackage, PhoneFactory.getPhones().length,
+                        new ImsFeatureBinderRepository());
                 mImsResolver.initialize();
             }
 
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index c22a8a4..9ddbe47 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -104,8 +104,6 @@
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.feature.ImsFeature;
@@ -5007,58 +5005,40 @@
     }
 
     /**
-     * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id for the MMTel
-     * feature or {@link null} if the service is not available. If the feature is available, the
-     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
+     * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
+     * callback.
      */
-    public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
-            IImsServiceFeatureCallback callback) {
+    @Override
+    public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback,
+            boolean oneShot) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             if (mImsResolver == null) {
-                // may happen if the device does not support IMS.
-                return null;
+                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                        "Device does not support IMS");
             }
-            return mImsResolver.getMmTelFeatureAndListen(slotId, callback);
+            if (oneShot) {
+                mImsResolver.callBackIfExists(slotId, ImsFeature.FEATURE_MMTEL, callback);
+            } else {
+                mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
-
-    /**
-     * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for the RCS
-     * feature during emergency calling or {@link null} if the service is not available. If the
-     * feature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
-     * listener for feature updates.
-     */
-    public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
-        enforceModifyPermission();
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            if (mImsResolver == null) {
-                // may happen if the device does not support IMS.
-                return null;
-            }
-            return mImsResolver.getRcsFeatureAndListen(slotId, callback);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     /**
      * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
      */
-    public void unregisterImsFeatureCallback(int slotId, int featureType,
-            IImsServiceFeatureCallback callback) {
+    @Override
+    public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             if (mImsResolver == null) return;
-            mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
+            mImsResolver.unregisterImsFeatureCallback(callback);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }