org.restcomm.app.qoslib.Utils.QosInfo.java Source code

Java tutorial

Introduction

Here is the source code for org.restcomm.app.qoslib.Utils.QosInfo.java

Source

/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2016, Telestax Inc and individual contributors
 * by the @authors tag.
 *
 * This program is free software: you can redistribute it and/or modify
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 * For questions related to commercial use licensing, please contact sales@telestax.com.
 *
 */

package org.restcomm.app.qoslib.Utils;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.format.DateFormat;

import org.restcomm.app.utillib.ContentProvider.Provider;
import org.restcomm.app.utillib.ContentProvider.Tables;
import org.restcomm.app.utillib.ContentProvider.UriMatch;
import org.restcomm.app.utillib.DataObjects.PhoneState;
import org.restcomm.app.utillib.Reporters.ReportManager;
import org.restcomm.app.utillib.Utils.CommonIntentActionsOld;
import org.restcomm.app.utillib.Utils.LoggerUtil;

import org.json.JSONObject;

import java.lang.reflect.Method;
import java.sql.Date;
import java.util.BitSet;
import org.restcomm.app.qoslib.R;

/**
 * QosInfo is a class that consolidates a wide variety of information about the network state of the phone.
 * The information originated from several sources such as apis, listeners, hidden methods and possibly even service mode.
 * QosInfo contains 4 inner classes representing the main network types, and each is only populated if in that network type
 * <ul>
 * <li>GSMInfo
 * <li>WiFiInfo
 * <li>LTEInfo
 * <li>CDMAInfo
 * <li>plus general info in main class
 * </ul>
 * <p>
 *
 * @author      Brad Scheurman
 * @version     %I%, %G%
 * @since       1.0
 */
public class QosInfo {

    Context context;
    public static final String TAG = QosInfo.class.getSimpleName();

    public QosInfo(Context cxt) {
        context = cxt;
        updateFromDB();
    }

    private static String[][] keys = {
            { "Time", "Network", "Data", "LTE RSSI", "RSSI", "CDMA RSSI", "LTE RSRP", "LTE RSRQ", "LTE SNR",
                    "LTE CQI", "EC/I0", "EC/N0", "RSCP", "SNR", "BER", "RRC", "ARFCN" },
            { "MCC", "MNC", "SID", "NID", "BID", "LAC", "RNC", "Cell ID", "PSC", "Lat", "Lng", "Tac", "Pci", "Ci",
                    "Band" } };

    public String Time, Carrier, Data, RRC;
    private int LTE_RSSI, RSSI, CDMA_RSSI, LTE_RSRP, LTE_RSRQ;
    private float LTE_SNR;
    private int LTE_CQI, ECIO, ECNO, RSCP, SNR, ARFCN;
    private int SID, NID, BID, LAC, RNC, CellID, PSC, Lat, Lng;
    private int Tac, Pci, Ci;
    private String Neighbors;
    public int Satellites;
    private String LTEIdentity;
    private int WifiSec, WifiFreq, WifiSig;
    private long WifiID;
    Location location;
    public int Band, Channel;
    public int MCC, MNC;

    /**
     * Specific information about the CDMA network if CDMA is active, otherwise this object is null
     */
    public CDMAInfo CDMAInfo;

    /**
     * Specific information about the 2G GSM network such as GPRS or EDGE if 2G active, otherwise this object is null
     */
    public GSMInfo GSMInfo;

    /**
     * Specific information about the 3G WCDMA network such as UMTS or HSPA if 3G active, otherwise this object is null
     */
    public WCDMAInfo WCDMAInfo;

    /**
     * Specific information about the LTE network if LTE is active, otherwise this object is null
     */
    public LTEInfo LTEInfo;

    /**
     * Specific information about the WiFi network if WiFi is active, otherwise this object is null
     */

    public WIFIInfo WiFiInfo;
    /**
     * The connectedNetwork represents the network that is currently connected, whether it be LTE, WiFi etc..
     * As a NetworkInfo object, it can be used in a unified way to access relevant info about the network.
     * For example: If CDMA, LTE and WiFi are active at the same time, the connectedNetwork is WiFi, because that is the only network in use for data connections.
     */
    public NetworkInfo connectedNetwork;

    /**
     * NetworkInfo is meant to be used directly to simplify access to information about the connected network.
     * NetworkInfo is also the base class for all of the main types of data network including LTEInfo, WiFiInfo, etc.
     * The {@link NetworkInfo connectedNetwork} object is a NetworkInfo object.
     *
     * NetworkInfo provides a signal indicator, quality indicator, and an array of all the cellular identifiers.
     * The signal indicator consists of a label such as 'RSSI' or 'RSRP' to describe the measurement the represents signal strength for the current type of network.
     *
     */
    public class NetworkInfo {
        protected int signal = 0;
        protected int sigMin = 0, sigMax = 0;
        protected int sigExcellent = 0; // the minimum signal strength that would be considered as excellent
        protected String sigLabel = "", sigUnits = "";
        protected String sigDoc = "";

        protected float noise = 0;
        protected int noiseMin = 0, noiseMax = 0;
        protected int noiseExcellent; // the minimum signal strength that would be considered as excellent
        protected String noiseLabel = "", noiseUnits = "";
        protected String noiseDoc = "";

        protected String[] identifierLabels, identifierDocs;
        protected long[] identifierValues;
        protected String networkType;

        /**
         *  Easy to understand rating for the signal type for the connected network.
         *
         *  @return rating from 0 to 5, equivalent to 'bars' where 5 bars is an excellent signal level
         */
        public int getSignalRating() {
            // calculate a rating from 0 to 5

            // unknown signal is rated as -1 and should be ignored
            if (signal == 0)
                return -1;
            // anything <= sigMin is rated as 0 for no signal
            if (signal <= sigMin)
                return 0;
            // anything >= sigExcellent is rated as 5
            if (signal >= sigExcellent)
                return 5;

            // all others are scaled from 1 to 4
            int quarter = (sigExcellent - sigMin) / 4;
            int rating = 1 + (signal - sigMin) * 4 / (sigExcellent - sigMin);
            return rating;

        }

        /**
         * getSignalDetails returns a text description of the signal type for the connected network.
         * the text is composed of the signalLabel and, optionally, the value, rating and units.
         * @param withValue  to include the dBm value of the signal  {@link int getSignal ()} and its units {@link String getSignalUnits ()}
         * @param withRating to include the rating of the signal {@link int getSignalRating ()}
         * @return the full text description
         */
        public String getSignalDetails(boolean withValue, boolean withRating) {
            if (getSignalLabel() == "")
                return "";
            String details = getSignalLabel() + ": ";
            if (withValue) {
                if (signal != 0)
                    details += signal + " " + getSignalUnits();
                else
                    details += "unknown";
            }
            if (withRating && signal != 0 && getSignalRating() > 0)
                details += " rating " + getSignalRating() + "/5";
            return details;
        }

        /**
         * Get the name of the type of signal for the connected network.
         * The label, units and ranges are defined in the constructor for each derived class.
         * @return the name of the relevent type of signal (RSSI, RSRP etc)
         */
        public String getSignalLabel() {
            return sigLabel;
        }

        /**
         * Get the unit for the type of signal for the connected network.
         * @return the unit for the relevent type of signal (usually dBm)
         */
        public String getSignalUnits() {
            return sigUnits;
        }

        /**
         * Get the minimum value of the signal range.
         * @return the minimum signal value (usually -120 dBm)
         */
        public int getSignalRangeMin() {
            return sigMin;
        }

        /**
         * Get the maximum value of the signal range.
         * @return the maximum signal value (usually -40 dBm)
         */
        public int getSignalRangeMax() {
            return sigMax;
        }

        /**
         * Get the value of the signal that gives excellent performance, expected near the tower.
         * Values above excellent are rated as 5 bars.
         * Each derived network type sets its range. RSRP -85 dBm is 'excellent' for LTE.
         * @return the excellent signal value
         */
        public int getSignalRangeExcellent() {
            return sigExcellent;
        }

        /**
         * Get a short documentation of the relevent type of signal for the network.
         * @return the description document
         */
        public String getSignalDoc() {
            return sigDoc;
        }

        /**
         * Get the actual value of the signal.
         * @return the signal value (usually -40 to -120)
         */
        public int getSignal() {
            return signal;
        }

        /**
         * Get the actual value of the noise or quality indicator.
         * Some network types can provide an additional performance indicator.
         * This is usually a measure of noise and is a good indicator or data throughput or voice quality.
         * @return the indicator value
         */
        public float getQuality() {
            return noise;
        }

        /**
         *  Easy to understand rating for the signal type for the connected network.
         *
         *  @return rating from 0 to 5, equivalent to 'bars' where 5 bars is an excellent signal level.
         */
        public int getQualityRating() {
            // calculate a rating from 0 to 5

            // unknown signal is rated as -1 and should be ignored
            if (noise == 0)
                return -1;
            // anything <= sigMin is rated as 0 for no signal
            if (noise <= noiseMin)
                return 0;
            // anything >= sigExcellent is rated as 5
            if (noise >= noiseExcellent)
                return 5;

            // all others are scaled from 1 to 4
            int quarter = (noiseExcellent - noiseMin) / 4;
            int rating = 1 + (int) (noise * 10 - noiseMin * 10) * 4 / (int) (noiseExcellent * 10 - noiseMin * 10);
            return rating;

        }

        /**
         * getQualityDetails returns a text description of the main noise/quality indicator, if available, for the connected network.
         * The text is composed of the qualityLabel and, optionally, the value, rating and units.
         * @param withValue  to include the value of the quality indicator  {@link int getQuality ()} and its units {@link String getQualityUnits ()}
         * @param withRating to include the rating of the quality indicator {@link int getQualityRating ()}
         * @return
         */
        public String getQualityDetails(boolean withValue, boolean withRating) {
            if (getQualityLabel() == "")
                return "";
            String details = getQualityLabel() + ": ";
            if (withValue) {
                if (noise != 0)
                    details += noise + " " + getQualityUnits() + " ";
                else
                    details += "unknown ";
            }
            if (withRating && noise != 0 && getQualityRating() >= 0)
                details += "rating " + getQualityRating() + "/5";

            return details;
        }

        /**
         * Get the name of the type of quality/noise indicator the connected network.
         * The label, units and ranges are defined in the constructor for each derived class.
         * @return the name of the indicator for the connected network (Ec/i0, SNR etc)
         */
        public String getQualityLabel() {
            return noiseLabel;
        }

        /**
         * Get the unit for the type of quality/noise indicator for the connected network
         * @return the unit for the connected network (may be unitless and return a blank string)
         */
        public String getQualityUnits() {
            return noiseUnits;
        }

        /**
         * Get the minimum value of the range for the main quality/noise indicator
         * @return the minimum value (usually -30 for Ec/i0 or -10 for SNR)
         */
        public int getQualityRangeMin() {
            return noiseMin;
        }

        /**
         * Get the maximum value of the range for the main quality/noise indicator
         * @return the maximum signal value (usually -40 dBm)
         */
        public int getQualityRangeMax() {
            return noiseMax;
        }

        /**
         * Get the value of the main quality/noise indicator that gives excellent performance, expected near the tower
         * Values above excellent are rated as 5 bars
         * set for each derived network type, SNR 20 dBm is 'excellent' for LTE
         * @return the excellent signal value
         */
        public int getQualityRangeExcellent() {
            return sigMax;
        }

        /**
         * Get a short documentation of the relevent type of signal for the network
         * @return the description document
         */
        public String getQualityDoc() {
            return noiseDoc;
        }

        /**
         * getIdentifier returns a text description of the Base Station's full Identifier
         * For example a full 3G cell identifier consists of LAN,RNC,CellID and PSC
         * Each derived Network type defines an array of labels, values and doc descriptions to represent
         * all the components to be appended for getIdentifier
         * @return the full text description to indentify the current base station
         */
        public String getIdentifier() {
            String identifiers = "";

            int i;
            if (identifierValues != null && identifierLabels != null) {
                for (i = 0; i < identifierValues.length; i++) {
                    if (i < identifierLabels.length) {
                        identifiers += identifierLabels[i] + ": ";
                        if (identifierValues[i] == 0)
                            identifiers += "n/a ";
                        else
                            identifiers += identifierValues[i] + " ";
                    }
                }
            }
            return identifiers;
        }

        /**
         * Get the array of names of the Identifier parts defined for the current Network type
         * @return the array of labels
         */
        public String[] getIdentifierLabels() {
            return identifierLabels;
        };

        /**
         * Get the array of values for the Identifier parts defined for the current Network type
         * @return the array of values
         */
        public long[] getIdentifierValues() {
            return identifierValues;
        };

        /**
         * Get the array of docs for the Identifier parts defined for the current Network type
         * @return the array of values
         */
        public String[] getIdentifierDocs() {
            return identifierDocs;
        };

        /**
         * Get the name of the type of network
         * @return the type of network
         */
        public String getType() {
            return networkType;
        }

        /**
         * Get the type of technology for the connected network
         * @return the type of network
         */
        public String getTechnology() {
            return Data;
        }
    }

    /**
     * CDMAInfo exposes information relevant to CDMA Networks
     * <ul>
     * <li>SID
     * <li>BID
     * <li>NID
     * <li>RSSI
     * <li>ECI0 (Ec/n0)
     * <li>SNR
     * </ul>
     */
    public class CDMAInfo extends NetworkInfo {
        public int BID = 0, SID = 0, NID = 0, RSSI = 0, ECIO = 0, SNR = 0;

        /**
         * Initialize all the special labels, units, value ranges appropriate for the CDMA type of network
        */
        public CDMAInfo(QosInfo qos) {
            SID = qos.SID;
            BID = qos.BID;
            NID = qos.NID;
            RSSI = qos.CDMA_RSSI;
            ECIO = qos.ECIO;
            SNR = qos.SNR;

            // base class assignments to describe LTE info in a unified way
            networkType = "CDMA";
            signal = qos.RSSI;
            sigLabel = "RSCP";
            sigUnits = "dBm";
            sigDoc = "RSSI gives the total power of all received signal (Receive Signal Strength Indicator). RSSI includes noise enery, but subtracting Ec/i0 from RSSI gives the actual usable signal.";
            sigMax = -40;
            sigMin = -120;
            sigExcellent = -65;

            noise = qos.ECIO;
            noiseLabel = "Ec/iO";
            noiseUnits = "dB";
            noiseDoc = "Ec/iO gives a ratio expressed in dBs of signal to noise and/or interference (Energy/interference). ";
            noiseMax = -2;
            noiseMin = -22;
            noiseExcellent = -6;

            identifierLabels = new String[] { "SID", "NID", "BID" };
            identifierDocs = new String[] {
                    "SID is the 'System ID' which identifies a region of towers, unique worldwide",
                    "NID is the 'Network ID'",
                    "BID is the 'Billing ID' which Uniquely identifies a cell tower, sector and band within a SID and NID" };
            identifierValues = new long[] { SID, NID, BID };
        }

        @Override
        public String toString() {
            String str = "CDMA Info:" + "\n";
            str += "SID: " + SID + "\n";
            str += "NID: " + NID + "\n";
            str += "BID: " + BID + "\n";
            str += "RSSI: " + RSSI + "\n";
            if (ECIO < 0)
                str += "ECIO: " + ECIO + "\n";
            if (SNR != 0)
                str += "SNR: " + SNR + "\n";
            return str;
        }
    }

    /**
     * GSMInfo exposes information relevant to 2G GSM Networks such as GPRS and EDGE
     * <ul>
     * <li>LAC
     * <li>CellID
     * <li>RSSI
     * <li>ECI0 (Ec/n0)
     * </ul>
     */
    public class GSMInfo extends NetworkInfo {
        public int LAC = 0, RNC = 0, CellID = 0, PSC = 0;
        public int RSCP = 0, ECIO = 0;

        /**
         * Initialize all the special labels, units, value ranges appropriate for the 2G GSM type of network
         */
        public GSMInfo(QosInfo qos) {
            LAC = qos.LAC;
            CellID = qos.CellID;
            RSSI = qos.RSSI;

            // base class assignments to describe LTE info in a unified way
            networkType = "2G GSM";
            signal = qos.RSSI;
            sigLabel = "RSSI";
            sigUnits = "dBm";
            sigDoc = "RSSI gives the total power of all received signal (Receive Signal Strength Indicator). A stronger signal is better, but noise and signal from other cell sectors is included in the total RSSI.";
            sigMax = -40;
            sigMin = -120;
            sigExcellent = -65;

            identifierLabels = new String[] { "LAC", "CellId" };
            identifierDocs = new String[] { "Local Area Code, identifies a group of cell towers",
                    "Cell Id uniquely identifies a cell tower, sector and band when combined with LAC" };
            identifierValues = new long[] { LAC, CellID };
        }

        @Override
        public String toString() {
            String str = "GSM Info:" + "\n";
            str += "LAC: " + LAC + "\n";
            str += "RNC: " + RNC + "\n";
            str += "CellID: " + CellID + "\n";
            str += "PSC: " + PSC + "\n";
            if (RSCP < 0)
                str += "RSCP: " + RSCP + "\n";
            else
                str += "RSSI: " + RSSI + "\n";
            if (ECIO < 0)
                str += "EC/I0: " + ECIO + "\n";
            if (Neighbors != null && !Neighbors.isEmpty())
                str += "Neighbors: " + Neighbors;
            return str;
        }
    }

    /**
     * WCDMAInfo exposes information relevant to 3G Networks such as UMTS and HSDPA
     * <ul>
     * <li>LAC
     * <li>RNC
     * <li>CellID
     * <li>PSC
     * <li>RSCP
     * <li>ECI0 (Ec/n0)
     * <li>SNR
     * </ul>
     */
    public class WCDMAInfo extends NetworkInfo {
        public int LAC = 0, RNC = 0, CellID = 0, PSC = 0;
        public int RSCP = 0, ECIO = 0;

        /**
         * Initialize all the special labels, units, value ranges appropriate for the 3G WCDMA type of network
         */
        public WCDMAInfo(QosInfo qos) {
            LAC = qos.LAC;
            RNC = qos.RNC;
            CellID = qos.CellID;
            PSC = qos.PSC;
            RSCP = qos.RSCP;
            ECIO = qos.ECIO;
            Neighbors = qos.Neighbors;

            // base class assignments to describe LTE info in a unified way
            networkType = "3G GSM";
            signal = qos.RSCP;
            sigLabel = "RSCP";
            sigUnits = "dBm";
            sigDoc = "RSCP gives the power of the usable component of 3G signal (Receive Signal Code Power). It is lower compared to the RSSI because it measures a specific part of the signal that carries data.";
            sigMax = -40;
            sigMin = -120;
            sigExcellent = -75;

            noise = qos.ECIO;
            noiseLabel = "Ec/iO";
            noiseUnits = "dB";
            noiseDoc = "Ec/iO gives a ratio expressed in dBs of signal to noise and/or interference (Energy/interference). Android rarely reports Ec/i0 for GSM, except on some rooted devices";
            noiseMax = -2;
            noiseMin = -22;
            noiseExcellent = -6;

            identifierLabels = new String[] { "LAC", "RNC", "CellId", "PSC" };
            identifierDocs = new String[] { "Local Area Code, identifies a group of cell towers",
                    "RNC Radio Network Controller is the top 12 bits of a 28 bit Cell Identifier",
                    "Cell Id is the bottom 16 bits of a 28 bit Cell identifier in 3G. Uniquely identifies a cell tower, sector and band when combined with LAC",
                    "PSC Primary Scrambling Code, short non-unique cell identifier" };
            identifierValues = new long[] { LAC, RNC, CellID, PSC };
        }

        @Override
        public String toString() {
            String str = "GSM Info:" + "\n";
            str += "LAC: " + LAC + "\n";
            str += "RNC: " + RNC + "\n";
            str += "CellID: " + CellID + "\n";
            str += "PSC: " + PSC + "\n";
            if (RSCP < 0)
                str += "RSCP: " + RSCP + "\n";
            else
                str += "RSSI: " + RSSI + "\n";
            if (ECIO < 0)
                str += "EC/I0: " + ECIO + "\n";
            if (Neighbors != null && !Neighbors.isEmpty())
                str += "Neighbors: " + Neighbors;
            return str;
        }
    }

    /**
     * LTEInfo exposes information relevant to LTE Networks
     * <ul>
     * <li>RSSI
     * <li>RSRP (main signal indicator)
     * <li>RSRQ
     * <li>SNR (main quality indicator)
     * <li>Base Station Identifiers
     * <li>Tac
     * <li>Ci
     * <li>Pci
     * <li>SNR
     * </ul>
     */
    public class LTEInfo extends NetworkInfo {
        public int RSSI, RSRP, RSRQ;
        public float SNR;
        public int Tac, Pci, Ci;
        public String LTEIdentity;

        /**
         * Initialize all the special labels, units, value ranges appropriate for the LTE type of network
         */
        public LTEInfo(QosInfo qos) {
            RSSI = qos.LTE_RSSI;
            RSRP = qos.LTE_RSRP;
            RSRQ = qos.LTE_RSRQ;
            SNR = qos.LTE_SNR;
            LTEIdentity = qos.LTEIdentity;
            // LTEIdentity =  "LTE Tac:" + tac + " Ci:" + ci + " pCi:" + pci + " eNB:" + eNB + "/" + cellid;
            if (LTEIdentity != null) {
                int pos = LTEIdentity.indexOf("Tac:");
                int pos2 = LTEIdentity.indexOf(" Ci:");
                String val = LTEIdentity.substring(pos + 4, pos2);
                Tac = Integer.parseInt(val);

                pos = pos2;
                pos2 = LTEIdentity.indexOf(" pCi:");
                val = LTEIdentity.substring(pos + 4, pos2);
                Ci = Integer.parseInt(val);

                pos = pos2;
                pos2 = LTEIdentity.indexOf(" eNB:");
                if (pos2 <= 0)
                    pos2 = LTEIdentity.length();
                val = LTEIdentity.substring(pos + 5, pos2);
                Pci = Integer.parseInt(val);
            } else {
                Tac = qos.LAC;
                Ci = qos.CellID + (qos.RNC << 16);
                Pci = qos.PSC;
            }

            // base class assignments to describe LTE info in a unified way
            networkType = "LTE";
            signal = qos.LTE_RSRP;
            sigLabel = "RSRP";
            sigUnits = "dBm";
            sigDoc = "RSRP gives the power of the reference component of LTE signal (Reference Signal Receive Power). It is about 20 dBm lower compared to the RSSI because it measures a specific part of the signal that carries data.";
            sigMax = -40;
            sigMin = -122;
            sigExcellent = -80;

            noise = qos.LTE_SNR;
            if (noise == 0)
                noise = 0.1f;
            noiseLabel = "SINR";
            noiseUnits = "";
            noiseDoc = "SINR gives the ratio of signal to noise+interference (Signal to Interference+Noise Ratio). SINR is a good predictor data bit rate.";
            noiseMax = 30;
            noiseMin = -5;
            noiseExcellent = 20;

            identifierLabels = new String[] { "Tac", "Ci", "Pci" };
            identifierDocs = new String[] { "Tracking Area Code, like a GSM LAC", "Cell Id",
                    "Physical cell id, 0-504, not unique" };
            identifierValues = new long[] { Tac, Ci, Pci };
        }

        @Override
        public String toString() {
            String str = "LTE Info:" + "\n";
            str += "Tac: " + Tac + "\n";
            str += "Ci: " + Ci + "\n";
            str += "Pci: " + Pci + "\n";
            str += "RSRP: " + RSRP + "\n";
            str += "SNR: " + SNR + "\n";
            if (RSRQ < 0)
                str += "RSRQ: " + RSRQ + "\n";
            return str;
        }
    }

    /**
     * WIFIInfo exposes information relevant to WiFi Networks
     * <ul>
     * <li>RSSI (main signal indicator)
     * <li>(no quality indicator)
     * <li>Base Station Identifiers
     * <li>WifiID
     * </ul>
     */
    public class WIFIInfo extends NetworkInfo {
        public int RSSI = 0;
        public int Frequency = 0;
        public long WifiID = 0;

        /**
         * Initialize all the special labels, units, value ranges appropriate for the WiFi type of network
         */
        public WIFIInfo(QosInfo qos) {
            RSSI = qos.WifiSig;
            Frequency = qos.WifiFreq;
            WifiID = qos.WifiID;

            // base class assignments to describe WiFi info in a unified way
            networkType = "WiFi";
            signal = RSSI;
            sigLabel = "RSSI";
            sigUnits = "dBm";
            sigDoc = "RSSI gives the overall power of the WiFi signal (Received Signal Strength Indicator)";
            sigMax = -40;
            sigMin = -120;
            sigExcellent = -65;
            identifierLabels = new String[] { "BSSID" };
            identifierDocs = new String[] {
                    "BSSID is a unique number identifying the WiFi access point (Basic Service Set Identifier)" };
            identifierValues = new long[] { WifiID };
        }

        @Override
        public String toString() {
            String str = "WIFI Info:" + "\n";
            str += "RSSI: " + RSSI + "\n";
            str += "Frequency: " + Frequency + "\n";
            str += "WifiID: " + WifiID + "\n";
            return str;
        }
    }

    /**
     * Called Internally to initialize all of the current measurements for every type of connected newtork
     * This is like a snapshot of everything at this moment in time
     * The information comes from various sources and it mainly fetched from the database for this call, or from APIs such as WiFi
     */
    private void updateFromDB() {
        Cursor sig_cursor = null;
        Cursor cell_cursor = null;

        try {
            Uri signalUri = UriMatch.SIGNAL_STRENGTHS.getContentUri();
            Uri limitSignalUri = signalUri.buildUpon().appendQueryParameter("limit", "1").build();
            // sig_cursor = managedQuery(

            Provider dbProvider = ReportManager.getInstance(context.getApplicationContext()).getDBProvider();
            if (dbProvider == null) {
                return;
            }

            sig_cursor = dbProvider.query(UriMatch.SIGNAL_STRENGTHS.getContentUri(), null, null, null,
                    Tables.TIMESTAMP_COLUMN_NAME + " DESC");

            sig_cursor.moveToFirst();

            Uri baseStationTable = (UriMatch.BASE_STATIONS
                    .getContentUri()/*telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA
                                    ? UriMatchOld.BASE_STATIONS_CDMA.getContentUri()
                                    : UriMatchOld.BASE_STATIONS_GSM.getContentUri()*/
            );
            Uri limitBSUri = baseStationTable.buildUpon().appendQueryParameter("limit", "1").build();

            // Cursor cell_cursor = managedQuery(
            cell_cursor = dbProvider.query(limitBSUri, null, null, null, Tables.TIMESTAMP_COLUMN_NAME + " DESC");

            cell_cursor.moveToFirst();

            int LowIndex = cell_cursor.getColumnIndex(Tables.BaseStations.BS_LOW);
            int MidIndex = cell_cursor.getColumnIndex(Tables.BaseStations.BS_MID);
            int HighIndex = cell_cursor.getColumnIndex(Tables.BaseStations.BS_HIGH);
            int CodeIndex = cell_cursor.getColumnIndex(Tables.BaseStations.BS_CODE);
            int BandIndex = cell_cursor.getColumnIndex(Tables.BaseStations.BS_BAND);
            int ChanIndex = cell_cursor.getColumnIndex(Tables.BaseStations.BS_CHAN);
            int netTypeIndex = cell_cursor.getColumnIndex(Tables.BaseStations.NET_TYPE);
            String netType = cell_cursor.getString(netTypeIndex);
            int bsLow = cell_cursor.getInt(LowIndex);
            int bsMid = cell_cursor.getInt(MidIndex);
            int bsHigh = cell_cursor.getInt(HighIndex);
            int bsCode = cell_cursor.getInt(CodeIndex);
            int bsBand = cell_cursor.getInt(BandIndex);
            int bsChan = cell_cursor.getInt(ChanIndex);
            if (netType.equals("cdma")) {
                if (LowIndex != -1)
                    BID = bsLow;
                if (MidIndex != -1)
                    NID = bsMid;
                if (HighIndex != -1)
                    SID = bsHigh;
            } else if (netType.equals("gsm")) {
                if (LowIndex != -1) {
                    RNC = bsMid;
                    CellID = cell_cursor.getInt(LowIndex);
                }
                // the network Id is kept 0 for gsm phones
                if (HighIndex != -1)
                    LAC = bsHigh;
                if (bsCode > 0 && bsCode < 1000)
                    PSC = bsCode;
                else
                    PSC = 0;
                if (bsBand > 0)
                    Band = bsBand;
                else
                    Band = 0;
                if (bsChan > 0)
                    Channel = bsChan;
                else
                    Channel = 0;
            }

            if (sig_cursor.getCount() != 0) {
                int signalIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.SIGNAL);
                int signal2GIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.SIGNAL2G);
                int rsrpIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.LTE_RSRP);
                int rsrqIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.LTE_RSRQ);
                int lteSnrIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.LTE_SNR);
                int lteSignalIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.LTE_SIGNAL);
                int lteCqiIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.LTE_CQI);
                int ecioIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.ECI0);
                int ecnoIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.ECN0);
                int snrIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.SNR);
                int berIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.BER);
                int rscpIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.RSCP);
                int tierIndex = sig_cursor.getColumnIndex(Tables.SignalStrengths.COVERAGE);
                Integer tier = sig_cursor.isNull(tierIndex) ? null : sig_cursor.getInt(tierIndex);
                Integer rssi = sig_cursor.isNull(signalIndex) ? null : sig_cursor.getInt(signalIndex);
                Integer rssi2G = sig_cursor.isNull(signal2GIndex) ? null : sig_cursor.getInt(signal2GIndex);
                Integer rsrp = sig_cursor.isNull(rsrpIndex) ? null : sig_cursor.getInt(rsrpIndex);
                Float lteSnr = (sig_cursor.isNull(lteSnrIndex) ? null : (float) sig_cursor.getInt(lteSnrIndex));
                Integer lteSignal = sig_cursor.isNull(lteSignalIndex) ? null : sig_cursor.getInt(lteSignalIndex);
                Integer lteCqi = sig_cursor.isNull(lteCqiIndex) ? null : sig_cursor.getInt(lteCqiIndex);
                Integer rsrq = sig_cursor.isNull(rsrqIndex) ? null : sig_cursor.getInt(rsrqIndex);
                Integer eci0 = sig_cursor.isNull(ecioIndex) ? null : sig_cursor.getInt(ecioIndex);
                Integer ecn0 = sig_cursor.isNull(ecnoIndex) ? null : sig_cursor.getInt(ecnoIndex);
                Integer snr = sig_cursor.isNull(snrIndex) ? null : sig_cursor.getInt(snrIndex);
                Integer ber = sig_cursor.isNull(berIndex) ? null : sig_cursor.getInt(berIndex);
                Integer rscp = sig_cursor.isNull(rscpIndex) ? null : sig_cursor.getInt(rscpIndex);

                if (eci0 != null && (netType.equals("cdma") || netType.equals("lte")) && eci0 <= -30)
                    eci0 = (eci0 / 10);
                else if (ecn0 != null && ecn0 > 1 && ecn0 < 60 && netType.equals("gsm"))
                    ecn0 = -(ecn0 / 2);
                else if (eci0 != null && eci0 > 1 && eci0 < 60 && netType.equals("gsm"))
                    eci0 = -(eci0 / 2);

                // if (lteSnr != null && lteSnr > 1 && lteSnr < 500)
                // lteSnr = (lteSnr+5)/10;
                if (lteSignal != null && lteSignal > -120 && lteSignal < -20) // rssi == lteSignal)
                {
                    LTE_RSSI = simpleValidate(lteSignal);
                    RSSI = 0;
                } else if (rssi == null || rssi == -255)
                    RSSI = 0;
                else if (rssi == -256)
                    RSSI = -256;
                else {
                    String name = "RSCP: ";
                    int spacing = 15;
                    if (netType.equals("gsm") && (tier == 3 || tier == 4)) {
                        RSCP = rssi;
                        RSSI = 0;
                    } else {
                        RSSI = rssi;
                        RSCP = 0;
                    }

                    LTE_RSSI = 0;
                }
                if (netType.equals("cdma") && rssi2G != null && rssi2G < -30 && rssi2G >= -120)
                    CDMA_RSSI = rssi2G;
                if (tier == 5) {
                    if (lteSnr != null && lteSnr > -101)
                        lteSnr = lteSnr / 10;
                    if (rsrq != null && rsrq > 0)
                        rsrq = -rsrq;
                    LTE_RSRP = simpleValidate(rsrp);
                    LTE_RSRQ = simpleValidate(rsrq);
                    LTE_SNR = simpleValidate(lteSnr);
                    LTE_CQI = simpleValidate(lteCqi);
                    ECIO = simpleValidate(eci0);
                    ECNO = simpleValidate(ecn0);
                }
                //nerdview.setValue(0, "RSCP", simpleValidate(rscp, "RSCP", "dBm"));
                //BER = simpleValidate(ber);
                SNR = simpleValidate(snr);

                if (rsrp != null && rsrp <= -10 && rsrp >= -140 && tier == 5) {
                    LTEIdentity = ReportManager.getInstance(context.getApplicationContext()).getNeighbors();
                } else {
                    LTEIdentity = null;
                    Neighbors = ReportManager.getInstance(context.getApplicationContext()).getNeighbors();
                }
            }
            location = ReportManager.getInstance(context.getApplicationContext()).getLastKnownLocation();

            try {
                JSONObject serviceMode = PhoneState.getServiceMode();
                if (serviceMode != null && serviceMode.getLong("time") + 5000 > System.currentTimeMillis()) {
                    if (serviceMode.has("rrc") && serviceMode.getString("rrc").length() > 1) {
                        RRC = serviceMode.getString("rrc");
                    } else
                        RRC = null;
                    if (serviceMode.has("band") && serviceMode.getString("band").length() > 0) {
                        Band = Integer.parseInt(serviceMode.getString("band"));
                    }
                    //else
                    if (serviceMode.has("freq") && serviceMode.getString("freq").length() > 0) {
                        Band = Integer.parseInt(serviceMode.getString("freq"));
                    } else
                        Band = 0;
                    if (serviceMode.has("channel") && serviceMode.getString("channel").length() > 0) {
                        Channel = Integer.parseInt(serviceMode.getString("channel"));
                    } else
                        Channel = 0;
                } else {
                    RRC = null;
                    Band = 0;
                    Channel = 0;
                }

                TelephonyManager telephonyManager = (TelephonyManager) context
                        .getSystemService(Service.TELEPHONY_SERVICE);
                String carrier = telephonyManager.getNetworkOperatorName();
                String mcc = "0", mnc = "0";
                if (telephonyManager.getNetworkOperator() != null
                        && telephonyManager.getNetworkOperator().length() >= 4) {
                    mcc = telephonyManager.getNetworkOperator().substring(0, 3);
                    mnc = telephonyManager.getNetworkOperator().substring(3);
                }
                int networkType = telephonyManager.getNetworkType();
                int networkTier = PhoneState.getNetworkGeneration(networkType);
                String nettype = PhoneState.getNetworkName(telephonyManager.getNetworkType());
                String data = PhoneState.getNetworkName(telephonyManager.getNetworkType()) + " ";
                int dataState = telephonyManager.getDataState();
                if (dataState == TelephonyManager.DATA_CONNECTED) {
                    String activity = getActivityName(telephonyManager.getDataActivity());
                    data += activity;
                } else if (telephonyManager.getNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
                    String state = getStateName(telephonyManager.getDataState());
                    data += state;
                }

                Data = data;
                Carrier = carrier;

                Date date = new Date(System.currentTimeMillis());
                final String dateStr = DateFormat.getDateFormat(context).format(date);
                final String timeStr = dateStr + "  " + DateFormat.getTimeFormat(context).format(date);

                Time = timeStr;

                MCC = Integer.parseInt(mcc);
                MNC = Integer.parseInt(mnc);

                // Tell the service we're watching the signal, so keep it updated
                Intent intent = new Intent(CommonIntentActionsOld.VIEWING_SIGNAL);
                context.sendBroadcast(intent);

                WifiInfo wifiinfo = getWifiInfo();
                WifiConfiguration wifiConfig = getWifiConfig();
                setWifi(wifiinfo, wifiConfig);

                // Instantiate only the relevant Network type
                if (netType.equals("cdma"))
                    connectedNetwork = CDMAInfo = new CDMAInfo(this);
                else if (netType.equals("gsm") && networkTier < 3)
                    connectedNetwork = GSMInfo = new GSMInfo(this);
                else if (netType.equals("gsm") && networkTier < 5)
                    connectedNetwork = WCDMAInfo = new WCDMAInfo(this);
                if (networkTier == 5) // LTE
                    connectedNetwork = LTEInfo = new LTEInfo(this);
                if (wifiConfig != null)
                    connectedNetwork = WiFiInfo = new WIFIInfo(this); // The most relevant network ends up in NetworkInfo
            } catch (Exception e) {
            }

        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "updateNerdViewFromDB",
                    "exception querying signal data: " + e.getMessage());
        } finally {
            if (cell_cursor != null)
                cell_cursor.close();
            if (sig_cursor != null)
                sig_cursor.close();
        }
    }

    private WifiInfo getWifiInfo() {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();

        return wifiInfo;
    }

    private WifiConfiguration getWifiConfig() {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        WifiConfiguration activeConfig = null;
        if (wifiManager.getConfiguredNetworks() == null)
            return null;

        for (WifiConfiguration conn : wifiManager.getConfiguredNetworks()) {
            if ((conn.BSSID != null && conn.BSSID.equals(wifiInfo.getBSSID()))
                    || (conn.SSID != null && conn.SSID.equals(wifiInfo.getSSID()))) {
                activeConfig = conn;
                break;
            }
        }
        if (activeConfig != null) {
            return activeConfig;
        }
        return null;
    }

    private void setWifi(WifiInfo wifiInfo, WifiConfiguration wifiConfig) {
        if (wifiInfo == null || wifiConfig == null)
            return;

        String macid = wifiInfo.getBSSID();
        if (macid == null)
            return;
        String[] bytes = macid.split(":");
        long bssid = 0;
        for (int i = 0; i < 6; i++) {
            if (i < bytes.length) {
                long v = hexval(bytes[i]);
                bssid = bssid + (v << ((5 - i) * 8));
            }
        }
        WifiID = bssid;

        if (wifiConfig != null) {
            int bits = 0;
            for (int i = 0; i < 4; i++) {
                if (wifiConfig.allowedKeyManagement.get(i))
                    bits += 1 << i;
            }
            BitSet bs = new BitSet();
            //bs.set(WifiConfiguration.KeyMgmt.NONE);
            //if (wifiConfig.allowedKeyManagement..allowedAuthAlgorithms.intersects(bs))
            WifiSec = bits;
        }

        int freq = getWifiFrequency(wifiInfo);
        if (freq != -1)
            WifiFreq = freq;

        int sig = wifiInfo.getRssi();
        WifiSig = sig;
    }

    public static int getWifiFrequency(WifiInfo wifiInfo) {
        int returnValue = -1;
        try {
            Method freqMethod = WifiInfo.class.getMethod("getFrequency", (Class[]) null);
            if (freqMethod != null) {
                //now we're in business!
                returnValue = (Integer) freqMethod.invoke(wifiInfo, (Object[]) null);
            }
        } catch (Exception e) {
        }
        return returnValue;

    }

    /*
    * Get the data connection state as a name
    * (connected, disconnected etc)
    * returns string name
    */
    public String getStateName(int state) {
        switch (state) {
        case TelephonyManager.DATA_CONNECTED:
            return "connected";
        case TelephonyManager.DATA_CONNECTING:
            return "connecting";
        case TelephonyManager.DATA_DISCONNECTED:
            return "disconnected";
        case TelephonyManager.DATA_SUSPENDED:
            return "suspended";
        }
        return "-";
    }

    /*
    * Get the current state of data activity, whether data is actively sending, receiving, etc
    * (send, recv, send recv, dormant, etc)
    * returns string to describe activity
    */
    public String getActivityName(int activity) {
        switch (activity) {
        case TelephonyManager.DATA_ACTIVITY_DORMANT:
            return context.getString(R.string.LiveStatus_dormant);
        case TelephonyManager.DATA_ACTIVITY_IN:
            return context.getString(R.string.LiveStatus_receiving);
        case TelephonyManager.DATA_ACTIVITY_OUT:
            return context.getString(R.string.LiveStatus_sending);
        case TelephonyManager.DATA_ACTIVITY_INOUT:
            return context.getString(R.string.LiveStatus_sendrecv);
        case TelephonyManager.DATA_ACTIVITY_NONE:
            return context.getString(R.string.LiveStatus_noactivty);

        }
        return "U";
    }

    /*
    * Get the cellular service state as a name
    * (in service, no service, etc)
    * returns string name
     */
    public String getServiceStateName(int state) {
        String name = "";
        if (state >= 10) {
            name = "roam ";
            if (state == 10)
                return name;
            else
                state = state - 10;
        }
        switch (state) {
        case ServiceState.STATE_OUT_OF_SERVICE:
            name += "no service";
            break;
        case ServiceState.STATE_EMERGENCY_ONLY:
            name += "911 only";
            break;
        case PhoneState.SERVICE_STATE_AIRPLANE:
            name += "airplane";
            break;
        case ServiceState.STATE_IN_SERVICE:
            name += "in service";
            break;
        case ServiceState.STATE_POWER_OFF:
            name += "power off";
            break;
        }
        return name;
    }

    private int hexval(String s) {
        int val = 0;
        if (s.length() < 2)
            return 0;
        char a = s.charAt(0);
        if (a >= '0' && a <= '9')
            val = (int) (a - '0') << 4;
        else if (a >= 'a' && a <= 'f')
            val = (int) (a - 'a' + 10) << 4;
        else if (a >= 'A' && a <= 'F')
            val = (int) (a - 'A' + 10) << 4;

        a = s.charAt(1);
        if (a >= '0' && a <= '9')
            val += (int) (a - '0');
        else if (a >= 'a' && a <= 'f')
            val += (int) (a - 'a' + 10);
        else if (a >= 'A' && a <= 'F')
            val += (int) (a - 'A' + 10);
        return val;
    }

    private int simpleValidate(Integer signal) {
        if (signal == null || signal == 0 || signal == -1 || signal == 255 || signal == 99 || signal >= 32767
                || signal <= -32767)
            return 0;
        return signal;
    }

    private float simpleValidate(Float signal) {
        if (signal == null || signal == 0)
            return 0;
        return signal;
    }

    /**
     * List the high level information about the Carrier Network such as the Carrier name, MCC and MNC
     * @return a String describing the QosInfo object
     */
    @Override
    public String toString() {
        String str = "Carrier: " + Carrier + "\n";
        str += "MCC: " + MCC + " MNC: " + MNC + "\n";
        str += "Data: " + Data + "\n";
        if (Band > 0)
            str += "Band: " + Band + "\n";
        if (Channel > 0)
            str += "Channel: " + Channel + "\n";
        if (location != null)
            str += "location: " + location.toString() + "\n";
        if (connectedNetwork != null)
            str += "\n" + "Connected Network:\n" + connectedNetwork.toString();
        return str;
    }

}