1 /*
2  * Copyright (C) 2014 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 android.content.res.Resources;
20 import android.os.AsyncResult;
21 import android.os.Handler;
22 import android.os.Message;
23 
24 import com.android.telephony.Rlog;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * TelephonyDevController - provides a unified view of the
31  * telephony hardware resources on a device.
32  *
33  * manages the set of HardwareConfig for the framework.
34  */
35 public class TelephonyDevController extends Handler {
36     private static final String LOG_TAG = "TDC";
37     private static final boolean DBG = true;
38     private static final Object mLock = new Object();
39 
40     private static final int EVENT_HARDWARE_CONFIG_CHANGED = 1;
41 
42     private static TelephonyDevController sTelephonyDevController;
43     private static ArrayList<HardwareConfig> mModems = new ArrayList<HardwareConfig>();
44     private static ArrayList<HardwareConfig> mSims = new ArrayList<HardwareConfig>();
45 
46     private static Message sRilHardwareConfig;
47 
logd(String s)48     private static void logd(String s) {
49         Rlog.d(LOG_TAG, s);
50     }
51 
loge(String s)52     private static void loge(String s) {
53         Rlog.e(LOG_TAG, s);
54     }
55 
56     /** Create TelephonyDevController and set as singleton instance. */
create()57     public static TelephonyDevController create() {
58         synchronized (mLock) {
59             if (sTelephonyDevController != null) {
60                 throw new RuntimeException("TelephonyDevController already created!?!");
61             }
62             sTelephonyDevController = new TelephonyDevController();
63             return sTelephonyDevController;
64         }
65     }
66 
67     /** Get TelephonyDevController singleton. */
getInstance()68     public static TelephonyDevController getInstance() {
69         synchronized (mLock) {
70             if (sTelephonyDevController == null) {
71                 throw new RuntimeException("TelephonyDevController not yet created!?!");
72             }
73             return sTelephonyDevController;
74         }
75     }
76 
initFromResource()77     private void initFromResource() {
78         Resources resource = Resources.getSystem();
79         String[] hwStrings = resource.getStringArray(
80             com.android.internal.R.array.config_telephonyHardware);
81         if (hwStrings != null) {
82             for (String hwString : hwStrings) {
83                 HardwareConfig hw = new HardwareConfig(hwString);
84                 if (hw != null) {
85                     if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_MODEM) {
86                         updateOrInsert(hw, mModems);
87                     } else if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_SIM) {
88                         updateOrInsert(hw, mSims);
89                     }
90                 }
91             }
92         }
93     }
94 
TelephonyDevController()95     private TelephonyDevController() {
96         initFromResource();
97 
98         mModems.trimToSize();
99         mSims.trimToSize();
100     }
101 
102     /**
103      * each RIL call this interface to register/unregister the unsolicited hardware
104      * configuration callback data it can provide.
105      */
registerRIL(CommandsInterface cmdsIf)106     public static void registerRIL(CommandsInterface cmdsIf) {
107         /* get the current configuration from this ril... */
108         cmdsIf.getHardwareConfig(sRilHardwareConfig);
109         /* ... process it ... */
110         if (sRilHardwareConfig != null) {
111             AsyncResult ar = (AsyncResult) sRilHardwareConfig.obj;
112             if (ar.exception == null) {
113                 handleGetHardwareConfigChanged(ar);
114             }
115         }
116         /* and register for async device configuration change. */
117         cmdsIf.registerForHardwareConfigChanged(sTelephonyDevController, EVENT_HARDWARE_CONFIG_CHANGED, null);
118     }
119 
unregisterRIL(CommandsInterface cmdsIf)120     public static void unregisterRIL(CommandsInterface cmdsIf) {
121         cmdsIf.unregisterForHardwareConfigChanged(sTelephonyDevController);
122     }
123 
124     /**
125      * handle callbacks from RIL.
126      */
handleMessage(Message msg)127     public void handleMessage(Message msg) {
128         AsyncResult ar;
129         switch (msg.what) {
130             case EVENT_HARDWARE_CONFIG_CHANGED:
131                 if (DBG) logd("handleMessage: received EVENT_HARDWARE_CONFIG_CHANGED");
132                 ar = (AsyncResult) msg.obj;
133                 handleGetHardwareConfigChanged(ar);
134             break;
135             default:
136                 loge("handleMessage: Unknown Event " + msg.what);
137         }
138     }
139 
140     /**
141      * hardware configuration update or insert.
142      */
updateOrInsert(HardwareConfig hw, ArrayList<HardwareConfig> list)143     private static void updateOrInsert(HardwareConfig hw, ArrayList<HardwareConfig> list) {
144         int size;
145         HardwareConfig item;
146         synchronized (mLock) {
147             size = list.size();
148             for (int i = 0 ; i < size ; i++) {
149                 item = list.get(i);
150                 if (item.uuid.compareTo(hw.uuid) == 0) {
151                     if (DBG) logd("updateOrInsert: removing: " + item);
152                     list.remove(i);
153                     break;
154                 }
155             }
156             if (DBG) logd("updateOrInsert: inserting: " + hw);
157             list.add(hw);
158         }
159     }
160 
161     /**
162      * hardware configuration changed.
163      */
handleGetHardwareConfigChanged(AsyncResult ar)164     private static void handleGetHardwareConfigChanged(AsyncResult ar) {
165         if ((ar.exception == null) && (ar.result != null)) {
166             List hwcfg = (List)ar.result;
167             for (int i = 0 ; i < hwcfg.size() ; i++) {
168                 HardwareConfig hw = null;
169 
170                 hw = (HardwareConfig) hwcfg.get(i);
171                 if (hw != null) {
172                     if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_MODEM) {
173                         updateOrInsert(hw, mModems);
174                     } else if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_SIM) {
175                         updateOrInsert(hw, mSims);
176                     }
177                 }
178             }
179         } else {
180             /* error detected, ignore.  are we missing some real time configutation
181              * at this point?  what to do...
182              */
183             loge("handleGetHardwareConfigChanged - returned an error.");
184         }
185     }
186 
187     /**
188      * get total number of registered modem.
189      */
getModemCount()190     public static int getModemCount() {
191         synchronized (mLock) {
192             int count = mModems.size();
193             if (DBG) logd("getModemCount: " + count);
194             return count;
195         }
196     }
197 
198     /**
199      * get modem at index 'index'.
200      */
getModem(int index)201     public HardwareConfig getModem(int index) {
202         synchronized (mLock) {
203             if (mModems.isEmpty()) {
204                 loge("getModem: no registered modem device?!?");
205                 return null;
206             }
207 
208             if (index > getModemCount()) {
209                 loge("getModem: out-of-bounds access for modem device " + index + " max: " + getModemCount());
210                 return null;
211             }
212 
213             if (DBG) logd("getModem: " + index);
214             return mModems.get(index);
215         }
216     }
217 
218     /**
219      * get total number of registered sims.
220      */
getSimCount()221     public int getSimCount() {
222         synchronized (mLock) {
223             int count = mSims.size();
224             if (DBG) logd("getSimCount: " + count);
225             return count;
226         }
227     }
228 
229     /**
230      * get sim at index 'index'.
231      */
getSim(int index)232     public HardwareConfig getSim(int index) {
233         synchronized (mLock) {
234             if (mSims.isEmpty()) {
235                 loge("getSim: no registered sim device?!?");
236                 return null;
237             }
238 
239             if (index > getSimCount()) {
240                 loge("getSim: out-of-bounds access for sim device " + index + " max: " + getSimCount());
241                 return null;
242             }
243 
244             if (DBG) logd("getSim: " + index);
245             return mSims.get(index);
246         }
247     }
248 
249     /**
250      * get modem associated with sim index 'simIndex'.
251      */
getModemForSim(int simIndex)252     public HardwareConfig getModemForSim(int simIndex) {
253         synchronized (mLock) {
254             if (mModems.isEmpty() || mSims.isEmpty()) {
255                 loge("getModemForSim: no registered modem/sim device?!?");
256                 return null;
257             }
258 
259             if (simIndex > getSimCount()) {
260                 loge("getModemForSim: out-of-bounds access for sim device " + simIndex + " max: " + getSimCount());
261                 return null;
262             }
263 
264             if (DBG) logd("getModemForSim " + simIndex);
265 
266             HardwareConfig sim = getSim(simIndex);
267             for (HardwareConfig modem: mModems) {
268                 if (modem.uuid.equals(sim.modemUuid)) {
269                     return modem;
270                 }
271             }
272 
273             return null;
274         }
275     }
276 
277     /**
278      * get all sim's associated with modem at index 'modemIndex'.
279      */
getAllSimsForModem(int modemIndex)280     public ArrayList<HardwareConfig> getAllSimsForModem(int modemIndex) {
281         synchronized (mLock) {
282             if (mSims.isEmpty()) {
283                 loge("getAllSimsForModem: no registered sim device?!?");
284                 return null;
285             }
286 
287             if (modemIndex > getModemCount()) {
288                 loge("getAllSimsForModem: out-of-bounds access for modem device " + modemIndex + " max: " + getModemCount());
289                 return null;
290             }
291 
292             if (DBG) logd("getAllSimsForModem " + modemIndex);
293 
294             ArrayList<HardwareConfig> result = new ArrayList<HardwareConfig>();
295             HardwareConfig modem = getModem(modemIndex);
296             for (HardwareConfig sim: mSims) {
297                 if (sim.modemUuid.equals(modem.uuid)) {
298                     result.add(sim);
299                 }
300             }
301             return result;
302         }
303     }
304 
305     /**
306      * get all modem's registered.
307      */
getAllModems()308     public ArrayList<HardwareConfig> getAllModems() {
309         synchronized (mLock) {
310             ArrayList<HardwareConfig> modems = new ArrayList<HardwareConfig>();
311             if (mModems.isEmpty()) {
312                 if (DBG) logd("getAllModems: empty list.");
313             } else {
314                 for (HardwareConfig modem: mModems) {
315                     modems.add(modem);
316                 }
317             }
318 
319             return modems;
320         }
321     }
322 
323     /**
324      * get all sim's registered.
325      */
getAllSims()326     public ArrayList<HardwareConfig> getAllSims() {
327         synchronized (mLock) {
328             ArrayList<HardwareConfig> sims = new ArrayList<HardwareConfig>();
329             if (mSims.isEmpty()) {
330                 if (DBG) logd("getAllSims: empty list.");
331             } else {
332                 for (HardwareConfig sim: mSims) {
333                     sims.add(sim);
334                 }
335             }
336 
337             return sims;
338         }
339     }
340 }
341