com.SecUpwN.AIMSICD.service.AimsicdService.java Source code

Java tutorial

Introduction

Here is the source code for com.SecUpwN.AIMSICD.service.AimsicdService.java

Source

/* Android IMSI Catcher Detector
*      Copyright (C) 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You may obtain a copy of the License at
*      https://github.com/SecUpwN/Android-IMSI-Catcher-Detector/blob/master/LICENSE
*/

/*
 * Portions of this software have been copied and modified from
 * Femtocatcher https://github.com/iSECPartners/femtocatcher
 *
 * Copyright (C) 2013 iSEC Partners
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/*
 * Portions of this software have been copied and modified from
 * https://github.com/illarionov/SamsungRilMulticlient
 * Copyright (C) 2014 Alexey Illarionov
 *
 * 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.SecUpwN.AIMSICD.service;

import com.SecUpwN.AIMSICD.AIMSICD;
import com.SecUpwN.AIMSICD.R;
import com.SecUpwN.AIMSICD.adapters.AIMSICDDbAdapter;
import com.SecUpwN.AIMSICD.rilexecutor.DetectResult;
import com.SecUpwN.AIMSICD.rilexecutor.OemRilExecutor;
import com.SecUpwN.AIMSICD.rilexecutor.RawResult;
import com.SecUpwN.AIMSICD.rilexecutor.SamsungMulticlientRilExecutor;
import com.SecUpwN.AIMSICD.utils.Cell;
import com.SecUpwN.AIMSICD.utils.Device;
import com.SecUpwN.AIMSICD.utils.Helpers;
import com.SecUpwN.AIMSICD.utils.OemCommands;

import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.CellLocation;
import android.telephony.CellSignalStrengthCdma;
import android.telephony.CellSignalStrengthGsm;
import android.telephony.CellSignalStrengthLte;
import android.telephony.CellSignalStrengthWcdma;
import android.telephony.NeighboringCellInfo;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.WindowManager;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class AimsicdService extends Service implements OnSharedPreferenceChangeListener {

    private final String TAG = "AIMSICD_Service";
    public static final String SHARED_PREFERENCES_BASENAME = "com.SecUpwN.AIMSICD_preferences";
    public static final String SILENT_SMS = "SILENT_SMS_INTERCEPTED";
    public static final String UPDATE_DISPLAY = "UPDATE_DISPLAY";
    public static int PHONE_TYPE;
    public static String OCID_API_KEY = "API KEY GOES HERE.......";

    /*
     * System and helper declarations
     */
    private final AimscidBinder mBinder = new AimscidBinder();
    private final AIMSICDDbAdapter dbHelper = new AIMSICDDbAdapter(this);
    private final Handler timerHandler = new Handler();
    private Context mContext;
    private final int NOTIFICATION_ID = 1;
    private long mDbResult;
    private TelephonyManager tm;
    private LocationManager lm;
    private SharedPreferences prefs;
    private PhoneStateListener mPhoneStateListener;
    private LocationListener mLocationListener;
    private static final long GPS_MIN_UPDATE_TIME = 1000;
    private static final float GPS_MIN_UPDATE_DISTANCE = 10;
    public boolean mMultiRilCompatible;
    public static long REFRESH_RATE;
    public static int LAST_DB_BACKUP_VERSION;
    public static boolean OCID_UPLOAD_PREF;
    private boolean CELL_TABLE_CLEANSED;

    public final Device mDevice = new Device();

    /*
     * Tracking and Alert Declarations
     */
    private boolean mLoaded;
    private boolean mMonitoringCell;
    private boolean mTrackingCell;
    private boolean mTrackingFemtocell;
    private boolean mFemtoDetected;
    private boolean mLocationPrompted;
    private boolean mTypeZeroSmsDetected;
    private boolean mChangedLAC;
    private Cell mMonitorCell;

    /*
     * Samsung MultiRil Implementation
     */
    private static final int ID_REQUEST_START_SERVICE_MODE_COMMAND = 1;
    private static final int ID_REQUEST_FINISH_SERVICE_MODE_COMMAND = 2;
    private static final int ID_REQUEST_PRESS_A_KEY = 3;
    private static final int ID_REQUEST_REFRESH = 4;
    private static final int ID_RESPONSE = 101;
    private static final int ID_RESPONSE_FINISH_SERVICE_MODE_COMMAND = 102;
    private static final int ID_RESPONSE_PRESS_A_KEY = 103;
    private static final int REQUEST_TIMEOUT = 10000; // ms

    private final ConditionVariable mRequestCondvar = new ConditionVariable();
    private final Object mLastResponseLock = new Object();
    private volatile List<String> mLastResponse;
    private DetectResult mRilExecutorDetectResult;
    private OemRilExecutor mRequestExecutor;
    private HandlerThread mHandlerThread;
    private Handler mHandler;

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public class AimscidBinder extends Binder {
        public AimsicdService getService() {
            return AimsicdService.this;
        }
    }

    public void onCreate() {
        //TelephonyManager provides system details
        tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
        lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        mContext = getApplicationContext();

        PHONE_TYPE = tm.getPhoneType();

        prefs = this.getSharedPreferences(AimsicdService.SHARED_PREFERENCES_BASENAME, 0);
        prefs.registerOnSharedPreferenceChangeListener(this);
        loadPreferences();

        if (!CELL_TABLE_CLEANSED) {
            dbHelper.open();
            dbHelper.cleanseCellTable();
            dbHelper.close();
            Editor prefsEditor;
            prefsEditor = prefs.edit();
            prefsEditor.putBoolean(this.getString(R.string.pref_cell_table_cleansed), true);
            prefsEditor.apply();
        }

        mDevice.refreshDeviceInfo(tm, this); //Telephony Manager
        setNotification();

        mRequestExecutor = new SamsungMulticlientRilExecutor();
        mRilExecutorDetectResult = mRequestExecutor.detect();
        if (!mRilExecutorDetectResult.available) {
            mMultiRilCompatible = false;
            Log.e(TAG, "Samsung multiclient ril not available: " + mRilExecutorDetectResult.error);
            mRequestExecutor = null;
        } else {
            mRequestExecutor.start();
            mMultiRilCompatible = true;
            //Sumsung MultiRil Initialization
            mHandlerThread = new HandlerThread("ServiceModeSeqHandler");
            mHandlerThread.start();

            Looper l = mHandlerThread.getLooper();
            if (l != null) {
                mHandler = new Handler(l, new MyHandler());
            }
        }

        //Register receiver for Silent SMS Interception Notification
        mContext.registerReceiver(mMessageReceiver, new IntentFilter(SILENT_SMS));

        mMonitorCell = new Cell();

        Log.i(TAG, "Service launched successfully");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        prefs.unregisterOnSharedPreferenceChangeListener(this);
        cancelNotification();
        dbHelper.close();
        mContext.unregisterReceiver(mMessageReceiver);
        if (mTrackingCell) {
            tm.listen(mCellSignalListener, PhoneStateListener.LISTEN_NONE);
            lm.removeUpdates(mLocationListener);
        }

        //Samsung MultiRil Cleanup
        if (mRequestExecutor != null) {
            mRequestExecutor.stop();
            mRequestExecutor = null;
            mHandler = null;
            mHandlerThread.quit();
            mHandlerThread = null;
        }

        Log.i(TAG, "Service destroyed");
    }

    private final BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final Bundle bundle = intent.getExtras();
            if (bundle != null) {
                dbHelper.open();
                dbHelper.insertSilentSms(bundle);
                dbHelper.close();
                setSilentSmsStatus(true);
            }
        }
    };

    /**
     * Check the status of the Rill Executor
     *
     * @return DetectResult providing access status of the Ril Executor
     */
    public DetectResult getRilExecutorStatus() {
        return mRilExecutorDetectResult;
    }

    /**
     * Executes and receives the Ciphering Information request using
     * the Rill Executor
     *
     * @return String list response from Rill Executor
     */
    public List<String> getCipheringInfo() {
        return executeServiceModeCommand(OemCommands.OEM_SM_TYPE_TEST_MANUAL,
                OemCommands.OEM_SM_TYPE_SUB_CIPHERING_PROTECTION_ENTER, null);
    }

    /**
     * Executes and receives the Neighbouring Cell request using
     * the Rill Executor
     *
     * @return String list response from Rill Executor
     */
    public List<String> getNeighbours() {
        KeyStep getNeighboursKeySeq[] = new KeyStep[] { new KeyStep('\0', false), new KeyStep('1', false), // [1] DEBUG SCREEN
                new KeyStep('4', true), // [4] NEIGHBOUR CELL
        };

        return executeServiceModeCommand(OemCommands.OEM_SM_TYPE_TEST_MANUAL, OemCommands.OEM_SM_TYPE_SUB_ENTER,
                Arrays.asList(getNeighboursKeySeq));

    }

    /**
     * Updates Neighbouring Cell details
     */
    public List<Cell> updateNeighbouringCells() {
        List<Cell> neighboringCells = new ArrayList<>();

        List<NeighboringCellInfo> neighboringCellInfo;
        neighboringCellInfo = tm.getNeighboringCellInfo();
        if (neighboringCellInfo.size() == 0) {
            // try to poll the neighboring cells for a few seconds
            final LinkedBlockingQueue<NeighboringCellInfo> neighboringCellBlockingQueue = new LinkedBlockingQueue<>(
                    100);
            final PhoneStateListener listener = new PhoneStateListener() {
                private void handle() {
                    List<NeighboringCellInfo> neighboringCellInfo;
                    neighboringCellInfo = tm.getNeighboringCellInfo();
                    if (neighboringCellInfo.size() == 0) {
                        return;
                    }
                    Log.i(TAG, "neighbouringCellInfo empty - event based polling succeeded!");
                    tm.listen(this, PhoneStateListener.LISTEN_NONE);
                    neighboringCellBlockingQueue.addAll(neighboringCellInfo);
                }

                @Override
                public void onServiceStateChanged(ServiceState serviceState) {
                    handle();
                }

                @Override
                public void onDataConnectionStateChanged(int state) {
                    handle();
                }

                @Override
                public void onDataConnectionStateChanged(int state, int networkType) {
                    handle();
                }

                @Override
                public void onSignalStrengthsChanged(SignalStrength signalStrength) {
                    handle();
                }

                @Override
                public void onCellInfoChanged(List<CellInfo> cellInfo) {
                    handle();
                }
            };
            Log.i(TAG, "neighbouringCellInfo empty - start polling");

            //LISTEN_CELL_INFO added in API 17
            if (Build.VERSION.SDK_INT > 16) {
                tm.listen(listener, PhoneStateListener.LISTEN_CELL_INFO | PhoneStateListener.LISTEN_CELL_LOCATION
                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | PhoneStateListener.LISTEN_SERVICE_STATE
                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
            } else {
                tm.listen(listener,
                        PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                                | PhoneStateListener.LISTEN_SERVICE_STATE
                                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
            }

            for (int i = 0; i < 10 && neighboringCellInfo.size() == 0; i++) {
                try {
                    Log.i(TAG, "neighbouringCellInfo empty - try " + i);
                    NeighboringCellInfo info = neighboringCellBlockingQueue.poll(1, TimeUnit.SECONDS);
                    if (info == null) {
                        neighboringCellInfo = tm.getNeighboringCellInfo();
                        if (neighboringCellInfo.size() > 0) {
                            Log.i(TAG, "neighbouringCellInfo empty - try " + i + " succeeded time based");
                            break;
                        } else {
                            continue;
                        }
                    }
                    ArrayList<NeighboringCellInfo> cellInfoList = new ArrayList<NeighboringCellInfo>(
                            neighboringCellBlockingQueue.size() + 1);
                    while (info != null) {
                        cellInfoList.add(info);
                        info = neighboringCellBlockingQueue.poll(1, TimeUnit.SECONDS);
                    }
                    neighboringCellInfo = cellInfoList;
                } catch (InterruptedException e) {
                    // normal
                }
            }
        }

        Log.i(TAG, "neighbouringCellInfo Size - " + neighboringCellInfo.size());
        for (NeighboringCellInfo neighbourCell : neighboringCellInfo) {
            Log.i(TAG, "neighbouringCellInfo - CID:" + neighbourCell.getCid() + " LAC:" + neighbourCell.getLac()
                    + " RSSI:" + neighbourCell.getRssi() + " PSC:" + neighbourCell.getPsc());

            final Cell cell = new Cell(neighbourCell.getCid(), neighbourCell.getLac(), neighbourCell.getRssi(),
                    neighbourCell.getPsc(), neighbourCell.getNetworkType(), false);
            neighboringCells.add(cell);
        }

        return neighboringCells;
    }

    /**
     * Service Mode Command Helper to call with Timeout value
     *
     * @return executeServiceModeCommand adding REQUEST_TIMEOUT
     */
    private List<String> executeServiceModeCommand(int type, int subtype,
            java.util.Collection<KeyStep> keySeqence) {
        return executeServiceModeCommand(type, subtype, keySeqence, REQUEST_TIMEOUT);
    }

    /**
     * Service Mode Command Helper to call with Timeout value
     *
     * @return executeServiceModeCommand adding REQUEST_TIMEOUT
     */
    private synchronized List<String> executeServiceModeCommand(int type, int subtype,
            java.util.Collection<KeyStep> keySeqence, int timeout) {
        if (mRequestExecutor == null) {
            return Collections.emptyList();
        }

        mRequestCondvar.close();
        mHandler.obtainMessage(ID_REQUEST_START_SERVICE_MODE_COMMAND, type, subtype, keySeqence).sendToTarget();
        if (!mRequestCondvar.block(timeout)) {
            Log.e(TAG, "request timeout");
            return Collections.emptyList();
        } else {
            synchronized (mLastResponseLock) {
                return mLastResponse;
            }
        }
    }

    private static class KeyStep {

        public final char keychar;

        public final boolean captureResponse;

        public KeyStep(char keychar, boolean captureResponse) {
            this.keychar = keychar;
            this.captureResponse = captureResponse;
        }

        public static final KeyStep KEY_START_SERVICE_MODE = new KeyStep('\0', true);
    }

    private class MyHandler implements Handler.Callback {

        private int mCurrentType;
        private int mCurrentSubtype;
        private Queue<KeyStep> mKeySequence;

        @Override
        public boolean handleMessage(Message msg) {
            byte[] requestData;
            Message responseMsg;
            KeyStep lastKeyStep;

            switch (msg.what) {
            case ID_REQUEST_START_SERVICE_MODE_COMMAND:
                mCurrentType = msg.arg1;
                mCurrentSubtype = msg.arg2;
                mKeySequence = new ArrayDeque<>(3);
                if (msg.obj != null) {
                    mKeySequence.addAll((java.util.Collection<KeyStep>) msg.obj);
                } else {
                    mKeySequence.add(KeyStep.KEY_START_SERVICE_MODE);
                }
                synchronized (mLastResponseLock) {
                    mLastResponse = new ArrayList<>();
                }
                requestData = OemCommands.getEnterServiceModeData(mCurrentType, mCurrentSubtype,
                        OemCommands.OEM_SM_ACTION);
                responseMsg = mHandler.obtainMessage(ID_RESPONSE);
                mRequestExecutor.invokeOemRilRequestRaw(requestData, responseMsg);
                break;
            case ID_REQUEST_FINISH_SERVICE_MODE_COMMAND:
                requestData = OemCommands.getEndServiceModeData(mCurrentType);
                responseMsg = mHandler.obtainMessage(ID_RESPONSE_FINISH_SERVICE_MODE_COMMAND);
                mRequestExecutor.invokeOemRilRequestRaw(requestData, responseMsg);
                break;
            case ID_REQUEST_PRESS_A_KEY:
                requestData = OemCommands.getPressKeyData(msg.arg1, OemCommands.OEM_SM_ACTION);
                responseMsg = mHandler.obtainMessage(ID_RESPONSE_PRESS_A_KEY);
                mRequestExecutor.invokeOemRilRequestRaw(requestData, responseMsg);
                break;
            case ID_REQUEST_REFRESH:
                requestData = OemCommands.getPressKeyData('\0', OemCommands.OEM_SM_QUERY);
                responseMsg = mHandler.obtainMessage(ID_RESPONSE);
                mRequestExecutor.invokeOemRilRequestRaw(requestData, responseMsg);
                break;
            case ID_RESPONSE:
                lastKeyStep = mKeySequence.poll();
                try {
                    RawResult result = (RawResult) msg.obj;
                    if (result == null) {
                        Log.e(TAG, "result is null");
                        break;
                    }
                    if (result.exception != null) {
                        Log.e(TAG, "", result.exception);
                        break;
                    }
                    if (result.result == null) {
                        Log.v(TAG, "No need to refresh.");
                        break;
                    }
                    if (lastKeyStep.captureResponse) {
                        synchronized (mLastResponseLock) {
                            mLastResponse.addAll(Helpers.unpackByteListOfStrings(result.result));
                        }
                    }
                } finally {
                    if (mKeySequence.isEmpty()) {
                        mHandler.obtainMessage(ID_REQUEST_FINISH_SERVICE_MODE_COMMAND).sendToTarget();
                    } else {
                        mHandler.obtainMessage(ID_REQUEST_PRESS_A_KEY, mKeySequence.element().keychar, 0)
                                .sendToTarget();
                    }
                }
                break;
            case ID_RESPONSE_PRESS_A_KEY:
                mHandler.sendMessageDelayed(mHandler.obtainMessage(ID_REQUEST_REFRESH), 10);
                break;
            case ID_RESPONSE_FINISH_SERVICE_MODE_COMMAND:
                mRequestCondvar.open();
                break;

            }
            return true;
        }
    }

    public void refreshDevice() {
        mDevice.refreshDeviceInfo(tm, this);
    }

    /**
     * Process User Preferences
     */
    private void loadPreferences() {
        boolean trackFemtoPref = prefs.getBoolean(this.getString(R.string.pref_femto_detection_key), false);

        boolean trackCellPref = prefs.getBoolean(this.getString(R.string.pref_enable_cell_key), false);

        LAST_DB_BACKUP_VERSION = prefs.getInt(this.getString(R.string.pref_last_database_backup_version), 1);

        OCID_UPLOAD_PREF = prefs.getBoolean(this.getString(R.string.pref_ocid_upload), false);

        CELL_TABLE_CLEANSED = prefs.getBoolean(this.getString(R.string.pref_cell_table_cleansed), false);

        String refreshRate = prefs.getString(getString(R.string.pref_refresh_key), "1");
        if (refreshRate.isEmpty()) {
            refreshRate = "1";
        }

        int rate = Integer.parseInt(refreshRate);
        long t;
        switch (rate) {
        case 1:
            t = 15L;
            break;
        default:
            t = (rate * 1L);
            break;
        }
        REFRESH_RATE = TimeUnit.SECONDS.toMillis(t);

        if (trackFemtoPref) {
            startTrackingFemto();
        }

        if (trackCellPref) {
            setCellTracking(true);
        }
    }

    /**
     * Tracking Cell Information
     *
     * @return boolean indicating Cell Information Tracking State
     */
    public boolean isTrackingCell() {
        return mTrackingCell;
    }

    /**
     * Tracking Femotcell Connections
     *
     * @return boolean indicating Femtocell Connection Tracking State
     */
    public boolean isTrackingFemtocell() {
        return mTrackingFemtocell;
    }

    void setSilentSmsStatus(boolean state) {
        mTypeZeroSmsDetected = state;
        setNotification();
        if (state) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage(R.string.sms_message).setTitle(R.string.sms_title);
            AlertDialog alert = builder.create();
            alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            alert.show();
            mTypeZeroSmsDetected = false;
        }
    }

    /**
     * Set or update the Notification
     */
    public void setNotification() {

        String tickerText;
        String contentText = "Phone Type " + mDevice.getPhoneType();

        String iconType = prefs.getString(this.getString(R.string.pref_ui_icons_key), "sense");

        int status;

        if (mFemtoDetected || mTypeZeroSmsDetected) {
            status = 4; //ALARM
        } else if (mChangedLAC) {
            status = 3; //MEDIUM
            contentText = "Hostile Service Area: Changing LAC Detected";
        } else if (mTrackingFemtocell || mTrackingCell || mLoaded) {
            status = 2; //NORMAL
            if (mTrackingFemtocell) {
                contentText = "FemtoCell Detection Active";
            } else if (mTrackingCell) {
                contentText = "Cell Tracking Active";
            }
        } else {
            status = 1; //IDLE
        }

        int icon = R.drawable.sense_idle;

        switch (status) {
        case 1: //IDLE
            switch (iconType) {
            case "flat":
                icon = R.drawable.flat_idle;
                break;
            case "sense":
                icon = R.drawable.sense_idle;
                break;
            case "white":
                icon = R.drawable.white_idle;
                break;
            }
            tickerText = getResources().getString(R.string.app_name_short) + " - Status: Idle";
            break;
        case 2: //NORMAL
            switch (iconType) {
            case "flat":
                icon = R.drawable.flat_ok;
                break;
            case "sense":
                icon = R.drawable.sense_ok;
                break;
            case "white":
                icon = R.drawable.white_ok;
                break;
            }
            tickerText = getResources().getString(R.string.app_name_short) + " - Status: Good No Threats Detected";
            break;
        case 3: //MEDIUM
            switch (iconType) {
            case "flat":
                icon = R.drawable.flat_medium;
                break;
            case "sense":
                icon = R.drawable.sense_medium;
                break;
            case "white":
                icon = R.drawable.white_medium;
                break;
            }
            tickerText = getResources().getString(R.string.app_name_short)
                    + " - Hostile Service Area: Changing LAC Detected";
            break;
        case 4: //DANGER
            switch (iconType) {
            case "flat":
                icon = R.drawable.flat_danger;
                break;
            case "sense":
                icon = R.drawable.sense_danger;
                break;
            case "white":
                icon = R.drawable.white_danger;
                break;
            }
            tickerText = getResources().getString(R.string.app_name_short) + " - ALERT!! Threat Detected";
            if (mFemtoDetected) {
                contentText = "ALERT!! FemtoCell Connection Threat Detected";
            } else if (mTypeZeroSmsDetected) {
                contentText = "ALERT!! Type Zero Silent SMS Intercepted";
            }

            break;
        default:
            icon = R.drawable.sense_idle;
            tickerText = getResources().getString(R.string.app_name);
            break;
        }

        Intent notificationIntent = new Intent(mContext, AIMSICD.class);
        notificationIntent.putExtra("silent_sms", mTypeZeroSmsDetected);
        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_FROM_BACKGROUND);
        PendingIntent contentIntent = PendingIntent.getActivity(mContext, NOTIFICATION_ID, notificationIntent,
                PendingIntent.FLAG_CANCEL_CURRENT);
        Notification mBuilder = new NotificationCompat.Builder(this).setSmallIcon(icon).setTicker(tickerText)
                .setContentTitle(this.getResources().getString(R.string.app_name)).setContentText(contentText)
                .setOngoing(true).setAutoCancel(false).setContentIntent(contentIntent).build();

        NotificationManager mNotificationManager = (NotificationManager) this
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder);
    }

    /**
     * Cancel and remove the persistent notification
     */
    private void cancelNotification() {
        NotificationManager notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
        if (notificationManager != null) {
            notificationManager.cancel(NOTIFICATION_ID);
        }
    }

    public Location lastKnownLocation() {
        Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (location == null || (location.getLatitude() == 0.0 && location.getLongitude() == 0.0)) {
            location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            if (location == null || (location.getLatitude() == 0.0 && location.getLongitude() == 0.0)) {

            }
        }

        return location;
    }

    public void setLoaded() {
        mLoaded = true;
        setNotification();
    }

    public boolean isMonitoringCell() {
        return mMonitoringCell;
    }

    private LocationListener cellMonitorListener = new MyLocationListener();

    /**
     * Cell Information Monitoring
     *
     * @param monitor Enable/Disable monitoring
     */
    public void setCellMonitoring(boolean monitor) {
        if (monitor) {
            timerHandler.postDelayed(timerRunnable, 0);
            mMonitoringCell = true;
            Helpers.msgShort(this, "Monitoring cell information");
        } else {
            timerHandler.removeCallbacks(timerRunnable);
            mMonitoringCell = false;
            Helpers.msgShort(this, "Stopped monitoring cell information");
        }
    }

    private final Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            switch (mDevice.getPhoneID()) {
            case TelephonyManager.PHONE_TYPE_GSM:
                GsmCellLocation gsmCellLocation = (GsmCellLocation) tm.getCellLocation();
                if (gsmCellLocation != null) {
                    mMonitorCell.setLAC(gsmCellLocation.getLac());
                    mMonitorCell.setCID(gsmCellLocation.getCid());
                    dbHelper.open();
                    boolean lacOK = dbHelper.checkLAC(mMonitorCell);
                    if (!lacOK) {
                        mChangedLAC = true;
                        setNotification();
                    }
                    dbHelper.close();
                }
                break;
            case TelephonyManager.PHONE_TYPE_CDMA:
                CdmaCellLocation cdmaCellLocation = (CdmaCellLocation) tm.getCellLocation();
                if (cdmaCellLocation != null) {
                    mMonitorCell.setLAC(cdmaCellLocation.getNetworkId());
                    mMonitorCell.setCID(cdmaCellLocation.getBaseStationId());
                    dbHelper.open();
                    boolean lacOK = dbHelper.checkLAC(mMonitorCell);
                    if (!lacOK) {
                        mChangedLAC = true;
                        setNotification();
                    }
                    dbHelper.close();
                }
            }
            if (REFRESH_RATE != 0) {
                timerHandler.postDelayed(this, REFRESH_RATE);
            } else {
                //Default to 25 seconds refresh rate
                timerHandler.postDelayed(this, TimeUnit.SECONDS.toMillis(25));
            }
        }
    };

    /**
     * Cell Information Tracking and database logging
     *
     * @param track Enable/Disable tracking
     */
    public void setCellTracking(boolean track) {
        if (track) {
            tm.listen(mCellSignalListener,
                    PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
                            | PhoneStateListener.LISTEN_DATA_ACTIVITY
                            | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
            if (lm != null) {
                mLocationListener = new MyLocationListener();
                Log.i(TAG, "LocationManager already existed");
                lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_MIN_UPDATE_TIME,
                        GPS_MIN_UPDATE_DISTANCE, mLocationListener);
            } else {
                Log.i(TAG, "LocationManager did not exist");
                lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
                if (lm != null) {
                    if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                        Log.i(TAG, "LocationManager created");
                        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_MIN_UPDATE_TIME,
                                GPS_MIN_UPDATE_DISTANCE, mLocationListener);
                    }
                }
            }
            Helpers.msgShort(this, "Tracking cell information");
            mTrackingCell = true;
        } else {
            tm.listen(mCellSignalListener, PhoneStateListener.LISTEN_NONE);
            lm.removeUpdates(mLocationListener);
            mDevice.mCell.setLon(0.0);
            mDevice.mCell.setLat(0.0);
            mTrackingCell = false;
            mDevice.setCellInfo("[0,0]|nn|nn|");
            Helpers.msgShort(this, "Stopped tracking cell information");
        }
        setNotification();
    }

    private final PhoneStateListener mCellSignalListener = new PhoneStateListener() {
        public void onCellLocationChanged(CellLocation location) {
            mDevice.setNetID(tm);
            mDevice.getNetworkTypeName();

            switch (mDevice.getPhoneID()) {
            case TelephonyManager.PHONE_TYPE_GSM:
                GsmCellLocation gsmCellLocation = (GsmCellLocation) location;
                if (gsmCellLocation != null) {
                    mDevice.setCellInfo(gsmCellLocation.toString() + mDevice.getDataActivityTypeShort() + "|"
                            + mDevice.getDataStateShort() + "|" + mDevice.getNetworkTypeName() + "|");
                    mDevice.mCell.setLAC(gsmCellLocation.getLac());
                    mDevice.mCell.setCID(gsmCellLocation.getCid());
                    if (gsmCellLocation.getPsc() != -1)
                        mDevice.mCell.setPSC(gsmCellLocation.getPsc());

                }
                break;
            case TelephonyManager.PHONE_TYPE_CDMA:
                CdmaCellLocation cdmaCellLocation = (CdmaCellLocation) location;
                if (cdmaCellLocation != null) {
                    mDevice.setCellInfo(cdmaCellLocation.toString() + mDevice.getDataActivityTypeShort() + "|"
                            + mDevice.getDataStateShort() + "|" + mDevice.getNetworkTypeName() + "|");
                    mDevice.mCell.setLAC(cdmaCellLocation.getNetworkId());
                    mDevice.mCell.setCID(cdmaCellLocation.getBaseStationId());
                    mDevice.mCell.setSID(cdmaCellLocation.getSystemId());
                    mDevice.mCell.setMNC(cdmaCellLocation.getSystemId());
                    mDevice.setNetworkName(tm.getNetworkOperatorName());
                }
            }

        }

        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            //Update Signal Strength
            if (signalStrength.isGsm()) {
                mDevice.setSignalDbm(signalStrength.getGsmSignalStrength());
            } else {
                int evdoDbm = signalStrength.getEvdoDbm();
                int cdmaDbm = signalStrength.getCdmaDbm();

                //Use lowest signal to be conservative
                mDevice.setSignalDbm((cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm);
            }
        }

        public void onDataActivity(int direction) {
            switch (direction) {
            case TelephonyManager.DATA_ACTIVITY_NONE:
                mDevice.setDataActivityTypeShort("No");
                mDevice.setDataActivityType("None");
                break;
            case TelephonyManager.DATA_ACTIVITY_IN:
                mDevice.setDataActivityTypeShort("In");
                mDevice.setDataActivityType("In");
                break;
            case TelephonyManager.DATA_ACTIVITY_OUT:
                mDevice.setDataActivityTypeShort("Ou");
                mDevice.setDataActivityType("Out");
                break;
            case TelephonyManager.DATA_ACTIVITY_INOUT:
                mDevice.setDataActivityTypeShort("IO");
                mDevice.setDataActivityType("In-Out");
                break;
            case TelephonyManager.DATA_ACTIVITY_DORMANT:
                mDevice.setDataActivityTypeShort("Do");
                mDevice.setDataActivityType("Dormant");
                break;
            }
        }

        public void onDataConnectionStateChanged(int state) {
            switch (state) {
            case TelephonyManager.DATA_DISCONNECTED:
                mDevice.setDataState("Disconnected");
                mDevice.setDataStateShort("Di");
                break;
            case TelephonyManager.DATA_CONNECTING:
                mDevice.setDataState("Connecting");
                mDevice.setDataStateShort("Ct");
                break;
            case TelephonyManager.DATA_CONNECTED:
                mDevice.setDataState("Connected");
                mDevice.setDataStateShort("Cd");
                break;
            case TelephonyManager.DATA_SUSPENDED:
                mDevice.setDataState("Suspended");
                mDevice.setDataStateShort("Su");
                break;
            }
        }

    };

    private void enableLocationServices() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.location_error_message).setTitle(R.string.location_error_title)
                .setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent gpsSettings = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        gpsSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(gpsSettings);
                    }
                }).setNegativeButton(R.string.text_cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        setCellTracking(false);
                    }
                });
        AlertDialog alert = builder.create();
        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alert.show();
    }

    private class MyLocationListener implements LocationListener {

        @Override
        public void onLocationChanged(Location loc) {
            if (mDevice.isBetterLocation(loc, mDevice.getLastLocation())) {
                if (Build.VERSION.SDK_INT > 16) {
                    List<CellInfo> cellinfolist = tm.getAllCellInfo();
                    if (cellinfolist != null) {
                        for (final CellInfo cellinfo : cellinfolist) {
                            if (cellinfo instanceof CellInfoGsm) {
                                final CellSignalStrengthGsm signalStrengthGsm = ((CellInfoGsm) cellinfo)
                                        .getCellSignalStrength();
                                final CellIdentityGsm identityGsm = ((CellInfoGsm) cellinfo).getCellIdentity();
                                if (identityGsm != null) {
                                    mDevice.mCell.setCID(identityGsm.getCid());
                                    mDevice.mCell.setLAC(identityGsm.getLac());
                                    mDevice.mCell.setMCC(identityGsm.getMcc());
                                    mDevice.mCell.setMNC(identityGsm.getMnc());
                                }
                                if (signalStrengthGsm != null) {
                                    mDevice.mCell.setDBM(signalStrengthGsm.getDbm());
                                }
                                break;
                            } else if (cellinfo instanceof CellInfoCdma) {
                                final CellSignalStrengthCdma signalStrengthCdma = ((CellInfoCdma) cellinfo)
                                        .getCellSignalStrength();
                                final CellIdentityCdma identityCdma = ((CellInfoCdma) cellinfo).getCellIdentity();
                                if (identityCdma != null) {
                                    mDevice.mCell.setCID(identityCdma.getBasestationId());
                                    mDevice.mCell.setLAC(identityCdma.getNetworkId());
                                    mDevice.mCell.setMNC(identityCdma.getSystemId());
                                    mDevice.mCell.setSID(identityCdma.getSystemId());
                                }

                                if (signalStrengthCdma != null) {
                                    mDevice.setSignalDbm(signalStrengthCdma.getDbm());
                                }
                                break;
                            } else if (cellinfo instanceof CellInfoLte) {
                                final CellSignalStrengthLte signalStrengthLte = ((CellInfoLte) cellinfo)
                                        .getCellSignalStrength();
                                final CellIdentityLte identityLte = ((CellInfoLte) cellinfo).getCellIdentity();

                                if (identityLte != null) {
                                    mDevice.mCell.setCID(identityLte.getPci());
                                    mDevice.mCell.setLAC(identityLte.getTac());
                                    mDevice.mCell.setMCC(identityLte.getMcc());
                                    mDevice.mCell.setMNC(identityLte.getMnc());
                                }

                                if (signalStrengthLte != null) {
                                    mDevice.setSignalDbm(signalStrengthLte.getDbm());
                                }
                                break;
                            } else if (cellinfo instanceof CellInfoWcdma) {
                                final CellSignalStrengthWcdma signalStrengthWcdma = ((CellInfoWcdma) cellinfo)
                                        .getCellSignalStrength();
                                final CellIdentityWcdma identityWcdma = ((CellInfoWcdma) cellinfo)
                                        .getCellIdentity();
                                if (identityWcdma != null) {
                                    mDevice.mCell.setCID(identityWcdma.getCid());
                                    mDevice.mCell.setLAC(identityWcdma.getLac());
                                    mDevice.mCell.setMCC(identityWcdma.getMcc());
                                    mDevice.mCell.setMNC(identityWcdma.getMnc());
                                }

                                if (signalStrengthWcdma != null) {
                                    mDevice.setSignalDbm(signalStrengthWcdma.getDbm());
                                }
                                break;
                            }
                        }
                    }
                }

                if (!mDevice.mCell.isValid()) {
                    CellLocation cellLocation = tm.getCellLocation();
                    if (cellLocation != null) {
                        switch (mDevice.getPhoneID()) {
                        case TelephonyManager.PHONE_TYPE_GSM:
                            GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
                            mDevice.mCell.setCID(gsmCellLocation.getCid());
                            mDevice.mCell.setLAC(gsmCellLocation.getLac());
                            mDevice.mCell.setPSC(gsmCellLocation.getPsc());
                            break;
                        case TelephonyManager.PHONE_TYPE_CDMA:
                            CdmaCellLocation cdmaCellLocation = (CdmaCellLocation) cellLocation;
                            mDevice.mCell.setCID(cdmaCellLocation.getBaseStationId());
                            mDevice.mCell.setLAC(cdmaCellLocation.getNetworkId());
                            mDevice.mCell.setSID(cdmaCellLocation.getSystemId());
                            mDevice.mCell.setMNC(cdmaCellLocation.getSystemId());
                        }
                    }
                }

                if (loc != null && (loc.getLatitude() != 0.0 && loc.getLongitude() != 0.0)) {
                    mDevice.mCell.setLon(loc.getLongitude());
                    mDevice.mCell.setLat(loc.getLatitude());
                    mDevice.mCell.setSpeed(loc.getSpeed());
                    mDevice.mCell.setAccuracy(loc.getAccuracy());
                    mDevice.mCell.setBearing(loc.getBearing());
                    mDevice.setLastLocation(loc);

                    if (mTrackingCell) {
                        dbHelper.open();
                        mDbResult = dbHelper.insertLocation(mDevice.mCell.getLAC(), mDevice.mCell.getCID(),
                                mDevice.mCell.getNetType(), mDevice.mCell.getLat(), mDevice.mCell.getLon(),
                                mDevice.mCell.getDBM(), mDevice.getCellInfo());

                        mDbResult = dbHelper.insertCell(mDevice.mCell.getLAC(), mDevice.mCell.getCID(),
                                mDevice.mCell.getNetType(), mDevice.mCell.getLat(), mDevice.mCell.getLon(),
                                mDevice.mCell.getDBM(), mDevice.mCell.getMCC(), mDevice.mCell.getMNC(),
                                mDevice.mCell.getAccuracy(), mDevice.mCell.getSpeed(), mDevice.mCell.getBearing(),
                                mDevice.getNetworkTypeName(), SystemClock.currentThreadTimeMillis());

                        if (mDbResult == -1) {
                            Log.e(TAG, "Error writing to database");
                        }
                    }
                }
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
            if (!mLocationPrompted) {
                mLocationPrompted = true;
                enableLocationServices();
            }
        }

        @Override
        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub
        }
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        final String KEY_UI_ICONS = this.getString(R.string.pref_ui_icons_key);
        final String FEMTO_DECTECTION = this.getString(R.string.pref_femto_detection_key);
        final String REFRESH = this.getString(R.string.pref_refresh_key);
        final String DB_VERSION = this.getString(R.string.pref_last_database_backup_version);
        final String OCID_UPLOAD = this.getString(R.string.pref_ocid_upload);

        if (key.equals(KEY_UI_ICONS)) {
            //Update Notification to display selected icon type
            setNotification();
        } else if (key.equals(FEMTO_DECTECTION)) {
            boolean trackFemtoPref = sharedPreferences.getBoolean(FEMTO_DECTECTION, false);
            if (trackFemtoPref) {
                startTrackingFemto();
            } else {
                stopTrackingFemto();
            }
        } else if (key.equals(REFRESH)) {
            String refreshRate = sharedPreferences.getString(REFRESH, "1");
            if (refreshRate.isEmpty()) {
                refreshRate = "1";
            }

            int rate = Integer.parseInt(refreshRate);
            long t;
            switch (rate) {
            case 1:
                t = 15L;
                break;
            default:
                t = (rate * 1L);
                break;
            }
            REFRESH_RATE = TimeUnit.SECONDS.toMillis(t);
        } else if (key.equals(DB_VERSION)) {
            LAST_DB_BACKUP_VERSION = sharedPreferences.getInt(DB_VERSION, 1);
        } else if (key.equals(OCID_UPLOAD)) {
            OCID_UPLOAD_PREF = sharedPreferences.getBoolean(OCID_UPLOAD, false);
        }
    }

    /*
     * The below code section was copied and modified from
     * Femtocatcher https://github.com/iSECPartners/femtocatcher
     *
     * Copyright (C) 2013 iSEC Partners
     */

    /**
     * Start FemtoCell detection tracking
     * CDMA Devices ONLY
     */
    public void startTrackingFemto() {

        /* Check if it is a CDMA phone */
        if (mDevice.getPhoneID() != TelephonyManager.PHONE_TYPE_CDMA) {
            Helpers.msgShort(this, "AIMSICD can only detect Femtocell connections on CDMA devices.");
            return;
        }

        mTrackingFemtocell = true;
        mPhoneStateListener = new PhoneStateListener() {
            public void onServiceStateChanged(ServiceState s) {
                Log.d(TAG, "Service State changed!");
                getServiceStateInfo(s);
            }
        };
        tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_LOCATION);
        tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
        setNotification();
    }

    /**
     * Stop FemtoCell detection tracking
     * CDMA Devices ONLY
     */
    public void stopTrackingFemto() {
        if (mPhoneStateListener != null) {
            tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
            mTrackingFemtocell = false;
            setNotification();
            Log.v(TAG, "Stopped tracking Femtocell connections");
        }
    }

    private void getServiceStateInfo(ServiceState s) {
        if (s != null) {
            if (IsConnectedToCdmaFemto(s)) {
                Helpers.msgShort(this, "ALERT!! Femtocell Connection Detected!!");
                mFemtoDetected = true;
                setNotification();
                //toggleRadio();
            } else {
                mFemtoDetected = false;
                setNotification();
            }
        }
    }

    private boolean IsConnectedToCdmaFemto(ServiceState s) {
        if (s == null) {
            return false;
        }

        /* Get International Roaming indicator
         * if indicator is not 0 return false
         */

        /* Get the radio technology */
        int networkType = mDevice.mCell.getNetType();

        /* Check if it is EvDo network */
        boolean evDoNetwork = isEvDoNetwork(networkType);

        /* If it is not an evDo network check the network ID range.
         * If it is connected to femtocell, the nid should be lie between [0xfa, 0xff)
         */
        if (!evDoNetwork) {
            /* get network ID */
            if (tm != null) {
                CdmaCellLocation c = (CdmaCellLocation) tm.getCellLocation();

                if (c != null) {
                    int networkID = c.getNetworkId();
                    int FEMTO_NID_MAX = 0xff;
                    int FEMTO_NID_MIN = 0xfa;
                    return !((networkID < FEMTO_NID_MIN) || (networkID >= FEMTO_NID_MAX));

                } else {
                    Log.v(TAG, "Cell location info is null.");
                    return false;
                }
            } else {
                Log.v(TAG, "Telephony Manager is null.");
                return false;
            }
        }

        /* if it is an evDo network */
        // TODO
        else {
            /* get network ID */
            if (tm != null) {
                CdmaCellLocation c = (CdmaCellLocation) tm.getCellLocation();

                if (c != null) {
                    int networkID = c.getNetworkId();

                    int FEMTO_NID_MAX = 0xff;
                    int FEMTO_NID_MIN = 0xfa;
                    return !((networkID < FEMTO_NID_MIN) || (networkID >= FEMTO_NID_MAX));
                } else {
                    Log.v(TAG, "Cell location info is null.");
                    return false;
                }
            } else {
                Log.v(TAG, "Telephony Manager is null.");
                return false;
            }
        }

    }

    /**
     * Confirmation of connection to an EVDO Network
     *
     * @return EVDO network connection returns TRUE
     */
    private boolean isEvDoNetwork(int networkType) {
        return (networkType == TelephonyManager.NETWORK_TYPE_EVDO_0)
                || (networkType == TelephonyManager.NETWORK_TYPE_EVDO_A)
                || (networkType == TelephonyManager.NETWORK_TYPE_EVDO_B)
                || (networkType == TelephonyManager.NETWORK_TYPE_EHRPD);
    }
    /*
     * The above code section was copied and modified from
     * Femtocatcher https://github.com/iSECPartners/femtocatcher
     *
     * Copyright (C) 2013 iSEC Partners
     */

}