• 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 com.android.internal.telephony;
18 
19 import static android.telephony.TelephonyManager.HAL_SERVICE_DATA;
20 import static android.telephony.TelephonyManager.HAL_SERVICE_IMS;
21 import static android.telephony.TelephonyManager.HAL_SERVICE_MESSAGING;
22 import static android.telephony.TelephonyManager.HAL_SERVICE_MODEM;
23 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
24 import static android.telephony.TelephonyManager.HAL_SERVICE_SIM;
25 import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE;
26 
27 import android.app.ActivityManager;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.ServiceConnection;
32 import android.os.IBinder;
33 import android.os.UserHandle;
34 
35 import com.android.telephony.Rlog;
36 
37 /** This class provides wrapper APIs for binding interfaces to mock service. */
38 public class MockModem {
39     private static final String TAG = "MockModem";
40     private static final String BIND_IRADIOMODEM = "android.telephony.mockmodem.iradiomodem";
41     private static final String BIND_IRADIOSIM = "android.telephony.mockmodem.iradiosim";
42     private static final String BIND_IRADIOMESSAGING =
43             "android.telephony.mockmodem.iradiomessaging";
44     private static final String BIND_IRADIODATA = "android.telephony.mockmodem.iradiodata";
45     private static final String BIND_IRADIONETWORK = "android.telephony.mockmodem.iradionetwork";
46     private static final String BIND_IRADIOVOICE = "android.telephony.mockmodem.iradiovoice";
47     private static final String BIND_IRADIOIMS = "android.telephony.mockmodem.iradioims";
48     private static final String BIND_IRADIOCONFIG = "android.telephony.mockmodem.iradioconfig";
49     private static final String PHONE_ID = "phone_id";
50 
51     private static final byte DEFAULT_PHONE_ID = 0x00;
52 
53     static final int RADIOCONFIG_SERVICE = RIL.MAX_SERVICE_IDX + 1;
54 
55     static final int BINDER_RETRY_MILLIS = 3 * 100;
56     static final int BINDER_MAX_RETRY = 10;
57 
58     private Context mContext;
59     private String mServiceName;
60     private String mPackageName;
61 
62     private IBinder mModemBinder;
63     private IBinder mSimBinder;
64     private IBinder mMessagingBinder;
65     private IBinder mDataBinder;
66     private IBinder mNetworkBinder;
67     private IBinder mVoiceBinder;
68     private IBinder mImsBinder;
69     private IBinder mConfigBinder;
70     private ServiceConnection mModemServiceConnection;
71     private ServiceConnection mSimServiceConnection;
72     private ServiceConnection mMessagingServiceConnection;
73     private ServiceConnection mDataServiceConnection;
74     private ServiceConnection mNetworkServiceConnection;
75     private ServiceConnection mVoiceServiceConnection;
76     private ServiceConnection mImsServiceConnection;
77     private ServiceConnection mConfigServiceConnection;
78 
79     private byte mPhoneId;
80     private String mTag;
81 
MockModem(Context context, String serviceName)82     MockModem(Context context, String serviceName) {
83         this(context, serviceName, 0);
84     }
85 
MockModem(Context context, String serviceName, int phoneId)86     MockModem(Context context, String serviceName, int phoneId) {
87         mPhoneId = (byte) phoneId;
88         mTag = TAG + "-" + mPhoneId;
89         mContext = context;
90         String[] componentInfo = serviceName.split("/", 2);
91         mPackageName = componentInfo[0];
92         mServiceName = componentInfo[1];
93     }
94 
95     private class MockModemConnection implements ServiceConnection {
96         private int mService;
97 
MockModemConnection(int module)98         MockModemConnection(int module) {
99             mService = module;
100         }
101 
102         @Override
onServiceConnected(ComponentName name, IBinder binder)103         public void onServiceConnected(ComponentName name, IBinder binder) {
104             Rlog.d(mTag, "IRadio " + getModuleName(mService) + "  - onServiceConnected");
105 
106             if (mService == HAL_SERVICE_MODEM) {
107                 mModemBinder = binder;
108             } else if (mService == HAL_SERVICE_SIM) {
109                 mSimBinder = binder;
110             } else if (mService == HAL_SERVICE_MESSAGING) {
111                 mMessagingBinder = binder;
112             } else if (mService == HAL_SERVICE_DATA) {
113                 mDataBinder = binder;
114             } else if (mService == HAL_SERVICE_NETWORK) {
115                 mNetworkBinder = binder;
116             } else if (mService == HAL_SERVICE_VOICE) {
117                 mVoiceBinder = binder;
118             } else if (mService == HAL_SERVICE_IMS) {
119                 mImsBinder = binder;
120             } else if (mService == RADIOCONFIG_SERVICE) {
121                 mConfigBinder = binder;
122             }
123         }
124 
125         @Override
onServiceDisconnected(ComponentName name)126         public void onServiceDisconnected(ComponentName name) {
127             Rlog.d(mTag, "IRadio " + getModuleName(mService) + "  - onServiceDisconnected");
128 
129             if (mService == HAL_SERVICE_MODEM) {
130                 mModemBinder = null;
131             } else if (mService == HAL_SERVICE_SIM) {
132                 mSimBinder = null;
133             } else if (mService == HAL_SERVICE_MESSAGING) {
134                 mMessagingBinder = null;
135             } else if (mService == HAL_SERVICE_DATA) {
136                 mDataBinder = null;
137             } else if (mService == HAL_SERVICE_NETWORK) {
138                 mNetworkBinder = null;
139             } else if (mService == HAL_SERVICE_VOICE) {
140                 mVoiceBinder = null;
141             } else if (mService == HAL_SERVICE_IMS) {
142                 mImsBinder = null;
143             } else if (mService == RADIOCONFIG_SERVICE) {
144                 mConfigBinder = null;
145             }
146         }
147     }
148 
bindModuleToMockModemService( String actionName, ServiceConnection serviceConnection)149     private boolean bindModuleToMockModemService(
150             String actionName, ServiceConnection serviceConnection) {
151         return bindModuleToMockModemService(DEFAULT_PHONE_ID, actionName, serviceConnection);
152     }
153 
bindModuleToMockModemService( byte phoneId, String actionName, ServiceConnection serviceConnection)154     private boolean bindModuleToMockModemService(
155             byte phoneId, String actionName, ServiceConnection serviceConnection) {
156         boolean status = false;
157 
158         Intent intent = new Intent();
159         intent.setComponent(new ComponentName(mPackageName, mServiceName));
160         intent.setAction(actionName + phoneId);
161         intent.putExtra(PHONE_ID, phoneId);
162 
163         status = mContext.bindServiceAsUser(intent, serviceConnection, Context.BIND_AUTO_CREATE,
164                 UserHandle.of(ActivityManager.getCurrentUser()));
165         return status;
166     }
167 
168     /** waitForBinder */
getServiceBinder(int service)169     public IBinder getServiceBinder(int service) {
170         switch (service) {
171             case HAL_SERVICE_MODEM:
172                 return mModemBinder;
173             case HAL_SERVICE_SIM:
174                 return mSimBinder;
175             case HAL_SERVICE_MESSAGING:
176                 return mMessagingBinder;
177             case HAL_SERVICE_DATA:
178                 return mDataBinder;
179             case HAL_SERVICE_NETWORK:
180                 return mNetworkBinder;
181             case HAL_SERVICE_VOICE:
182                 return mVoiceBinder;
183             case HAL_SERVICE_IMS:
184                 return mImsBinder;
185             case RADIOCONFIG_SERVICE:
186                 return mConfigBinder;
187             default:
188                 return null;
189         }
190     }
191 
192     /** Binding interfaces with mock modem service */
bindAllMockModemService()193     public void bindAllMockModemService() {
194         for (int service = RIL.MIN_SERVICE_IDX; service <= RIL.MAX_SERVICE_IDX; service++) {
195             bindToMockModemService(service);
196         }
197     }
198 
199     /** bindToMockModemService */
bindToMockModemService(int service)200     public void bindToMockModemService(int service) {
201         if (service == RADIOCONFIG_SERVICE) {
202             if (mConfigBinder == null) {
203                 mConfigServiceConnection = new MockModemConnection(RADIOCONFIG_SERVICE);
204 
205                 boolean status =
206                         bindModuleToMockModemService(BIND_IRADIOCONFIG, mConfigServiceConnection);
207                 if (!status) {
208                     Rlog.d(mTag, "IRadio Config bind fail");
209                     mConfigServiceConnection = null;
210                 }
211             } else {
212                 Rlog.d(mTag, "IRadio Config is bound");
213             }
214         } else if (service == HAL_SERVICE_MODEM) {
215             if (mModemBinder == null) {
216                 mModemServiceConnection = new MockModemConnection(HAL_SERVICE_MODEM);
217 
218                 boolean status =
219                         bindModuleToMockModemService(
220                                 mPhoneId, BIND_IRADIOMODEM, mModemServiceConnection);
221                 if (!status) {
222                     Rlog.d(mTag, "IRadio Modem bind fail");
223                     mModemServiceConnection = null;
224                 }
225             } else {
226                 Rlog.d(mTag, "IRadio Modem is bound");
227             }
228         } else if (service == HAL_SERVICE_SIM) {
229             if (mSimBinder == null) {
230                 mSimServiceConnection = new MockModemConnection(HAL_SERVICE_SIM);
231 
232                 boolean status =
233                         bindModuleToMockModemService(
234                                 mPhoneId, BIND_IRADIOSIM, mSimServiceConnection);
235                 if (!status) {
236                     Rlog.d(mTag, "IRadio Sim bind fail");
237                     mSimServiceConnection = null;
238                 }
239             } else {
240                 Rlog.d(mTag, "IRadio Sim is bound");
241             }
242         } else if (service == HAL_SERVICE_MESSAGING) {
243             if (mMessagingBinder == null) {
244                 mMessagingServiceConnection = new MockModemConnection(HAL_SERVICE_MESSAGING);
245 
246                 boolean status =
247                         bindModuleToMockModemService(
248                                 mPhoneId, BIND_IRADIOMESSAGING, mMessagingServiceConnection);
249                 if (!status) {
250                     Rlog.d(mTag, "IRadio Messaging bind fail");
251                     mMessagingServiceConnection = null;
252                 }
253             } else {
254                 Rlog.d(mTag, "IRadio Messaging is bound");
255             }
256         } else if (service == HAL_SERVICE_DATA) {
257             if (mDataBinder == null) {
258                 mDataServiceConnection = new MockModemConnection(HAL_SERVICE_DATA);
259 
260                 boolean status =
261                         bindModuleToMockModemService(
262                                 mPhoneId, BIND_IRADIODATA, mDataServiceConnection);
263                 if (!status) {
264                     Rlog.d(mTag, "IRadio Data bind fail");
265                     mDataServiceConnection = null;
266                 }
267             } else {
268                 Rlog.d(mTag, "IRadio Data is bound");
269             }
270         } else if (service == HAL_SERVICE_NETWORK) {
271             if (mNetworkBinder == null) {
272                 mNetworkServiceConnection = new MockModemConnection(HAL_SERVICE_NETWORK);
273 
274                 boolean status =
275                         bindModuleToMockModemService(
276                                 mPhoneId, BIND_IRADIONETWORK, mNetworkServiceConnection);
277                 if (!status) {
278                     Rlog.d(mTag, "IRadio Network bind fail");
279                     mNetworkServiceConnection = null;
280                 }
281             } else {
282                 Rlog.d(mTag, "IRadio Network is bound");
283             }
284         } else if (service == HAL_SERVICE_VOICE) {
285             if (mVoiceBinder == null) {
286                 mVoiceServiceConnection = new MockModemConnection(HAL_SERVICE_VOICE);
287 
288                 boolean status =
289                         bindModuleToMockModemService(
290                                 mPhoneId, BIND_IRADIOVOICE, mVoiceServiceConnection);
291                 if (!status) {
292                     Rlog.d(mTag, "IRadio Voice bind fail");
293                     mVoiceServiceConnection = null;
294                 }
295             } else {
296                 Rlog.d(mTag, "IRadio Voice is bound");
297             }
298         } else if (service == HAL_SERVICE_IMS) {
299             if (mImsBinder == null) {
300                 mImsServiceConnection = new MockModemConnection(HAL_SERVICE_IMS);
301 
302                 boolean status =
303                         bindModuleToMockModemService(
304                                 mPhoneId, BIND_IRADIOIMS, mImsServiceConnection);
305                 if (!status) {
306                     Rlog.d(TAG, "IRadio Ims bind fail");
307                     mImsServiceConnection = null;
308                 }
309             } else {
310                 Rlog.d(TAG, "IRadio Ims is bound");
311             }
312         }
313     }
314 
315     /** unbindMockModemService */
unbindMockModemService(int service)316     public void unbindMockModemService(int service) {
317 
318         if (service == RADIOCONFIG_SERVICE) {
319             if (mConfigServiceConnection != null) {
320                 mContext.unbindService(mConfigServiceConnection);
321                 mConfigServiceConnection = null;
322                 mConfigBinder = null;
323                 Rlog.d(mTag, "unbind IRadio Config");
324             }
325         } else if (service == HAL_SERVICE_MODEM) {
326             if (mModemServiceConnection != null) {
327                 mContext.unbindService(mModemServiceConnection);
328                 mModemServiceConnection = null;
329                 mModemBinder = null;
330                 Rlog.d(mTag, "unbind IRadio Modem");
331             }
332         } else if (service == HAL_SERVICE_SIM) {
333             if (mSimServiceConnection != null) {
334                 mContext.unbindService(mSimServiceConnection);
335                 mSimServiceConnection = null;
336                 mSimBinder = null;
337                 Rlog.d(mTag, "unbind IRadio Sim");
338             }
339         } else if (service == HAL_SERVICE_MESSAGING) {
340             if (mMessagingServiceConnection != null) {
341                 mContext.unbindService(mMessagingServiceConnection);
342                 mMessagingServiceConnection = null;
343                 mMessagingBinder = null;
344                 Rlog.d(mTag, "unbind IRadio Messaging");
345             }
346         } else if (service == HAL_SERVICE_DATA) {
347             if (mDataServiceConnection != null) {
348                 mContext.unbindService(mDataServiceConnection);
349                 mDataServiceConnection = null;
350                 mDataBinder = null;
351                 Rlog.d(mTag, "unbind IRadio Data");
352             }
353         } else if (service == HAL_SERVICE_NETWORK) {
354             if (mNetworkServiceConnection != null) {
355                 mContext.unbindService(mNetworkServiceConnection);
356                 mNetworkServiceConnection = null;
357                 mNetworkBinder = null;
358                 Rlog.d(mTag, "unbind IRadio Network");
359             }
360         } else if (service == HAL_SERVICE_VOICE) {
361             if (mVoiceServiceConnection != null) {
362                 mContext.unbindService(mVoiceServiceConnection);
363                 mVoiceServiceConnection = null;
364                 mVoiceBinder = null;
365                 Rlog.d(mTag, "unbind IRadio Voice");
366             }
367         } else if (service == HAL_SERVICE_IMS) {
368             if (mImsServiceConnection != null) {
369                 mContext.unbindService(mImsServiceConnection);
370                 mImsServiceConnection = null;
371                 mImsBinder = null;
372                 Rlog.d(TAG, "unbind IRadio Ims");
373             }
374         }
375     }
376 
getServiceName()377     public String getServiceName() {
378         return mServiceName;
379     }
380 
getModuleName(int service)381     private String getModuleName(int service) {
382         switch (service) {
383             case HAL_SERVICE_MODEM:
384                 return "modem";
385             case HAL_SERVICE_SIM:
386                 return "sim";
387             case HAL_SERVICE_MESSAGING:
388                 return "messaging";
389             case HAL_SERVICE_DATA:
390                 return "data";
391             case HAL_SERVICE_NETWORK:
392                 return "network";
393             case HAL_SERVICE_VOICE:
394                 return "voice";
395             case HAL_SERVICE_IMS:
396                 return "ims";
397             case RADIOCONFIG_SERVICE:
398                 return "config";
399             default:
400                 return "none";
401         }
402     }
403 }
404