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                 }
158             }
159             if (DBG) logd("updateOrInsert: inserting: " + hw);
160             list.add(hw);
161         }
162     }
163 
164     /**
165      * hardware configuration changed.
166      */
handleGetHardwareConfigChanged(AsyncResult ar)167     private static void handleGetHardwareConfigChanged(AsyncResult ar) {
168         if ((ar.exception == null) && (ar.result != null)) {
169             List hwcfg = (List)ar.result;
170             for (int i = 0 ; i < hwcfg.size() ; i++) {
171                 HardwareConfig hw = null;
172 
173                 hw = (HardwareConfig) hwcfg.get(i);
174                 if (hw != null) {
175                     if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_MODEM) {
176                         updateOrInsert(hw, mModems);
177                     } else if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_SIM) {
178                         updateOrInsert(hw, mSims);
179                     }
180                 }
181             }
182         } else {
183             /* error detected, ignore.  are we missing some real time configutation
184              * at this point?  what to do...
185              */
186             loge("handleGetHardwareConfigChanged - returned an error.");
187         }
188     }
189 
190     /**
191      * get total number of registered modem.
192      */
getModemCount()193     public static int getModemCount() {
194         synchronized (mLock) {
195             int count = mModems.size();
196             if (DBG) logd("getModemCount: " + count);
197             return count;
198         }
199     }
200 
201     /**
202      * get modem at index 'index'.
203      */
getModem(int index)204     public HardwareConfig getModem(int index) {
205         synchronized (mLock) {
206             if (mModems.isEmpty()) {
207                 loge("getModem: no registered modem device?!?");
208                 return null;
209             }
210 
211             if (index > getModemCount()) {
212                 loge("getModem: out-of-bounds access for modem device " + index + " max: " + getModemCount());
213                 return null;
214             }
215 
216             if (DBG) logd("getModem: " + index);
217             return mModems.get(index);
218         }
219     }
220 
221     /**
222      * get total number of registered sims.
223      */
getSimCount()224     public int getSimCount() {
225         synchronized (mLock) {
226             int count = mSims.size();
227             if (DBG) logd("getSimCount: " + count);
228             return count;
229         }
230     }
231 
232     /**
233      * get sim at index 'index'.
234      */
getSim(int index)235     public HardwareConfig getSim(int index) {
236         synchronized (mLock) {
237             if (mSims.isEmpty()) {
238                 loge("getSim: no registered sim device?!?");
239                 return null;
240             }
241 
242             if (index > getSimCount()) {
243                 loge("getSim: out-of-bounds access for sim device " + index + " max: " + getSimCount());
244                 return null;
245             }
246 
247             if (DBG) logd("getSim: " + index);
248             return mSims.get(index);
249         }
250     }
251 
252     /**
253      * get modem associated with sim index 'simIndex'.
254      */
getModemForSim(int simIndex)255     public HardwareConfig getModemForSim(int simIndex) {
256         synchronized (mLock) {
257             if (mModems.isEmpty() || mSims.isEmpty()) {
258                 loge("getModemForSim: no registered modem/sim device?!?");
259                 return null;
260             }
261 
262             if (simIndex > getSimCount()) {
263                 loge("getModemForSim: out-of-bounds access for sim device " + simIndex + " max: " + getSimCount());
264                 return null;
265             }
266 
267             if (DBG) logd("getModemForSim " + simIndex);
268 
269             HardwareConfig sim = getSim(simIndex);
270             for (HardwareConfig modem: mModems) {
271                 if (modem.uuid.equals(sim.modemUuid)) {
272                     return modem;
273                 }
274             }
275 
276             return null;
277         }
278     }
279 
280     /**
281      * get all sim's associated with modem at index 'modemIndex'.
282      */
getAllSimsForModem(int modemIndex)283     public ArrayList<HardwareConfig> getAllSimsForModem(int modemIndex) {
284         synchronized (mLock) {
285             if (mSims.isEmpty()) {
286                 loge("getAllSimsForModem: no registered sim device?!?");
287                 return null;
288             }
289 
290             if (modemIndex > getModemCount()) {
291                 loge("getAllSimsForModem: out-of-bounds access for modem device " + modemIndex + " max: " + getModemCount());
292                 return null;
293             }
294 
295             if (DBG) logd("getAllSimsForModem " + modemIndex);
296 
297             ArrayList<HardwareConfig> result = new ArrayList<HardwareConfig>();
298             HardwareConfig modem = getModem(modemIndex);
299             for (HardwareConfig sim: mSims) {
300                 if (sim.modemUuid.equals(modem.uuid)) {
301                     result.add(sim);
302                 }
303             }
304             return result;
305         }
306     }
307 
308     /**
309      * get all modem's registered.
310      */
getAllModems()311     public ArrayList<HardwareConfig> getAllModems() {
312         synchronized (mLock) {
313             ArrayList<HardwareConfig> modems = new ArrayList<HardwareConfig>();
314             if (mModems.isEmpty()) {
315                 if (DBG) logd("getAllModems: empty list.");
316             } else {
317                 for (HardwareConfig modem: mModems) {
318                     modems.add(modem);
319                 }
320             }
321 
322             return modems;
323         }
324     }
325 
326     /**
327      * get all sim's registered.
328      */
getAllSims()329     public ArrayList<HardwareConfig> getAllSims() {
330         synchronized (mLock) {
331             ArrayList<HardwareConfig> sims = new ArrayList<HardwareConfig>();
332             if (mSims.isEmpty()) {
333                 if (DBG) logd("getAllSims: empty list.");
334             } else {
335                 for (HardwareConfig sim: mSims) {
336                     sims.add(sim);
337                 }
338             }
339 
340             return sims;
341         }
342     }
343 }
344