/* * This file is part of Sensorium. * * Sensorium is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Sensorium is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Sensorium. If not, see * <http://www.gnu.org/licenses/>. * * */ package at.univie.sensorium.sensors; import java.io.PrintWriter; import java.io.StringWriter; import android.content.Context; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.telephony.CellLocation; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.util.Log; import at.univie.sensorium.SensorRegistry; public class RadioSensor extends AbstractSensor { private TelephonyManager telephonyManager; private PhoneStateListener phoneStateListener; private SensorValue mcc; private SensorValue mnc; private SensorValue cid; private SensorValue lac; private SensorValue networkpreference; private SensorValue networktype; private SensorValue signalstrength; private SensorValue subscriberid; private SensorValue roaming; private SensorValue servicestate; private SensorValue operator; public RadioSensor() { super(); setName("Radio Cell Information"); mcc = new SensorValue(SensorValue.UNIT.NUMBER, SensorValue.TYPE.MCC); mnc = new SensorValue(SensorValue.UNIT.NUMBER, SensorValue.TYPE.MNC); lac = new SensorValue(SensorValue.UNIT.NUMBER, SensorValue.TYPE.LAC); cid = new SensorValue(SensorValue.UNIT.NUMBER, SensorValue.TYPE.CID); networkpreference = new SensorValue(SensorValue.UNIT.STRING, SensorValue.TYPE.NETWORK_PREFERENCE); networktype = new SensorValue(SensorValue.UNIT.STRING, SensorValue.TYPE.NETWORKTYPE); signalstrength = new SensorValue(SensorValue.UNIT.DBM, SensorValue.TYPE.SIGNALSTRENGTH); roaming = new SensorValue(SensorValue.UNIT.OTHER, SensorValue.TYPE.ROAMING); servicestate = new SensorValue(SensorValue.UNIT.STRING, SensorValue.TYPE.SERVICESTATE); operator = new SensorValue(SensorValue.UNIT.STRING, SensorValue.TYPE.OPERATOR); subscriberid = new SensorValue(SensorValue.UNIT.STRING, SensorValue.TYPE.SUBSCRIBER_ID); } @Override protected void _enable() { telephonyManager = ((TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE)); GsmCellLocation gsmCell = (GsmCellLocation) telephonyManager.getCellLocation(); if (gsmCell != null) { String mccmnc = telephonyManager.getNetworkOperator(); mcc.setValue(mccmnc.substring(0, 3)); mnc.setValue(mccmnc.substring(3)); cid.setValue(gsmCell.getCid()); lac.setValue(gsmCell.getLac()); } setPreferredNetworkModeValue(); phoneStateListener = new PhoneStateListener() { @Override public void onServiceStateChanged(ServiceState serviceState) { super.onServiceStateChanged(serviceState); String state = ""; switch (serviceState.getState()) { case ServiceState.STATE_EMERGENCY_ONLY: state = "emergency calls only"; break; case ServiceState.STATE_IN_SERVICE: state = "in service"; break; case ServiceState.STATE_OUT_OF_SERVICE: state = "no service"; break; case ServiceState.STATE_POWER_OFF: state = "disabled"; break; } servicestate.setValue(state); operator.setValue(serviceState.getOperatorAlphaLong()); roaming.setValue(serviceState.getRoaming()); subscriberid.setValue(telephonyManager.getSubscriberId()); notifyListeners(); } @Override public void onCellLocationChanged(CellLocation location) { GsmCellLocation gsmCell = (GsmCellLocation) location; timestamp.setValue(System.currentTimeMillis()); String mccmnc = telephonyManager.getNetworkOperator(); if ((mccmnc == null || mccmnc.equals("")) || !servicestate.getValue().equals("in service")) { mcc.setValue("n/a"); mnc.setValue("n/a"); cid.setValue("n/a"); lac.setValue("n/a"); signalstrength.setValue("n/a"); networktype.setValue("n/a"); } else { mcc.setValue(mccmnc.substring(0, 3)); mnc.setValue(mccmnc.substring(3)); cid.setValue(gsmCell.getCid()); lac.setValue(gsmCell.getLac()); networktype.setValue(decodenetworktype(telephonyManager.getNetworkType())); } notifyListeners(); } @Override public void onSignalStrengthsChanged(SignalStrength sStrength) { // In GSM networks, ASU is equal to the RSSI // (received signal strength indicator, see TS 27.007). // dBm = 2 × ASU - 113, ASU in the range of 0..31 and 99 // In UMTS networks, ASU is equal the RSCP level // (received signal code power, see TS 25.125) // dBm = ASU - 116, ASU in the range of -5..91 int asu = sStrength.getGsmSignalStrength(); if (networktype.getValue().equals("GPRS") || networktype.getValue().equals("EDGE")) { signalstrength.setUnit(SensorValue.UNIT.DBM); if (asu < 31) { signalstrength.setValue(-113 + (asu * 2)); } else if (asu == 31) { signalstrength.setValue(">=51"); } else if (asu == 99) { signalstrength.setValue("not detectable"); } else { Log.d(SensorRegistry.TAG, "unexpected GSM signal strength value"); } } else if (networktype.getValue().equals("UMTS") || networktype.getValue().equals("HSPA") || networktype.getValue().equals("HSPA+") || networktype.getValue().equals("HSUPA") || networktype.getValue().equals("HSDPA")) { signalstrength.setUnit(SensorValue.UNIT.DBM); if (asu >= -5 && asu <= 91) { signalstrength.setValue(asu - 116); } } else { signalstrength.setUnit(SensorValue.UNIT.ASU); signalstrength.setValue(asu); } timestamp.setValue(System.currentTimeMillis()); GsmCellLocation gsmCell = (GsmCellLocation) telephonyManager.getCellLocation(); if (gsmCell != null) { String mccmnc = telephonyManager.getNetworkOperator(); mcc.setValue(mccmnc.substring(0, 3)); mnc.setValue(mccmnc.substring(3)); cid.setValue(gsmCell.getCid()); lac.setValue(gsmCell.getLac()); } notifyListeners(); } }; telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_SERVICE_STATE); } @Override protected void _disable() { if (telephonyManager != null) { telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); } } private void setPreferredNetworkModeValue() { try { // setting is not official sdk, may change without warning int value = Settings.Secure.getInt(getContext().getContentResolver(), "preferred_network_mode"); switch (value) { case (0): networkpreference.setValue("GSM/WCDMA preferred"); break; case (1): networkpreference.setValue("GSM only"); break; case (2): networkpreference.setValue("WCDMA only"); break; case (3): networkpreference.setValue("GSM/WCDMA auto"); break; case (4): networkpreference.setValue("CDMA/EVDO auto"); break; case (5): networkpreference.setValue("CDMA without EVDO"); break; case (6): networkpreference.setValue("EVDO only"); break; case (7): networkpreference.setValue("Global"); break; } } catch (SettingNotFoundException e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); Log.d(SensorRegistry.TAG, sw.toString()); } } private String decodenetworktype(int networkType) { switch (networkType) { case (TelephonyManager.NETWORK_TYPE_CDMA): return "CDMA"; case (TelephonyManager.NETWORK_TYPE_EDGE): return "EDGE"; case (TelephonyManager.NETWORK_TYPE_GPRS): return "GPRS"; case (TelephonyManager.NETWORK_TYPE_HSPA): return "HSPA"; case (TelephonyManager.NETWORK_TYPE_HSDPA): return "HSDPA"; case (TelephonyManager.NETWORK_TYPE_HSPAP): return "HSPA+"; case (TelephonyManager.NETWORK_TYPE_HSUPA): return "HSUPA"; case (TelephonyManager.NETWORK_TYPE_LTE): return "LTE"; case (TelephonyManager.NETWORK_TYPE_UMTS): return "UMTS"; case (TelephonyManager.NETWORK_TYPE_EVDO_0): case (TelephonyManager.NETWORK_TYPE_EVDO_A): case (TelephonyManager.NETWORK_TYPE_EVDO_B): return "EVDO"; case (TelephonyManager.NETWORK_TYPE_UNKNOWN): default: return "unknown"; } } }