• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 android.telephony.mockmodem;
18 
19 import android.hardware.radio.RadioError;
20 import android.hardware.radio.RadioIndicationType;
21 import android.hardware.radio.RadioResponseInfo;
22 import android.hardware.radio.config.IRadioConfig;
23 import android.hardware.radio.config.IRadioConfigIndication;
24 import android.hardware.radio.config.IRadioConfigResponse;
25 import android.hardware.radio.config.PhoneCapability;
26 import android.hardware.radio.config.SimSlotStatus;
27 import android.hardware.radio.config.SimType;
28 import android.hardware.radio.config.SimTypeInfo;
29 import android.hardware.radio.config.SlotPortMapping;
30 import android.os.AsyncResult;
31 import android.os.Build;
32 import android.os.Handler;
33 import android.os.Message;
34 import android.os.RemoteException;
35 import android.util.Log;
36 
37 public class IRadioConfigImpl extends IRadioConfig.Stub {
38     private static final String TAG = "MRCFG";
39 
40     private final MockModemService mService;
41     private IRadioConfigResponse mRadioConfigResponse;
42     private IRadioConfigIndication mRadioConfigIndication;
43     private MockModemConfigInterface mMockModemConfigInterface;
44     private final Object mCacheUpdateMutex;
45     private final Handler mHandler;
46     private int mSubId;
47     private String mTag;
48 
49     // ***** Events
50     static final int EVENT_NUM_OF_LIVE_MODEM_CHANGED = 1;
51     static final int EVENT_PHONE_CAPABILITY_CHANGED = 2;
52     static final int EVENT_SIM_SLOT_STATUS_CHANGED = 3;
53     static final int EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED = 4;
54 
55     // ***** Cache of modem attributes/status
56     private int mSlotNum = 1;
57     private byte mNumOfLiveModems = 1;
58     private PhoneCapability mPhoneCapability = new PhoneCapability();
59     private SimSlotStatus[] mSimSlotStatus;
60     private int[] mEnabledLogicalSlots = {};
61     private SimTypeInfo[] mSimTypeInfos;
62 
63     MockCentralizedNetworkAgent mMockCentralizedNetworkAgent;
64 
IRadioConfigImpl( MockModemService service, MockModemConfigInterface configInterface, MockCentralizedNetworkAgent centralizedNetworkAgent, int instanceId)65     public IRadioConfigImpl(
66             MockModemService service, MockModemConfigInterface configInterface,
67             MockCentralizedNetworkAgent centralizedNetworkAgent, int instanceId) {
68         mTag = TAG + "-" + instanceId;
69         Log.d(mTag, "Instantiated");
70 
71         this.mService = service;
72         mMockModemConfigInterface = configInterface;
73         mSlotNum = mService.getNumPhysicalSlots();
74         mSimSlotStatus = new SimSlotStatus[mSlotNum];
75         mCacheUpdateMutex = new Object();
76         mHandler = new IRadioConfigHandler();
77         mSubId = instanceId;
78         mMockCentralizedNetworkAgent = centralizedNetworkAgent;
79         mSimTypeInfos = new SimTypeInfo[mSlotNum];
80 
81         // Register events
82         mMockModemConfigInterface.registerForNumOfLiveModemChanged(
83                 mSubId, mHandler, EVENT_NUM_OF_LIVE_MODEM_CHANGED, null);
84         mMockModemConfigInterface.registerForPhoneCapabilityChanged(
85                 mSubId, mHandler, EVENT_PHONE_CAPABILITY_CHANGED, null);
86         mMockModemConfigInterface.registerForSimSlotStatusChanged(
87                 mSubId, mHandler, EVENT_SIM_SLOT_STATUS_CHANGED, null);
88         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
89             mMockModemConfigInterface.registerForSimultaneousCallingSupportStatusChanged(
90                     mSubId, mHandler, EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED, null);
91         }
92     }
93 
94     /** Handler class to handle callbacks */
95     private final class IRadioConfigHandler extends Handler {
96         @Override
handleMessage(Message msg)97         public void handleMessage(Message msg) {
98             AsyncResult ar;
99             synchronized (mCacheUpdateMutex) {
100                 switch (msg.what) {
101                     case EVENT_NUM_OF_LIVE_MODEM_CHANGED:
102                         Log.d(mTag, "Received EVENT_NUM_OF_LIVE_MODEM_CHANGED");
103                         ar = (AsyncResult) msg.obj;
104                         if (ar != null && ar.exception == null) {
105                             mNumOfLiveModems = (byte) ar.result;
106                             Log.i(mTag, "Number of live modem: " + mNumOfLiveModems);
107                         } else {
108                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
109                         }
110                         break;
111                     case EVENT_PHONE_CAPABILITY_CHANGED:
112                         Log.d(mTag, "Received EVENT_PHONE_CAPABILITY_CHANGED");
113                         ar = (AsyncResult) msg.obj;
114                         if (ar != null && ar.exception == null) {
115                             mPhoneCapability = (PhoneCapability) ar.result;
116                             Log.i(mTag, "Phone capability: " + mPhoneCapability);
117                         } else {
118                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
119                         }
120                         break;
121                     case EVENT_SIM_SLOT_STATUS_CHANGED:
122                         Log.d(mTag, "Received EVENT_SIM_SLOT_STATUS_CHANGED");
123                         ar = (AsyncResult) msg.obj;
124                         if (ar != null && ar.exception == null) {
125                             mSimSlotStatus = (SimSlotStatus[]) ar.result;
126                             for (int i = 0; i < mSlotNum; i++) {
127                                 Log.i(mTag, "Sim slot status: " + mSimSlotStatus[i]);
128                             }
129                             unsolSimSlotsStatusChanged();
130                         } else {
131                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
132                         }
133                         break;
134                     case EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED:
135                         Log.i(mTag, "Received EVENT_SIMULTANEOUS_CALLING_SUPPORT_CHANGED");
136                         ar = (AsyncResult) msg.obj;
137                         if (ar != null && ar.exception == null) {
138                             mEnabledLogicalSlots = (int[]) ar.result;
139                             if (mEnabledLogicalSlots != null) {
140                                 for (int enabledLogicalSlot : mEnabledLogicalSlots) {
141                                     Log.i(mTag, "Enabled logical slot = "
142                                             + enabledLogicalSlot);
143                                 }
144                             } else {
145                                 Log.i(mTag, "mEnabledLogicalSlots is null");
146                             }
147                             unsolSimultaneousCallingSupportChanged();
148                         } else {
149                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
150                         }
151                         break;
152                 }
153             }
154         }
155     }
156 
157     // Implementation of IRadioConfig functions
158     @Override
getHalDeviceCapabilities(int serial)159     public void getHalDeviceCapabilities(int serial) {
160         Log.d(mTag, "getHalDeviceCapabilities");
161 
162         boolean modemReducedFeatureSet1 = false;
163 
164         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
165         try {
166             mRadioConfigResponse.getHalDeviceCapabilitiesResponse(rsp, modemReducedFeatureSet1);
167         } catch (RemoteException ex) {
168             Log.e(
169                     mTag,
170                     "Failed to invoke getHalDeviceCapabilitiesResponse from AIDL. Exception" + ex);
171         }
172     }
173 
174     @Override
getNumOfLiveModems(int serial)175     public void getNumOfLiveModems(int serial) {
176         Log.d(mTag, "getNumOfLiveModems");
177         byte numoflivemodem;
178 
179         synchronized (mCacheUpdateMutex) {
180             numoflivemodem = mNumOfLiveModems;
181         }
182 
183         RadioResponseInfo rsp = mService.makeSolRsp(serial);
184         try {
185             mRadioConfigResponse.getNumOfLiveModemsResponse(rsp, numoflivemodem);
186         } catch (RemoteException ex) {
187             Log.e(mTag, "Failed to invoke getNumOfLiveModemsResponse from AIDL. Exception" + ex);
188         }
189     }
190 
191     @Override
getPhoneCapability(int serial)192     public void getPhoneCapability(int serial) {
193         Log.d(mTag, "getPhoneCapability");
194         PhoneCapability phoneCapability;
195 
196         synchronized (mCacheUpdateMutex) {
197             phoneCapability = mPhoneCapability;
198         }
199 
200         RadioResponseInfo rsp = mService.makeSolRsp(serial);
201         try {
202             mRadioConfigResponse.getPhoneCapabilityResponse(rsp, phoneCapability);
203         } catch (RemoteException ex) {
204             Log.e(mTag, "Failed to invoke getPhoneCapabilityResponse from AIDL. Exception" + ex);
205         }
206     }
207 
208     @Override
getSimultaneousCallingSupport(int serial)209     public void getSimultaneousCallingSupport(int serial) {
210         Log.d(mTag, "getSimultaneousCallingSupport");
211         int[] enabledLogicalSlots;
212 
213         synchronized (mCacheUpdateMutex) {
214             enabledLogicalSlots = mEnabledLogicalSlots;
215         }
216 
217         RadioResponseInfo rsp = mService.makeSolRsp(serial);
218         try {
219             mRadioConfigResponse.getSimultaneousCallingSupportResponse(rsp, enabledLogicalSlots);
220         } catch (RemoteException ex) {
221             Log.e(mTag, "Failed to invoke getSimultaneousCallingSupportResponse from AIDL. "
222                     + "Exception" + ex);
223         }
224     }
225 
226     @Override
getSimSlotsStatus(int serial)227     public void getSimSlotsStatus(int serial) {
228         Log.d(mTag, "getSimSlotsStatus");
229         SimSlotStatus[] slotStatus;
230 
231         synchronized (mCacheUpdateMutex) {
232             if (mSlotNum < 1) {
233                 Log.d(mTag, "No slot information is retured.");
234                 slotStatus = null;
235             } else {
236                 slotStatus = mSimSlotStatus;
237             }
238         }
239 
240         RadioResponseInfo rsp = mService.makeSolRsp(serial);
241         try {
242             mRadioConfigResponse.getSimSlotsStatusResponse(rsp, slotStatus);
243         } catch (RemoteException ex) {
244             Log.e(mTag, "Failed to invoke getSimSlotsStatusResponse from AIDL. Exception" + ex);
245         }
246     }
247 
248     @Override
setNumOfLiveModems(int serial, byte numOfLiveModems)249     public void setNumOfLiveModems(int serial, byte numOfLiveModems) {
250         Log.d(mTag, "setNumOfLiveModems");
251         // TODO: cache value
252 
253         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
254         try {
255             mRadioConfigResponse.setNumOfLiveModemsResponse(rsp);
256         } catch (RemoteException ex) {
257             Log.e(mTag, "Failed to invoke setNumOfLiveModemsResponse from AIDL. Exception" + ex);
258         }
259     }
260 
261     @Override
setPreferredDataModem(int serial, byte modemId)262     public void setPreferredDataModem(int serial, byte modemId) {
263         Log.d(mTag, "setPreferredDataModem");
264         // TODO: cache value
265 
266         RadioResponseInfo rsp = mService.makeSolRsp(serial);
267         try {
268             mMockCentralizedNetworkAgent.setPreferredDataPhone((int) modemId);
269             mRadioConfigResponse.setPreferredDataModemResponse(rsp);
270         } catch (RemoteException ex) {
271             Log.e(mTag, "Failed to invoke setPreferredDataModemResponse from AIDL. Exception" + ex);
272         }
273     }
274 
275     @Override
setResponseFunctions( IRadioConfigResponse radioConfigResponse, IRadioConfigIndication radioConfigIndication)276     public void setResponseFunctions(
277             IRadioConfigResponse radioConfigResponse,
278             IRadioConfigIndication radioConfigIndication) {
279         Log.d(mTag, "setResponseFunctions");
280         mRadioConfigResponse = radioConfigResponse;
281         mRadioConfigIndication = radioConfigIndication;
282         mService.countDownLatch(MockModemService.LATCH_RADIO_INTERFACES_READY);
283     }
284 
285     @Override
setSimSlotsMapping(int serial, SlotPortMapping[] slotMap)286     public void setSimSlotsMapping(int serial, SlotPortMapping[] slotMap) {
287         Log.d(mTag, "setSimSlotsMapping");
288         // TODO: cache value
289 
290         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
291         try {
292             mRadioConfigResponse.setSimSlotsMappingResponse(rsp);
293         } catch (RemoteException ex) {
294             Log.e(mTag, "Failed to invoke setSimSlotsMappingResponse from AIDL. Exception" + ex);
295         }
296     }
297 
298     @Override
getSimTypeInfo(int serial)299     public void getSimTypeInfo(int serial) {
300         Log.d(mTag, "getSimTypeInfo");
301         SimTypeInfo[] simTypeInfos;
302 
303         synchronized (mCacheUpdateMutex) {
304             simTypeInfos = mSimTypeInfos;
305         }
306 
307         RadioResponseInfo rsp = mService.makeSolRsp(serial);
308         try {
309             mRadioConfigResponse.getSimTypeInfoResponse(rsp, simTypeInfos);
310         } catch (RemoteException ex) {
311             Log.e(mTag, "Failed to invoke getSimTypeInfoResponse from AIDL. "
312                     + "Exception" + ex);
313         }
314     }
315 
316     @Override
setSimType(int serial, @SimType int[] simTypes)317     public void setSimType(int serial, @SimType int[] simTypes) {
318         Log.d(mTag, "setSimType");
319         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
320         try {
321             mRadioConfigResponse.setSimTypeResponse(rsp);
322         } catch (RemoteException ex) {
323             Log.e(mTag, "Failed to invoke setSimTypeResponse from AIDL. "
324                     + "Exception" + ex);
325         }
326     }
327 
unsolSimSlotsStatusChanged()328     public void unsolSimSlotsStatusChanged() {
329         Log.d(mTag, "unsolSimSlotsStatusChanged");
330         SimSlotStatus[] slotStatus;
331 
332         if (mRadioConfigIndication != null) {
333             synchronized (mCacheUpdateMutex) {
334                 if (mSlotNum < 1) {
335                     Log.d(mTag, "No slot information is retured.");
336                     slotStatus = null;
337                 } else {
338                     slotStatus = mSimSlotStatus;
339                 }
340             }
341 
342             try {
343                 mRadioConfigIndication.simSlotsStatusChanged(
344                         RadioIndicationType.UNSOLICITED, slotStatus);
345             } catch (RemoteException ex) {
346                 Log.e(mTag, "Failed to invoke simSlotsStatusChanged from AIDL. Exception" + ex);
347             }
348         } else {
349             Log.e(mTag, "null mRadioConfigIndication");
350         }
351     }
352 
unsolSimultaneousCallingSupportChanged()353     public void unsolSimultaneousCallingSupportChanged() {
354         Log.d(mTag, "unsolSimultaneousCallingSupportChanged");
355         int[] enabledLogicalSlots;
356 
357         if (mRadioConfigIndication != null) {
358             synchronized (mCacheUpdateMutex) {
359                 if (mSlotNum < 1) {
360                     Log.d(mTag, "No slot information is retured.");
361                     enabledLogicalSlots = null;
362                 } else {
363                     enabledLogicalSlots = mEnabledLogicalSlots;
364                 }
365             }
366 
367             try {
368                 mRadioConfigIndication.onSimultaneousCallingSupportChanged(enabledLogicalSlots);
369             } catch (RemoteException ex) {
370                 Log.e(mTag, "Failed to invoke onSimultaneousCallingSupportChanged from AIDL."
371                         + " Exception" + ex);
372             }
373         } else {
374             Log.e(mTag, "null mRadioConfigIndication");
375         }
376     }
377 
378     @Override
getInterfaceHash()379     public String getInterfaceHash() {
380         return IRadioConfig.HASH;
381     }
382 
383     @Override
getInterfaceVersion()384     public int getInterfaceVersion() {
385         return IRadioConfig.VERSION;
386     }
387 }
388