1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.ims; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.os.Handler; 22 import android.os.IBinder; 23 import android.os.IInterface; 24 import android.os.RemoteException; 25 import android.telephony.ims.aidl.IImsConfig; 26 import android.telephony.ims.aidl.IImsMmTelFeature; 27 import android.telephony.ims.aidl.IImsRcsFeature; 28 import android.telephony.ims.aidl.IImsRegistration; 29 import android.telephony.ims.aidl.ISipTransport; 30 import android.telephony.ims.compat.ImsService; 31 import android.telephony.ims.compat.feature.ImsFeature; 32 import android.telephony.ims.compat.feature.MMTelFeature; 33 import android.util.Log; 34 import android.util.SparseArray; 35 36 import com.android.ims.ImsFeatureBinderRepository; 37 import com.android.ims.internal.IImsFeatureStatusCallback; 38 import com.android.ims.internal.IImsMMTelFeature; 39 import com.android.ims.internal.IImsServiceController; 40 import com.android.internal.annotations.VisibleForTesting; 41 import com.android.internal.telephony.flags.FeatureFlagsImpl; 42 43 /** 44 * Manages the Binding lifecycle of one ImsService as well as the relevant ImsFeatures that the 45 * ImsService will support. 46 * 47 * Compatibility interface for interacting with older implementations of ImsService. The older 48 * ImsService implementation is contained within the android.telephony.ims.compat.* namespace. 49 * Newer implementations of ImsService should use the current APIs contained in 50 * android.telephony.ims.*. 51 */ 52 public class ImsServiceControllerCompat extends ImsServiceController { 53 54 private static final String TAG = "ImsSCCompat"; 55 56 private IImsServiceController mServiceController; 57 58 private final SparseArray<MmTelFeatureCompatAdapter> mMmTelCompatAdapters = new SparseArray<>(); 59 private final SparseArray<ImsConfigCompatAdapter> mConfigCompatAdapters = new SparseArray<>(); 60 private final SparseArray<ImsRegistrationCompatAdapter> mRegCompatAdapters = 61 new SparseArray<>(); 62 63 private final MmTelFeatureCompatFactory mMmTelFeatureFactory; 64 65 /** 66 * Used to inject test instances of MmTelFeatureCompatAdapter 67 */ 68 @VisibleForTesting 69 public interface MmTelFeatureCompatFactory { 70 /** 71 * @return A new instance of {@link MmTelFeatureCompatAdapter} 72 */ create(Context context, int slotId, MmTelInterfaceAdapter compatFeature)73 MmTelFeatureCompatAdapter create(Context context, int slotId, 74 MmTelInterfaceAdapter compatFeature); 75 } 76 ImsServiceControllerCompat(Context context, ComponentName componentName, ImsServiceController.ImsServiceControllerCallbacks callbacks, ImsFeatureBinderRepository repo)77 public ImsServiceControllerCompat(Context context, ComponentName componentName, 78 ImsServiceController.ImsServiceControllerCallbacks callbacks, 79 ImsFeatureBinderRepository repo) { 80 super(context, componentName, callbacks, repo, new FeatureFlagsImpl()); 81 mMmTelFeatureFactory = MmTelFeatureCompatAdapter::new; 82 } 83 84 @VisibleForTesting ImsServiceControllerCompat(Context context, ComponentName componentName, ImsServiceControllerCallbacks callbacks, Handler handler, RebindRetry rebindRetry, ImsFeatureBinderRepository repo, MmTelFeatureCompatFactory factory)85 public ImsServiceControllerCompat(Context context, ComponentName componentName, 86 ImsServiceControllerCallbacks callbacks, Handler handler, RebindRetry rebindRetry, 87 ImsFeatureBinderRepository repo, MmTelFeatureCompatFactory factory) { 88 super(context, componentName, callbacks, handler, rebindRetry, repo, 89 new FeatureFlagsImpl()); 90 mMmTelFeatureFactory = factory; 91 } 92 93 @Override getServiceInterface()94 protected final String getServiceInterface() { 95 // Return compatibility version of String. 96 return ImsService.SERVICE_INTERFACE; 97 } 98 99 /** 100 * Converts the new command to {@link MMTelFeature#turnOnIms()}. 101 */ 102 @Override enableIms(int slotId, int subId)103 public final void enableIms(int slotId, int subId) { 104 MmTelFeatureCompatAdapter adapter = mMmTelCompatAdapters.get(slotId); 105 if (adapter == null) { 106 Log.w(TAG, "enableIms: adapter null for slot :" + slotId); 107 return; 108 } 109 try { 110 adapter.enableIms(); 111 } catch (RemoteException e) { 112 Log.w(TAG, "Couldn't enable IMS: " + e.getMessage()); 113 } 114 } 115 116 /** 117 * Converts the new command to {@link MMTelFeature#turnOffIms()}. 118 */ 119 @Override disableIms(int slotId, int subId)120 public final void disableIms(int slotId, int subId) { 121 MmTelFeatureCompatAdapter adapter = mMmTelCompatAdapters.get(slotId); 122 if (adapter == null) { 123 Log.w(TAG, "disableIms: adapter null for slot :" + slotId); 124 return; 125 } 126 try { 127 adapter.disableIms(); 128 } catch (RemoteException e) { 129 Log.w(TAG, "Couldn't disableIms IMS: " + e.getMessage()); 130 } 131 } 132 133 /** 134 * @return the IImsRegistration that corresponds to the slot id specified. 135 */ 136 @Override getRegistration(int slotId, int subId)137 public final IImsRegistration getRegistration(int slotId, int subId) { 138 ImsRegistrationCompatAdapter adapter = mRegCompatAdapters.get(slotId); 139 if (adapter == null) { 140 Log.w(TAG, "getRegistration: Registration does not exist for slot " + slotId); 141 return null; 142 } 143 return adapter.getBinder(); 144 } 145 146 /** 147 * @return the IImsConfig that corresponds to the slot id specified. 148 */ 149 @Override getConfig(int slotId, int subId)150 public final IImsConfig getConfig(int slotId, int subId) { 151 ImsConfigCompatAdapter adapter = mConfigCompatAdapters.get(slotId); 152 if (adapter == null) { 153 Log.w(TAG, "getConfig: Config does not exist for slot " + slotId); 154 return null; 155 } 156 return adapter.getIImsConfig(); 157 } 158 159 /** 160 * Return the SIP transport interface, which is not supported on the compat version of 161 * ImsService, so return null. 162 */ 163 @Override getSipTransport(int slotId)164 public ISipTransport getSipTransport(int slotId) { 165 return null; 166 } 167 168 @Override getStaticServiceCapabilities()169 protected long getStaticServiceCapabilities() { 170 // Older implementations do not support optional static capabilities 171 return 0L; 172 } 173 174 @Override notifyImsServiceReady()175 protected final void notifyImsServiceReady() { 176 Log.d(TAG, "notifyImsServiceReady"); 177 // don't do anything for compat impl. 178 } 179 180 @Override createImsFeature(int slotId, int subId, int featureType, long capabilities)181 protected final IInterface createImsFeature(int slotId, int subId, int featureType, 182 long capabilities) throws RemoteException { 183 switch (featureType) { 184 case ImsFeature.MMTEL: { 185 return createMMTelCompat(slotId); 186 } 187 case ImsFeature.RCS: { 188 189 return createRcsFeature(slotId); 190 } 191 default: 192 return null; 193 } 194 } 195 196 @Override registerImsFeatureStatusCallback(int slotId, int featureType, IImsFeatureStatusCallback c)197 protected void registerImsFeatureStatusCallback(int slotId, int featureType, 198 IImsFeatureStatusCallback c) throws RemoteException { 199 mServiceController.addFeatureStatusCallback(slotId, featureType, c); 200 } 201 202 @Override unregisterImsFeatureStatusCallback(int slotId, int featureType, IImsFeatureStatusCallback c)203 protected void unregisterImsFeatureStatusCallback(int slotId, int featureType, 204 IImsFeatureStatusCallback c) { 205 try { 206 mServiceController.removeFeatureStatusCallback(slotId, featureType, c); 207 } catch (RemoteException e) { 208 Log.w(TAG, "compat - unregisterImsFeatureStatusCallback - couldn't remove " + c); 209 } 210 } 211 212 @Override removeImsFeature(int slotId, int featureType, boolean changeSubId)213 protected final void removeImsFeature(int slotId, int featureType, boolean changeSubId) 214 throws RemoteException { 215 if (featureType == ImsFeature.MMTEL) { 216 MmTelFeatureCompatAdapter adapter = mMmTelCompatAdapters.get(slotId, null); 217 // Need to manually call onFeatureRemoved here, since this is normally called by the 218 // ImsService itself. 219 if (adapter != null) adapter.onFeatureRemoved(); 220 mMmTelCompatAdapters.remove(slotId); 221 mRegCompatAdapters.remove(slotId); 222 mConfigCompatAdapters.remove(slotId); 223 } 224 if (mServiceController != null) { 225 mServiceController.removeImsFeature(slotId, featureType); 226 } 227 } 228 229 @Override setServiceController(IBinder serviceController)230 protected void setServiceController(IBinder serviceController) { 231 mServiceController = IImsServiceController.Stub.asInterface(serviceController); 232 } 233 234 @Override isServiceControllerAvailable()235 protected boolean isServiceControllerAvailable() { 236 return mServiceController != null; 237 } 238 getInterface(int slotId)239 private MmTelInterfaceAdapter getInterface(int slotId) 240 throws RemoteException { 241 IImsMMTelFeature feature = mServiceController.createMMTelFeature(slotId); 242 if (feature == null) { 243 Log.w(TAG, "createMMTelCompat: createMMTelFeature returned null."); 244 return null; 245 } 246 return new MmTelInterfaceAdapter(slotId, feature.asBinder()); 247 } 248 createMMTelCompat(int slotId)249 private IImsMmTelFeature createMMTelCompat(int slotId) 250 throws RemoteException { 251 MmTelInterfaceAdapter interfaceAdapter = getInterface(slotId); 252 MmTelFeatureCompatAdapter mmTelAdapter = mMmTelFeatureFactory.create(mContext, slotId, 253 interfaceAdapter); 254 mMmTelCompatAdapters.put(slotId, mmTelAdapter); 255 ImsRegistrationCompatAdapter regAdapter = new ImsRegistrationCompatAdapter(); 256 mmTelAdapter.addRegistrationAdapter(regAdapter); 257 mRegCompatAdapters.put(slotId, regAdapter); 258 mConfigCompatAdapters.put(slotId, new ImsConfigCompatAdapter( 259 mmTelAdapter.getOldConfigInterface())); 260 return mmTelAdapter.getBinder(); 261 } 262 createRcsFeature(int slotId)263 private IImsRcsFeature createRcsFeature(int slotId) { 264 // Return non-null if there is a custom RCS implementation that needs a compatability layer. 265 return null; 266 } 267 } 268