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