• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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