blob: f97386df230e55fe7f364db035307b065eb2250a [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import com.android.telephony.Rlog;
import java.util.ArrayList;
import java.util.List;
/**
* TelephonyDevController - provides a unified view of the
* telephony hardware resources on a device.
*
* manages the set of HardwareConfig for the framework.
*/
public class TelephonyDevController extends Handler {
private static final String LOG_TAG = "TDC";
private static final boolean DBG = true;
private static final Object mLock = new Object();
private static final int EVENT_HARDWARE_CONFIG_CHANGED = 1;
private static TelephonyDevController sTelephonyDevController;
private static ArrayList<HardwareConfig> mModems = new ArrayList<HardwareConfig>();
private static ArrayList<HardwareConfig> mSims = new ArrayList<HardwareConfig>();
private static Message sRilHardwareConfig;
private static void logd(String s) {
Rlog.d(LOG_TAG, s);
}
private static void loge(String s) {
Rlog.e(LOG_TAG, s);
}
/** Create TelephonyDevController and set as singleton instance. */
public static TelephonyDevController create() {
synchronized (mLock) {
if (sTelephonyDevController != null) {
throw new RuntimeException("TelephonyDevController already created!?!");
}
sTelephonyDevController = new TelephonyDevController();
return sTelephonyDevController;
}
}
/** Get TelephonyDevController singleton. */
public static TelephonyDevController getInstance() {
synchronized (mLock) {
if (sTelephonyDevController == null) {
throw new RuntimeException("TelephonyDevController not yet created!?!");
}
return sTelephonyDevController;
}
}
private void initFromResource() {
Resources resource = Resources.getSystem();
String[] hwStrings = resource.getStringArray(
com.android.internal.R.array.config_telephonyHardware);
if (hwStrings != null) {
for (String hwString : hwStrings) {
HardwareConfig hw = new HardwareConfig(hwString);
if (hw != null) {
if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_MODEM) {
updateOrInsert(hw, mModems);
} else if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_SIM) {
updateOrInsert(hw, mSims);
}
}
}
}
}
private TelephonyDevController() {
initFromResource();
mModems.trimToSize();
mSims.trimToSize();
}
/**
* each RIL call this interface to register/unregister the unsolicited hardware
* configuration callback data it can provide.
*/
public static void registerRIL(CommandsInterface cmdsIf) {
/* get the current configuration from this ril... */
cmdsIf.getHardwareConfig(sRilHardwareConfig);
/* ... process it ... */
if (sRilHardwareConfig != null) {
AsyncResult ar = (AsyncResult) sRilHardwareConfig.obj;
if (ar.exception == null) {
handleGetHardwareConfigChanged(ar);
}
}
/* and register for async device configuration change. */
cmdsIf.registerForHardwareConfigChanged(sTelephonyDevController, EVENT_HARDWARE_CONFIG_CHANGED, null);
}
public static void unregisterRIL(CommandsInterface cmdsIf) {
cmdsIf.unregisterForHardwareConfigChanged(sTelephonyDevController);
}
/**
* handle callbacks from RIL.
*/
public void handleMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
case EVENT_HARDWARE_CONFIG_CHANGED:
if (DBG) logd("handleMessage: received EVENT_HARDWARE_CONFIG_CHANGED");
ar = (AsyncResult) msg.obj;
handleGetHardwareConfigChanged(ar);
break;
default:
loge("handleMessage: Unknown Event " + msg.what);
}
}
/**
* hardware configuration update or insert.
*/
private static void updateOrInsert(HardwareConfig hw, ArrayList<HardwareConfig> list) {
int size;
HardwareConfig item;
synchronized (mLock) {
size = list.size();
for (int i = 0 ; i < size ; i++) {
item = list.get(i);
if (item.uuid.compareTo(hw.uuid) == 0) {
if (DBG) logd("updateOrInsert: removing: " + item);
list.remove(i);
break;
}
}
if (DBG) logd("updateOrInsert: inserting: " + hw);
list.add(hw);
}
}
/**
* hardware configuration changed.
*/
private static void handleGetHardwareConfigChanged(AsyncResult ar) {
if ((ar.exception == null) && (ar.result != null)) {
List hwcfg = (List)ar.result;
for (int i = 0 ; i < hwcfg.size() ; i++) {
HardwareConfig hw = null;
hw = (HardwareConfig) hwcfg.get(i);
if (hw != null) {
if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_MODEM) {
updateOrInsert(hw, mModems);
} else if (hw.type == HardwareConfig.DEV_HARDWARE_TYPE_SIM) {
updateOrInsert(hw, mSims);
}
}
}
} else {
/* error detected, ignore. are we missing some real time configutation
* at this point? what to do...
*/
loge("handleGetHardwareConfigChanged - returned an error.");
}
}
/**
* get total number of registered modem.
*/
public static int getModemCount() {
synchronized (mLock) {
int count = mModems.size();
if (DBG) logd("getModemCount: " + count);
return count;
}
}
/**
* get modem at index 'index'.
*/
public HardwareConfig getModem(int index) {
synchronized (mLock) {
if (mModems.isEmpty()) {
loge("getModem: no registered modem device?!?");
return null;
}
if (index > getModemCount()) {
loge("getModem: out-of-bounds access for modem device " + index + " max: " + getModemCount());
return null;
}
if (DBG) logd("getModem: " + index);
return mModems.get(index);
}
}
/**
* get total number of registered sims.
*/
public int getSimCount() {
synchronized (mLock) {
int count = mSims.size();
if (DBG) logd("getSimCount: " + count);
return count;
}
}
/**
* get sim at index 'index'.
*/
public HardwareConfig getSim(int index) {
synchronized (mLock) {
if (mSims.isEmpty()) {
loge("getSim: no registered sim device?!?");
return null;
}
if (index > getSimCount()) {
loge("getSim: out-of-bounds access for sim device " + index + " max: " + getSimCount());
return null;
}
if (DBG) logd("getSim: " + index);
return mSims.get(index);
}
}
/**
* get modem associated with sim index 'simIndex'.
*/
public HardwareConfig getModemForSim(int simIndex) {
synchronized (mLock) {
if (mModems.isEmpty() || mSims.isEmpty()) {
loge("getModemForSim: no registered modem/sim device?!?");
return null;
}
if (simIndex > getSimCount()) {
loge("getModemForSim: out-of-bounds access for sim device " + simIndex + " max: " + getSimCount());
return null;
}
if (DBG) logd("getModemForSim " + simIndex);
HardwareConfig sim = getSim(simIndex);
for (HardwareConfig modem: mModems) {
if (modem.uuid.equals(sim.modemUuid)) {
return modem;
}
}
return null;
}
}
/**
* get all sim's associated with modem at index 'modemIndex'.
*/
public ArrayList<HardwareConfig> getAllSimsForModem(int modemIndex) {
synchronized (mLock) {
if (mSims.isEmpty()) {
loge("getAllSimsForModem: no registered sim device?!?");
return null;
}
if (modemIndex > getModemCount()) {
loge("getAllSimsForModem: out-of-bounds access for modem device " + modemIndex + " max: " + getModemCount());
return null;
}
if (DBG) logd("getAllSimsForModem " + modemIndex);
ArrayList<HardwareConfig> result = new ArrayList<HardwareConfig>();
HardwareConfig modem = getModem(modemIndex);
for (HardwareConfig sim: mSims) {
if (sim.modemUuid.equals(modem.uuid)) {
result.add(sim);
}
}
return result;
}
}
/**
* get all modem's registered.
*/
public ArrayList<HardwareConfig> getAllModems() {
synchronized (mLock) {
ArrayList<HardwareConfig> modems = new ArrayList<HardwareConfig>();
if (mModems.isEmpty()) {
if (DBG) logd("getAllModems: empty list.");
} else {
for (HardwareConfig modem: mModems) {
modems.add(modem);
}
}
return modems;
}
}
/**
* get all sim's registered.
*/
public ArrayList<HardwareConfig> getAllSims() {
synchronized (mLock) {
ArrayList<HardwareConfig> sims = new ArrayList<HardwareConfig>();
if (mSims.isEmpty()) {
if (DBG) logd("getAllSims: empty list.");
} else {
for (HardwareConfig sim: mSims) {
sims.add(sim);
}
}
return sims;
}
}
}