• 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 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