Loading src/java/com/android/internal/telephony/PhoneFactory.java +8 −2 Original line number Diff line number Diff line Loading @@ -150,11 +150,17 @@ public class PhoneFactory { where as in single SIM mode only instance. isMultiSimEnabled() function checks whether it is single SIM or multi SIM mode */ int numPhones = TelephonyManager.getDefault().getPhoneCount(); // Start ImsResolver and bind to ImsServices. // Return whether or not the device should use dynamic binding or the static // implementation (deprecated) boolean isDynamicBinding = sContext.getResources().getBoolean( com.android.internal.R.bool.config_dynamic_bind_ims); // Get the package name of the default IMS implementation. String defaultImsPackage = sContext.getResources().getString( com.android.internal.R.string.config_ims_package); // Start ImsResolver and bind to ImsServices. Rlog.i(LOG_TAG, "ImsResolver: defaultImsPackage: " + defaultImsPackage); sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones); sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones, isDynamicBinding); sImsResolver.populateCacheAndStartBind(); int[] networkModes = new int[numPhones]; Loading src/java/com/android/internal/telephony/ims/ImsResolver.java +61 −15 Original line number Diff line number Diff line Loading @@ -241,12 +241,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } }; private ImsServiceControllerFactory mImsServiceControllerFactoryStaticBindingCompat = new ImsServiceControllerFactory() { @Override public String getServiceInterface() { // The static method of binding does not use service interfaces. return null; } @Override public ImsServiceController create(Context context, ComponentName componentName, ImsServiceController.ImsServiceControllerCallbacks callbacks) { return new ImsServiceControllerStaticCompat(context, componentName, callbacks); } }; private final CarrierConfigManager mCarrierConfigManager; private final Context mContext; // Locks mBoundImsServicesByFeature only. Be careful to avoid deadlocks from // ImsServiceController callbacks. private final Object mBoundServicesLock = new Object(); private final int mNumSlots; private final boolean mIsDynamicBinding; // Synchronize all messages on a handler to ensure that the cache includes the most recent // version of the installed ImsServices. Loading Loading @@ -284,28 +300,41 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal private Set<ImsServiceInfo> mInstalledServicesCache = new ArraySet<>(); // not locked, only accessed on a handler thread. private Set<ImsServiceController> mActiveControllers = new ArraySet<>(); // Only used as the private final ComponentName mStaticComponent; public ImsResolver(Context context, String defaultImsPackageName, int numSlots) { public ImsResolver(Context context, String defaultImsPackageName, int numSlots, boolean isDynamicBinding) { mContext = context; mDeviceService = defaultImsPackageName; mNumSlots = numSlots; mIsDynamicBinding = isDynamicBinding; mStaticComponent = new ComponentName(mContext, ImsResolver.class); if (!mIsDynamicBinding) { Log.i(TAG, "ImsResolver initialized with static binding."); mDeviceService = mStaticComponent.getPackageName(); } mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService( Context.CARRIER_CONFIG_SERVICE); mCarrierServices = new String[numSlots]; mBoundImsServicesByFeature = Stream.generate(SparseArray<ImsServiceController>::new) .limit(mNumSlots).collect(Collectors.toList()); // Only register for Package/CarrierConfig updates if dynamic binding. if(mIsDynamicBinding) { IntentFilter appChangedFilter = new IntentFilter(); appChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); appChangedFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED); appChangedFilter.addDataScheme("package"); context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter, null, context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter, null, null); context.registerReceiver(mConfigChangedReceiver, new IntentFilter( CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); } } @VisibleForTesting public void setSubscriptionManagerProxy(SubscriptionManagerProxy proxy) { Loading Loading @@ -500,7 +529,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } } // Update the current cache with the new ImsService(s) if it has been added or update the // supported IMS features if they have changed. // Called from the handler ONLY Loading Loading @@ -783,10 +811,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal // get all packages that support ImsServices. private List<ImsServiceInfo> getImsServiceInfo(String packageName) { List<ImsServiceInfo> infos = new ArrayList<>(); if (!mIsDynamicBinding) { // always return the same ImsService info. infos.addAll(getStaticImsService()); } else { // Search for Current ImsService implementations infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactory)); // Search for compat ImsService Implementations infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactoryCompat)); } return infos; } private List<ImsServiceInfo> getStaticImsService() { List<ImsServiceInfo> infos = new ArrayList<>(); ImsServiceInfo info = new ImsServiceInfo(); info.name = mStaticComponent; info.supportedFeatures = new HashSet<>(ImsFeature.FEATURE_MAX); info.controllerFactory = mImsServiceControllerFactoryStaticBindingCompat; info.supportsEmergencyMmTel = true; info.supportedFeatures.add(ImsFeature.FEATURE_MMTEL); infos.add(info); return infos; } Loading src/java/com/android/internal/telephony/ims/ImsServiceController.java +15 −2 Original line number Diff line number Diff line Loading @@ -334,8 +334,12 @@ public class ImsServiceController { | Context.BIND_IMPORTANT; Log.i(LOG_TAG, "Binding ImsService:" + mComponentName); try { return mContext.bindService(imsServiceIntent, mImsServiceConnection, serviceFlags); boolean bindSucceeded = startBindToService(imsServiceIntent, mImsServiceConnection, serviceFlags); if (!bindSucceeded) { mBackoff.notifyFailed(); } return bindSucceeded; } catch (Exception e) { mBackoff.notifyFailed(); Log.e(LOG_TAG, "Error binding (" + mComponentName + ") with exception: " Loading @@ -349,6 +353,15 @@ public class ImsServiceController { } } /** * Starts the bind to the ImsService. Overridden by subclasses that need to access the service * in a different fashion. */ protected boolean startBindToService(Intent intent, ImsServiceConnection connection, int flags) { return mContext.bindService(intent, connection, flags); } /** * Calls {@link IImsServiceController#removeImsFeature} on all features that the * ImsService supports and then unbinds the service. Loading src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java +8 −2 Original line number Diff line number Diff line Loading @@ -160,15 +160,21 @@ public class ImsServiceControllerCompat extends ImsServiceController { return mServiceController != null; } private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c) protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c) throws RemoteException { IImsMMTelFeature feature = mServiceController.createMMTelFeature(slotId, c); if (feature == null) { Log.w(TAG, "createMMTelCompat: createMMTelFeature returned null."); return null; } return new MmTelInterfaceAdapter(slotId, feature.asBinder()); } private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c) throws RemoteException { MmTelInterfaceAdapter interfaceAdapter = getInterface(slotId, c); MmTelFeatureCompatAdapter mmTelAdapter = new MmTelFeatureCompatAdapter(mContext, slotId, feature); interfaceAdapter); mMmTelCompatAdapters.put(slotId, mmTelAdapter); ImsRegistrationCompatAdapter regAdapter = new ImsRegistrationCompatAdapter(); mmTelAdapter.addRegistrationAdapter(regAdapter); Loading src/java/com/android/internal/telephony/ims/ImsServiceControllerStaticCompat.java 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.internal.telephony.ims; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.ims.internal.IImsService; /** * A compat layer for communicating with older devices that still used the ServiceManager to get * the ImsService. */ public class ImsServiceControllerStaticCompat extends ImsServiceControllerCompat { private static final String TAG = "ImsSCStaticCompat"; private static final String IMS_SERVICE_NAME = "ims"; private IImsService mImsServiceCompat = null; public ImsServiceControllerStaticCompat(Context context, ComponentName componentName, ImsServiceController.ImsServiceControllerCallbacks callbacks) { super(context, componentName, callbacks); } @Override public boolean startBindToService(Intent intent, ImsServiceConnection connection, int flags) { IBinder binder = ServiceManager.checkService(IMS_SERVICE_NAME); if (binder == null) { return false; } // This is a little hacky, but we are going to call the onServiceConnected to "pretend" like // bindService has completed here, which will pass the binder to setServiceController and // set up all supporting structures. connection.onServiceConnected(new ComponentName(mContext, ImsServiceControllerStaticCompat.class), binder); return true; } @Override protected void setServiceController(IBinder serviceController) { mImsServiceCompat = IImsService.Stub.asInterface(serviceController); } @Override protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c) throws RemoteException { if (mImsServiceCompat == null) { Log.w(TAG, "getInterface: IImsService returned null."); return null; } return new ImsServiceInterfaceAdapter(slotId, mImsServiceCompat.asBinder()); } } Loading
src/java/com/android/internal/telephony/PhoneFactory.java +8 −2 Original line number Diff line number Diff line Loading @@ -150,11 +150,17 @@ public class PhoneFactory { where as in single SIM mode only instance. isMultiSimEnabled() function checks whether it is single SIM or multi SIM mode */ int numPhones = TelephonyManager.getDefault().getPhoneCount(); // Start ImsResolver and bind to ImsServices. // Return whether or not the device should use dynamic binding or the static // implementation (deprecated) boolean isDynamicBinding = sContext.getResources().getBoolean( com.android.internal.R.bool.config_dynamic_bind_ims); // Get the package name of the default IMS implementation. String defaultImsPackage = sContext.getResources().getString( com.android.internal.R.string.config_ims_package); // Start ImsResolver and bind to ImsServices. Rlog.i(LOG_TAG, "ImsResolver: defaultImsPackage: " + defaultImsPackage); sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones); sImsResolver = new ImsResolver(sContext, defaultImsPackage, numPhones, isDynamicBinding); sImsResolver.populateCacheAndStartBind(); int[] networkModes = new int[numPhones]; Loading
src/java/com/android/internal/telephony/ims/ImsResolver.java +61 −15 Original line number Diff line number Diff line Loading @@ -241,12 +241,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } }; private ImsServiceControllerFactory mImsServiceControllerFactoryStaticBindingCompat = new ImsServiceControllerFactory() { @Override public String getServiceInterface() { // The static method of binding does not use service interfaces. return null; } @Override public ImsServiceController create(Context context, ComponentName componentName, ImsServiceController.ImsServiceControllerCallbacks callbacks) { return new ImsServiceControllerStaticCompat(context, componentName, callbacks); } }; private final CarrierConfigManager mCarrierConfigManager; private final Context mContext; // Locks mBoundImsServicesByFeature only. Be careful to avoid deadlocks from // ImsServiceController callbacks. private final Object mBoundServicesLock = new Object(); private final int mNumSlots; private final boolean mIsDynamicBinding; // Synchronize all messages on a handler to ensure that the cache includes the most recent // version of the installed ImsServices. Loading Loading @@ -284,28 +300,41 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal private Set<ImsServiceInfo> mInstalledServicesCache = new ArraySet<>(); // not locked, only accessed on a handler thread. private Set<ImsServiceController> mActiveControllers = new ArraySet<>(); // Only used as the private final ComponentName mStaticComponent; public ImsResolver(Context context, String defaultImsPackageName, int numSlots) { public ImsResolver(Context context, String defaultImsPackageName, int numSlots, boolean isDynamicBinding) { mContext = context; mDeviceService = defaultImsPackageName; mNumSlots = numSlots; mIsDynamicBinding = isDynamicBinding; mStaticComponent = new ComponentName(mContext, ImsResolver.class); if (!mIsDynamicBinding) { Log.i(TAG, "ImsResolver initialized with static binding."); mDeviceService = mStaticComponent.getPackageName(); } mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService( Context.CARRIER_CONFIG_SERVICE); mCarrierServices = new String[numSlots]; mBoundImsServicesByFeature = Stream.generate(SparseArray<ImsServiceController>::new) .limit(mNumSlots).collect(Collectors.toList()); // Only register for Package/CarrierConfig updates if dynamic binding. if(mIsDynamicBinding) { IntentFilter appChangedFilter = new IntentFilter(); appChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); appChangedFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED); appChangedFilter.addDataScheme("package"); context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter, null, context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter, null, null); context.registerReceiver(mConfigChangedReceiver, new IntentFilter( CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); } } @VisibleForTesting public void setSubscriptionManagerProxy(SubscriptionManagerProxy proxy) { Loading Loading @@ -500,7 +529,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal } } // Update the current cache with the new ImsService(s) if it has been added or update the // supported IMS features if they have changed. // Called from the handler ONLY Loading Loading @@ -783,10 +811,28 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal // get all packages that support ImsServices. private List<ImsServiceInfo> getImsServiceInfo(String packageName) { List<ImsServiceInfo> infos = new ArrayList<>(); if (!mIsDynamicBinding) { // always return the same ImsService info. infos.addAll(getStaticImsService()); } else { // Search for Current ImsService implementations infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactory)); // Search for compat ImsService Implementations infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactoryCompat)); } return infos; } private List<ImsServiceInfo> getStaticImsService() { List<ImsServiceInfo> infos = new ArrayList<>(); ImsServiceInfo info = new ImsServiceInfo(); info.name = mStaticComponent; info.supportedFeatures = new HashSet<>(ImsFeature.FEATURE_MAX); info.controllerFactory = mImsServiceControllerFactoryStaticBindingCompat; info.supportsEmergencyMmTel = true; info.supportedFeatures.add(ImsFeature.FEATURE_MMTEL); infos.add(info); return infos; } Loading
src/java/com/android/internal/telephony/ims/ImsServiceController.java +15 −2 Original line number Diff line number Diff line Loading @@ -334,8 +334,12 @@ public class ImsServiceController { | Context.BIND_IMPORTANT; Log.i(LOG_TAG, "Binding ImsService:" + mComponentName); try { return mContext.bindService(imsServiceIntent, mImsServiceConnection, serviceFlags); boolean bindSucceeded = startBindToService(imsServiceIntent, mImsServiceConnection, serviceFlags); if (!bindSucceeded) { mBackoff.notifyFailed(); } return bindSucceeded; } catch (Exception e) { mBackoff.notifyFailed(); Log.e(LOG_TAG, "Error binding (" + mComponentName + ") with exception: " Loading @@ -349,6 +353,15 @@ public class ImsServiceController { } } /** * Starts the bind to the ImsService. Overridden by subclasses that need to access the service * in a different fashion. */ protected boolean startBindToService(Intent intent, ImsServiceConnection connection, int flags) { return mContext.bindService(intent, connection, flags); } /** * Calls {@link IImsServiceController#removeImsFeature} on all features that the * ImsService supports and then unbinds the service. Loading
src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java +8 −2 Original line number Diff line number Diff line Loading @@ -160,15 +160,21 @@ public class ImsServiceControllerCompat extends ImsServiceController { return mServiceController != null; } private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c) protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c) throws RemoteException { IImsMMTelFeature feature = mServiceController.createMMTelFeature(slotId, c); if (feature == null) { Log.w(TAG, "createMMTelCompat: createMMTelFeature returned null."); return null; } return new MmTelInterfaceAdapter(slotId, feature.asBinder()); } private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c) throws RemoteException { MmTelInterfaceAdapter interfaceAdapter = getInterface(slotId, c); MmTelFeatureCompatAdapter mmTelAdapter = new MmTelFeatureCompatAdapter(mContext, slotId, feature); interfaceAdapter); mMmTelCompatAdapters.put(slotId, mmTelAdapter); ImsRegistrationCompatAdapter regAdapter = new ImsRegistrationCompatAdapter(); mmTelAdapter.addRegistrationAdapter(regAdapter); Loading
src/java/com/android/internal/telephony/ims/ImsServiceControllerStaticCompat.java 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.internal.telephony.ims; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import com.android.ims.internal.IImsFeatureStatusCallback; import com.android.ims.internal.IImsService; /** * A compat layer for communicating with older devices that still used the ServiceManager to get * the ImsService. */ public class ImsServiceControllerStaticCompat extends ImsServiceControllerCompat { private static final String TAG = "ImsSCStaticCompat"; private static final String IMS_SERVICE_NAME = "ims"; private IImsService mImsServiceCompat = null; public ImsServiceControllerStaticCompat(Context context, ComponentName componentName, ImsServiceController.ImsServiceControllerCallbacks callbacks) { super(context, componentName, callbacks); } @Override public boolean startBindToService(Intent intent, ImsServiceConnection connection, int flags) { IBinder binder = ServiceManager.checkService(IMS_SERVICE_NAME); if (binder == null) { return false; } // This is a little hacky, but we are going to call the onServiceConnected to "pretend" like // bindService has completed here, which will pass the binder to setServiceController and // set up all supporting structures. connection.onServiceConnected(new ComponentName(mContext, ImsServiceControllerStaticCompat.class), binder); return true; } @Override protected void setServiceController(IBinder serviceController) { mImsServiceCompat = IImsService.Stub.asInterface(serviceController); } @Override protected MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c) throws RemoteException { if (mImsServiceCompat == null) { Log.w(TAG, "getInterface: IImsService returned null."); return null; } return new ImsServiceInterfaceAdapter(slotId, mImsServiceCompat.asBinder()); } }