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