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