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