Merge "Added getEquivalentHomePlmns API"
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index 1d33514..f5f24d3 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -29,17 +29,14 @@
 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;
@@ -58,7 +55,6 @@
 
     private PhoneGlobals mApp;
     private TelephonyRcsService mRcsService;
-    private ImsResolver mImsResolver;
 
     /**
      * Initialize the singleton ImsRcsController instance.
@@ -81,7 +77,6 @@
         mApp = app;
         TelephonyFrameworkInitializer
                 .getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
-        mImsResolver = mApp.getImsResolver();
     }
 
     /**
@@ -354,46 +349,6 @@
     }
 
     /**
-     * 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 509aa57..bd2b2ed 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -55,7 +55,6 @@
 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;
@@ -357,8 +356,7 @@
                 String defaultImsRcsPackage = getResources().getString(
                         R.string.config_ims_rcs_package);
                 mImsResolver = new ImsResolver(this, defaultImsMmtelPackage,
-                        defaultImsRcsPackage, PhoneFactory.getPhones().length,
-                        new ImsFeatureBinderRepository());
+                        defaultImsRcsPackage, PhoneFactory.getPhones().length);
                 mImsResolver.initialize();
             }
 
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index cfedda3..fc41dcc 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -104,6 +104,8 @@
 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;
@@ -311,6 +313,8 @@
     private AtomicBoolean mNotifyUserActivity;
     private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
 
+    private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
+
     private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
     private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
     private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
@@ -5005,40 +5009,58 @@
     }
 
     /**
-     * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
-     * callback.
+     * 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.
      */
-    @Override
-    public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback,
-            boolean oneShot) {
+    public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
+            IImsServiceFeatureCallback callback) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             if (mImsResolver == null) {
-                throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
-                        "Device does not support IMS");
+                // may happen if the device does not support IMS.
+                return null;
             }
-            if (oneShot) {
-                mImsResolver.callBackIfExists(slotId, ImsFeature.FEATURE_MMTEL, callback);
-            } else {
-                mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
-            }
+            return mImsResolver.getMmTelFeatureAndListen(slotId, 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.
      */
-    @Override
-    public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
+    public void unregisterImsFeatureCallback(int slotId, int featureType,
+            IImsServiceFeatureCallback callback) {
         enforceModifyPermission();
 
         final long identity = Binder.clearCallingIdentity();
         try {
             if (mImsResolver == null) return;
-            mImsResolver.unregisterImsFeatureCallback(callback);
+            mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5836,7 +5858,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+            int subId = phone.getSubId();
+            if (mCarrierPrivilegeTestOverrideSubIds.contains(subId)) {
+                // A test override is in place for the privileges for this subId, so don't try to
+                // read the subscription privileges.
+                return privilegeFromSim;
+            }
+            SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
             SubscriptionManager subManager = (SubscriptionManager)
                     phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
             for (String pkg : packages) {
@@ -5859,7 +5887,13 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+            int subId = phone.getSubId();
+            if (mCarrierPrivilegeTestOverrideSubIds.contains(subId)) {
+                // A test override is in place for the privileges for this subId, so don't try to
+                // read the subscription privileges.
+                return privilegeFromSim;
+            }
+            SubscriptionInfo subInfo = subController.getSubscriptionInfo(subId);
             SubscriptionManager subManager = (SubscriptionManager)
                     phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
             return subManager.canManageSubscription(subInfo, pkgName)
@@ -7744,6 +7778,11 @@
             }
             phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
                     carrierPrivilegeRules, apn);
+            if (carrierPrivilegeRules == null) {
+                mCarrierPrivilegeTestOverrideSubIds.remove(subId);
+            } else {
+                mCarrierPrivilegeTestOverrideSubIds.add(subId);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 916b4ce..5a2b384 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -1586,7 +1586,7 @@
                 }
             }
 
-            isVowifiEnabled = isWfcEnabled(phone);
+            isVowifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
         }
 
         if (isCurrentVideoCall) {
@@ -2722,7 +2722,7 @@
         boolean isIms = phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS;
         boolean isVoWifiEnabled = false;
         if (isIms) {
-            isVoWifiEnabled = isWfcEnabled(phone);
+            isVoWifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
         }
         boolean isRttMergeSupported = getCarrierConfig()
                 .getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
@@ -2772,12 +2772,6 @@
             notifyConferenceSupportedChanged(isConferenceSupported);
         }
     }
-
-    @VisibleForTesting
-    boolean isWfcEnabled(Phone phone) {
-        return ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
-    }
-
     /**
      * Provides a mapping from extras keys which may be found in the
      * {@link com.android.internal.telephony.Connection} to their equivalents defined in
diff --git a/src/com/android/services/telephony/rcs/RcsFeatureController.java b/src/com/android/services/telephony/rcs/RcsFeatureController.java
index 8c6fce0..fcfe312 100644
--- a/src/com/android/services/telephony/rcs/RcsFeatureController.java
+++ b/src/com/android/services/telephony/rcs/RcsFeatureController.java
@@ -20,9 +20,7 @@
 import android.content.Context;
 import android.net.Uri;
 import android.telephony.ims.ImsException;
-import android.telephony.ims.ImsRcsManager;
 import android.telephony.ims.ImsReasonInfo;
-import android.telephony.ims.RegistrationManager;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -30,7 +28,7 @@
 import android.util.Log;
 
 import com.android.ims.FeatureConnector;
-import com.android.ims.FeatureUpdates;
+import com.android.ims.IFeatureConnector;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
@@ -80,13 +78,13 @@
      * Used to inject FeatureConnector instances for testing.
      */
     @VisibleForTesting
-    public interface FeatureConnectorFactory<U extends FeatureUpdates> {
+    public interface FeatureConnectorFactory<T extends IFeatureConnector> {
         /**
-         * @return a {@link FeatureConnector} associated for the given {@link FeatureUpdates}
-         * and slot index.
+         * @return a {@link FeatureConnector} associated for the given {@link IFeatureConnector}
+         * and slot id.
          */
-        FeatureConnector<U> create(Context context, int slotIndex,
-                FeatureConnector.Listener<U> listener, Executor executor, String logPrefix);
+        FeatureConnector<T> create(Context context, int slotId,
+                FeatureConnector.Listener<T> listener, Executor executor, String tag);
     }
 
     /**
@@ -102,8 +100,7 @@
                 ImsRegistrationCallbackHelper.ImsRegistrationUpdate cb, Executor executor);
     }
 
-    private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory =
-            RcsFeatureManager::getConnector;
+    private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory = FeatureConnector::new;
     private RegistrationHelperFactory mRegistrationHelperFactory =
             ImsRegistrationCallbackHelper::new;
 
@@ -118,6 +115,11 @@
     private FeatureConnector.Listener<RcsFeatureManager> mFeatureConnectorListener =
             new FeatureConnector.Listener<RcsFeatureManager>() {
                 @Override
+                public RcsFeatureManager getFeatureManager() {
+                    return new RcsFeatureManager(mContext, mSlotId);
+                }
+
+                @Override
                 public void connectionReady(RcsFeatureManager manager)
                         throws com.android.ims.ImsException {
                     if (manager == null) {
@@ -138,10 +140,7 @@
                 }
 
                 @Override
-                public void connectionUnavailable(int reason) {
-                    if (reason == FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE) {
-                        loge("unexpected - connectionUnavailable due to server unavailable");
-                    }
+                public void connectionUnavailable() {
                     // Call before disabling connection to manager.
                     removeConnectionToService();
                     updateConnectionStatus(null /*manager*/);
@@ -280,7 +279,7 @@
     }
 
     @VisibleForTesting
-    public void setFeatureConnectorFactory(FeatureConnectorFactory<RcsFeatureManager> factory) {
+    public void setFeatureConnectorFactory(FeatureConnectorFactory factory) {
         mFeatureFactory = factory;
     }
 
@@ -434,10 +433,6 @@
         Log.w(LOG_TAG, getLogPrefix().append(log).toString());
     }
 
-    private void loge(String log) {
-        Log.e(LOG_TAG, getLogPrefix().append(log).toString());
-    }
-
     private StringBuilder getLogPrefix() {
         StringBuilder sb = new StringBuilder("[");
         sb.append(mSlotId);
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 2635e60..09cec17 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -169,12 +169,6 @@
         // Requires ImsManager dependencies, do not implement during testing.
     }
 
-    @Override
-    boolean isWfcEnabled(Phone phone) {
-        // Requires ImsManager dependencies, mock for test.
-        return true;
-    }
-
     public int getNotifyPhoneAccountChangedCount() {
         return mNotifyPhoneAccountChangedCount;
     }
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index 7e87dc7..fbb270d 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -100,8 +100,7 @@
         verify(mMockFeature).onRcsConnected(mFeatureManager);
 
         // Disconnect
-        mConnectorListener.getValue().connectionUnavailable(
-                FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
+        mConnectorListener.getValue().connectionUnavailable();
 
         verify(mFeatureManager).unregisterImsRegistrationCallback(any());
         verify(mMockFeature, times(2)).onRcsDisconnected();
@@ -194,8 +193,7 @@
     public void testFeatureManagerDisconnectedAddFeature() {
         RcsFeatureController controller = createFeatureController();
         // Disconnect the RcsFeatureManager
-        mConnectorListener.getValue().connectionUnavailable(
-                FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
+        mConnectorListener.getValue().connectionUnavailable();
         controller.addFeature(mMockFeature, RcsFeatureController.Feature.class);
 
         verify(mMockFeature).onRcsDisconnected();
@@ -207,8 +205,7 @@
         IImsRegistrationCallback regCb = mock(IImsRegistrationCallback.class);
         IImsCapabilityCallback capCb = mock(IImsCapabilityCallback.class);
         // Disconnect the RcsFeatureManager
-        mConnectorListener.getValue().connectionUnavailable(
-                FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
+        mConnectorListener.getValue().connectionUnavailable();
 
         try {
             controller.registerImsRegistrationCallback(0 /*subId*/, null /*callback*/);