org.restcomm.app.qoslib.UtilsOld.CellHistory.java Source code

Java tutorial

Introduction

Here is the source code for org.restcomm.app.qoslib.UtilsOld.CellHistory.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.UtilsOld;

import java.util.ArrayList;
import java.util.List;

import org.restcomm.app.utillib.DataObjects.CellLocationEx;
import org.restcomm.app.utillib.DataObjects.PhoneState;
import org.restcomm.app.utillib.Utils.LoggerUtil;

import android.annotation.TargetApi;
import android.os.Build;
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellLocation;
import android.telephony.CellSignalStrengthCdma;
import android.telephony.CellSignalStrengthGsm;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;

import org.json.JSONArray;
import org.json.JSONObject;

public class CellHistory {

    TelephonyManager telephonyManager = null;
    private List<CellidSample> cell_history = new ArrayList<CellidSample>();
    private List<CellidSample> neighbor_history = new ArrayList<CellidSample>();
    private long tmLastNeighborUpdate = 0, tmLastCellUpdate = 0, tmLastLTEUpdate = 0;
    private String lastCellString = "";
    private CellidSample lastLTECell = null;
    public static final String TAG = CellHistory.class.getSimpleName();

    public CellHistory(TelephonyManager _telephonyManager) {
        telephonyManager = _telephonyManager;
    }

    public long getLastCellSeen(CellLocation cellLoc) // MMCCellLocationOld cellInfo)
    {
        if (cellLoc == null)
            return -1;
        if (tmLastCellUpdate + 60000 > System.currentTimeMillis() && cellLoc.toString().equals(lastCellString))
            return -1;
        long timelastSeen = 0;
        tmLastCellUpdate = System.currentTimeMillis();

        // Is it reporting an unknown cell id? ignore those
        //        int cellId = 0;//cellInfo.getBSLow(); //low
        //        if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM && cellLoc instanceof GsmCellLocation)
        //         cellId = ((GsmCellLocation)cellLoc).getCid();
        //      else if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA && cellLoc instanceof CdmaCellLocation)
        //         cellId = ((CdmaCellLocation)cellLoc).getBaseStationId();
        //      if (cellId <= 0)
        //         return -1;

        CellidSample smp = new CellidSample(cellLoc);
        cell_history.add(smp);

        // How long has it been since we last saw this basestation
        //int bs_high = cellInfo.getBSHigh(), bs_mid = cellInfo.getBSMid(), bs_low = cellInfo.getBSLow();
        int bs_high = 0, bs_mid = 0, bs_low = 0;
        if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM
                && cellLoc instanceof GsmCellLocation) {
            GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLoc;
            bs_high = gsmCellLocation.getLac();
            bs_mid = gsmCellLocation.getCid() >> 16;
            bs_low = gsmCellLocation.getCid() & 0xffff;
        } else if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA
                && cellLoc instanceof CdmaCellLocation) {
            CdmaCellLocation cdmaCellLocation = (CdmaCellLocation) cellLoc;
            bs_high = cdmaCellLocation.getSystemId();
            bs_mid = cdmaCellLocation.getNetworkId();
            bs_low = cdmaCellLocation.getBaseStationId();
        }
        if (bs_low <= 0)
            return -1;
        int j;
        int histlen = cell_history.size();
        // How long has it been since we last saw this basestation
        long timestamp = System.currentTimeMillis();
        for (j = histlen - 2; j >= 0; j--) {
            if (cell_history.get(j).val2 == bs_low) //  && cell_history.get(j).val1 == bs_high)
            {
                // time last seen is the first timestamp after the cell was last seen
                // (the time this cell handed off to another cell)
                // (if the last known cell was this same cell, then the time last seen is now)
                timelastSeen = timestamp;
                break;
            } else
                timestamp = cell_history.get(j).timestamp;

        }

        return timelastSeen;
    }

    // Called when a neighbor list is detected in the RadioLog
    // It augments that neighbor list with the neighbor from the API
    public String updateNeighborHistory(int[] _list, int[] _list_rssi) {
        int i;
        //if (tmLastNeighborUpdate + 2000 > System.currentTimeMillis())
        //   return "";

        //if (!_isTravelling)
        {
            String txt = "";
            String stringNeighboring = "";
            String[] _type = null;
            try {
                int netType = telephonyManager.getNetworkType();
                int gen = PhoneState.getNetworkGeneration(netType);
                int n = 0, len = 0;
                boolean bValid = true;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                    try {
                        List<CellInfo> cells = null;
                        cells = telephonyManager.getAllCellInfo();
                        if (cells != null && cells.size() > 0 && cells.get(0) instanceof CellInfoLte
                                && telephonyManager.getNetworkType() == PhoneState.NETWORK_NEWTYPE_LTE) {
                            return updateLteNeighborHistory(cells);
                        }
                        //if (cells == null)
                        //   LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "updateNeighborHistory", "cells = null");

                        if (cells != null && cells.size() > 1)//1)
                        {

                            len = cells.size();
                            if (len > 8)
                                len = 8;
                            _list = new int[len];
                            _list_rssi = new int[len];
                            _type = new String[len];
                            for (i = 0; i < len; i++) {
                                bValid = true;
                                CellInfo neighbor = cells.get(i);
                                String msg = "cells[" + i + "]=" + neighbor.toString();
                                String classname = neighbor.getClass().toString();
                                //LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "updateNeighborHistory", "cells[" + i + "]=" + neighbor.toString());
                                //Log.d(TAG, "cells[" + c + "]=" + cells.get(c).toString());
                                if (gen < 3)
                                    _type[i] = "2G";
                                else
                                    _type[i] = "3G";
                                if (neighbor.isRegistered())
                                    _type[i] += "*";
                                if (neighbor instanceof CellInfoCdma) {
                                    CellIdentityCdma cdmacell = ((CellInfoCdma) neighbor).getCellIdentity();
                                    CellSignalStrengthCdma cdmasig = ((CellInfoCdma) neighbor)
                                            .getCellSignalStrength();
                                    if (cdmacell.getBasestationId() > 0) {
                                        _list[n] = cdmacell.getBasestationId();
                                        _list_rssi[n] = cdmasig.getEvdoDbm();
                                        n++;
                                        //else if (neighbor.getSystemId() > 0)
                                        //   _list[n] = (neighbor.getLac()<<16) + neighbor.getCid();
                                    } else
                                        bValid = false;
                                } else if (neighbor instanceof CellInfoGsm) {
                                    CellIdentityGsm gsmcell = ((CellInfoGsm) neighbor).getCellIdentity();
                                    CellSignalStrengthGsm gsmsig = ((CellInfoGsm) neighbor).getCellSignalStrength();
                                    if (gsmcell.getPsc() > 0 && gsmcell.getPsc() < 1000) {
                                        _list[n] = gsmcell.getPsc();
                                        _list_rssi[n] = gsmsig.getDbm();
                                        n++;
                                    } else if (gsmcell.getCid() > 0) {
                                        _list[n] = (gsmcell.getLac() << 16) + gsmcell.getCid();
                                        _list_rssi[n] = gsmsig.getDbm();
                                    } else
                                        bValid = false;
                                } else if (neighbor.getClass().toString()
                                        .equals("class android.telephony.CellInfoWcdma")) {
                                    try {
                                        Object gsmcell = neighbor.getClass().getDeclaredMethod("getCellIdentity")
                                                .invoke(neighbor, (Object[]) null);
                                        Object gsmsig = neighbor.getClass()
                                                .getDeclaredMethod("getCellSignalStrength")
                                                .invoke(neighbor, (Object[]) null);
                                        Integer psc = (Integer) gsmcell.getClass().getDeclaredMethod("getPsc")
                                                .invoke(gsmcell, (Object[]) null);
                                        Integer cid = (Integer) gsmcell.getClass().getDeclaredMethod("getCid")
                                                .invoke(gsmcell, (Object[]) null);
                                        Integer dbm = (Integer) gsmsig.getClass().getDeclaredMethod("getDbm")
                                                .invoke(gsmsig, (Object[]) null);
                                        if (psc > 0 && psc < 1000) {
                                            _list[n] = psc;
                                            //if (neighbor.isRegistered())
                                            //   _list[n] += 10000;
                                            _list_rssi[n] = dbm;
                                            n++;
                                        } else if (cid > 0 && cid < 65536) {
                                            _list[n] = cid;
                                            //if (neighbor.isRegistered())
                                            //   _list[n] += 10000;
                                            _list_rssi[n] = dbm;
                                            n++;
                                        } else
                                            bValid = false;
                                    } catch (Exception e) {
                                        //Log.d(TAG, "Field does not exist - " + fieldname);
                                    }

                                    //                     CellIdentityWcdma gsmcell =((CellInfoWcdma) neighbor).getCellIdentity();
                                    //                     CellSignalStrengthWcdma gsmsig = ((CellInfoWcdma) neighbor).getCellSignalStrength();
                                    //                     if (gsmcell.getPsc() > 0)
                                    //                     {   _list[n] = gsmcell.getPsc();
                                    //                        if (neighbor.isRegistered())
                                    //                           _list[n] += 0;
                                    //                        _list_rssi[n] = gsmsig.getDbm();
                                    //                        n++;
                                    //                     }
                                    //                     else if (gsmcell.getCid() > 0)
                                    //                     {
                                    //                        _list[n] = (gsmcell.getLac()<<16) + gsmcell.getCid();
                                    //                     }
                                    //                     else
                                    //                        bValid = false;
                                }
                            }

                        }

                    } catch (Exception e) {

                    }
                }
                if (_list == null) {
                    // Try to obtain the Neighbor list from the API
                    // If the API neighbor list has more active entries than what the log provided, use it instead
                    List<NeighboringCellInfo> neighboringList = telephonyManager.getNeighboringCellInfo();
                    len = neighboringList.size();
                    if (neighboringList != null && len > 0) {
                        int activeN = 0; // how many of the API neighbors are active?

                        for (i = 0; i < neighboringList.size(); i++) {
                            NeighboringCellInfo neighbor = neighboringList.get(i);
                            if (neighbor.getPsc() > 0 && neighbor.getRssi() > -120 && neighbor.getRssi() < -10)
                                activeN++;
                            else if (neighbor.getCid() > 0 && neighbor.getRssi() > 0 && neighbor.getRssi() < 32)
                                activeN++;
                        }
                        _list = new int[len];
                        _list_rssi = new int[len];
                        _type = new String[len];

                        for (i = 0; i < len; i++) {
                            bValid = true;
                            NeighboringCellInfo neighbor = neighboringList.get(i);
                            if (gen < 3)
                                _type[n] = "2G";
                            else
                                _type[n] = "3G";
                            if (neighbor.getPsc() > 0)
                                _list[n] = neighbor.getPsc();
                            else if (neighbor.getLac() > 0)
                                _list[n] = (neighbor.getLac() << 16) + neighbor.getCid();
                            else
                                bValid = false;

                            if (bValid) {
                                _list_rssi[n] = neighbor.getRssi();
                                if (_list_rssi[n] >= 0)
                                    _list_rssi[n] = getDbmValue(_list_rssi[n]);
                                n++;
                            }
                        }
                    }
                }

                if (_list == null)
                    return null;
                tmLastNeighborUpdate = System.currentTimeMillis();
                // create and add a neighbor cell item for each neighbor
                for (i = 0; i < _list.length; i++) {
                    if (_list[i] != 0) {
                        CellidSample smp = new CellidSample(_type[i], _list[i], _list_rssi[i]);
                        // Update Neighbor list history a maximum of once per 2 seconds
                        neighbor_history.add(smp);
                        stringNeighboring = stringNeighboring + String.valueOf(_list[i] & 0xFFFF) + "@"
                                + _list_rssi[i] + ",";

                    }
                }
                // Report the API neighbor list in the Log, build a string of neighbors
                if (lastCellString == stringNeighboring)
                    return null;
                lastCellString = stringNeighboring;
                //if (neighboringList.size() > 0)
                //MMCLogger.logToFile(MMCLogger.Level.DEBUG, TAG, "updateNeighborHistory", stringNeighboring);

                return stringNeighboring;
            } catch (Exception e) {
                return "";
            } finally {
                //if (txt.length() > 0 && (txt.indexOf("might") > 0 || txt.indexOf("detect") > 0))
                //   MMCLogger.logToFile(MMCLogger.Level.DEBUG, TAG, "detectTravellingFromNeighbors", "\n"+txt.substring(0,txt.length()));
            }
        }
    }

    // Called when a neighbor list is detected in the RadioLog
    // It augments that neighbor list with the neighbor from the API
    public String updateNeighborHistory(JSONArray neighbors) {
        int i;
        String stringNeighboring = "";
        //if (tmLastNeighborUpdate + 2000 > System.currentTimeMillis())
        //   return "";

        try {
            int len = neighbors.length();
            int[] list = new int[len];
            int[] list_rssi = new int[len];
            String[] type = new String[len];
            int netType = telephonyManager.getNetworkType();
            int gen = PhoneState.getNetworkGeneration(netType);
            for (i = 0; i < len; i++) {
                JSONObject neigh = (JSONObject) neighbors.get(i);
                if (gen < 3)
                    type[i] = "2G";
                else
                    type[i] = "3G";
                if (neigh.has("type") && neigh.getString("type").equals("ASET"))
                    type[i] += "*";

                if (neigh.has("psc")) {
                    int psc = Integer.valueOf(neigh.getString("psc"));
                    list[i] = psc;
                }
                if (neigh.has("rscp")) {
                    int rscp = Integer.valueOf(neigh.getString("rscp"));
                    if (rscp > 0)
                        rscp = -rscp;
                    list_rssi[i] = rscp;
                } else if (neigh.has("rxlev")) {
                    int rx = Integer.valueOf(neigh.getString("rxlev"));
                    int rssi = -121;
                    if (rx > 0) {
                        if (rx == 1)
                            rssi = -111; // officially 1 = -111 dB
                        else if (rx > 1 && rx <= 31)
                            rssi = (rx - 2) * 2 + -109;
                    }
                    list_rssi[i] = rssi;
                }
                CellidSample smp = new CellidSample(type[i], list[i], list_rssi[i]);
                // Update Neighbor list history a maximum of once per 2 seconds
                neighbor_history.add(smp);
                stringNeighboring = stringNeighboring + String.valueOf(list[i] & 0xFFFF) + "@" + list_rssi[i] + ",";
            }
            if (list.length == 0)
                return null;
            tmLastNeighborUpdate = System.currentTimeMillis();
            // Report the API neighbor list in the Log, build a string of neighbors
            if (lastCellString == stringNeighboring)
                return null;
            lastCellString = stringNeighboring;
            //if (neighboringList.size() > 0)
            //MMCLogger.logToFile(MMCLogger.Level.DEBUG, TAG, "updateNeighborHistory", stringNeighboring);

            return stringNeighboring;
        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "updateNeighborHistory", "Exception", e);
        }

        return "";
    }

    @TargetApi(17)
    public String updateLteNeighborHistory(List<CellInfo> cellinfos) {
        if (cellinfos == null || cellinfos.size() == 0) {
            if (lastLTECell != null) {
                CellidSample smp = new CellidSample("L", 0, 0, 0);
                neighbor_history.add(smp);
                lastLTECell = null;
            }
            return null;
        }
        for (int i = 0; i < cellinfos.size(); i++) {
            // All we're interested in here is getting new Lte cell identity with this new API. Otherwise ignore and use CellLocation updates
            if (cellinfos.get(i) instanceof CellInfoLte) {
                CellIdentityLte cellIDLte = ((CellInfoLte) cellinfos.get(i)).getCellIdentity();
                if (cellIDLte.getTac() > 0 && cellIDLte.getTac() < 100000) {
                    int tac = cellIDLte.getTac(), pci = cellIDLte.getPci(), ci = cellIDLte.getCi();
                    return updateLteNeighborHistory(tac, ci, pci);
                }
            } else // Lte CellIdentity contains bogus ids, treat like its null
            {
                CellidSample smp = new CellidSample("L", 0, 0, 0);
                neighbor_history.add(smp);
                lastLTECell = null;

            }
        }
        return null;
    }

    public String updateLteNeighborHistory(int tac, int ci, int pci) {
        String stringLTE = "";

        if (pci > 1000000)
            pci = 0; // bogus
        if (ci > 2000000000)
            ci = 0; // bogus
        if (tac <= 0 || tac > 2000000000)
            return null;

        CellidSample smp = new CellidSample("L", tac, ci, pci);
        //if (i==0)
        {
            //int ciHigh = ci >> 16;
            //int ciLow = ci & 0xffff;
            stringLTE = stringLTE + "LTE Tac:" + tac + " Ci:" + ci + " pCi:" + pci;
            if (ci > 0) {
                int eNB = (ci >> 8) & 0xFFFFF;
                int cellid = (ci & 0xFF);
                stringLTE = stringLTE + " eNB:" + eNB + "/" + cellid;
            }
        }
        if (lastLTECell == null || !lastLTECell.valuesEqual(smp)
                || tmLastLTEUpdate + 30000 < System.currentTimeMillis()) {
            // Update repeated LTE a maximum of once per 30 seconds
            neighbor_history.add(smp);
            lastLTECell = smp;
            tmLastLTEUpdate = System.currentTimeMillis();
        }

        //if (neighbors != null && neighbors.length() > 2)
        return stringLTE;
    }
    // Repeat the last history item at the beginning of recording an event
    //   public void snapshotHistory ()
    //   {
    //      CellidSample smp = null;
    //      if (neighbor_history.size() > 0)
    //         smp = neighbor_history.get(neighbor_history.size()-1);   
    //      smp = new CellidSample (smp.type, smp.val1, smp.val2, smp.val3);
    //      neighbor_history.add (smp);   
    //   }

    private Integer getDbmValue(int rssi) {
        rssi /= 2;
        // according to the 3GPP specs: http://m10.home.xs4all.nl/mac/downloads/3GPP-27007-630.pdf
        if (rssi == 0)
            return -120; // officially 0 means -113dB or less, but since lowest possible signal on Blackberry = -120, call it -120 for consistency
        else if (rssi == 1)
            return -111; // officially 1 = -111 dB
        else if (rssi > 1 && rssi <= 31)
            return (rssi - 2) * 2 + -109;
        else if (rssi == 99)
            return rssi;
        else
            return rssi; // shouldn't be possible

    }

    // Called when an event is being reported to the server
    // It builds a neighbor list history that doesnt ovrlap the previously reported neighbor list history
    public String getNeighborHistory(long startTime, long eventTime) {
        int i;
        String txt = "";
        //      String hdr = "3,sec,psc,rssi, ";
        String hdr = "5,sec,type,val1,val2,val3";
        int size = neighbor_history.size();
        for (i = size - 1; i >= 0; i--) {
            CellidSample smp = neighbor_history.get(i);
            //if (smp.sent == 0)
            {
                txt += toString(smp, eventTime);
            }
            if (smp.timestamp < startTime)
                break;
        }
        if (txt.length() > 1)
            return hdr + txt;
        else
            return "";
    }

    public String toString(CellidSample sample, long eventTime) {

        String txt = "";
        //txt += "," + (sample.timestamp/1000);
        txt += "," + ((sample.timestamp - eventTime) / 1000);
        txt += "," + sample.type;
        txt += "," + sample.val1;
        if (sample.type.equals("L")) // valid ranges different for lte vs 3G/2G
        {
            txt += "," + (sample.val2 <= 2000000000 ? sample.val2 : 0);
            txt += "," + (sample.val3 <= 2000000000 ? sample.val3 : 0);
        } else {
            txt += "," + sample.val2; // (sample.val2 <= -121 ? sample.val2 : 0);
            txt += "," + (sample.val3 > 0 ? sample.val3 : 0);
        }
        sample.sent = 1;

        return txt;
    }

    // ON each 3hr checkpoint, prune the cell history lists, removing items 3 hours old
    public void clearCellHistory() {
        // clear 3 hour old items out of history lists
        int i;
        for (i = 0; i < neighbor_history.size(); i++) {
            if (neighbor_history.get(i).timestamp + 180 * 60000 < System.currentTimeMillis()) {
                neighbor_history.remove(i);
                i--;
            } else
                break;

        }
        for (i = 0; i < cell_history.size(); i++) {
            if (cell_history.get(i).timestamp + 180 * 60000 * 3 < System.currentTimeMillis()) {
                cell_history.remove(i);
                i--;
            } else
                break;

        }
        LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "clearCellHistory",
                "neighbors=" + neighbor_history.size() + " cells=" + cell_history.size());
    }

    // Simple representation of either a cell or a neighbor cell
    public class CellidSample {
        public int val1 = -1, val2 = -1, val3 = -1, sent = 0;
        public String type = "";
        public long timestamp;

        public CellidSample(CellLocation cell) {
            CellLocationEx mmcCell = new CellLocationEx(cell);

            timestamp = System.currentTimeMillis();
            val1 = mmcCell.getBSHigh();
            val2 = mmcCell.getBSLow();
            //         
            //         if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA && mmcCell instanceof CdmaCellLocation)
            //         {
            //            lac = ((CdmaCellLocation)mmcCell).getSystemId();
            //            cid = ((CdmaCellLocation)mmcCell).getBaseStationId();
            //         }
            //         else if (mmcCell instanceof GsmCellLocation)
            //         {
            //            lac = ((GsmCellLocation)mmcCell).getLac();
            //            cid = ((GsmCellLocation)mmcCell).getCid();
            //         }
        }

        public CellidSample(NeighboringCellInfo neighbor) {
            timestamp = System.currentTimeMillis();
            val1 = neighbor.getPsc();
        }

        public CellidSample(String _type, int _psc, int _rssi) //add type?
        {
            timestamp = System.currentTimeMillis();
            type = _type;
            val1 = _psc;
            val2 = _rssi;
        }

        public CellidSample(String _type, int _tac, int _ci, int _pci) {
            timestamp = System.currentTimeMillis();
            type = _type;
            val1 = _tac;
            val2 = _ci;
            val3 = _pci;
        }

        public boolean valuesEqual(CellidSample smp) {
            if (val1 == smp.val1 && val2 == smp.val2 && val3 == smp.val3)
                return true;
            return false;
        }

    }
}