org.restcomm.app.qoslib.Services.TrackingManager.java Source code

Java tutorial

Introduction

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

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.preference.PreferenceManager;

import org.restcomm.app.qoslib.MainService;
import org.restcomm.app.qoslib.Services.Intents.IntentHandler;
import org.restcomm.app.utillib.DataObjects.EventType;
import org.restcomm.app.utillib.Utils.LoggerUtil;
import org.restcomm.app.utillib.Utils.PreferenceKeys;

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

/**
 * 
 * @author nasrullah
 */
public class TrackingManager {
    public static final String TAG = TrackingManager.class.getSimpleName();

    private MainService owner;
    //private Timer timer;
    private Handler handler = new Handler();
    private int trackingElapsed = 0;
    private int durMinutes = 0;
    //private long trackingExpires = 0;
    //private boolean bCoverage = true, bSpeed = false, bTracking = false;
    private boolean bTracking = false;
    private int coverageInterval = 5, speedtestInterval = 0, videoInterval = 0, audioInterval = 0;
    private int webInterval = 0, smsInterval = 0, connectInterval = 0, vqInterval = 0, youtubeInterval = 0;
    private int advancedIndex = 0;
    private boolean advancedWaiting = false;
    private int count = 0;
    private String testTrigger = "";
    private Runnable testRunnable = null;
    private JSONArray scheduledCommands = null;

    public TrackingManager(MainService owner) {
        this.owner = owner;
    }

    public void resumeTracking() {
        try {
            String cmd = PreferenceManager.getDefaultSharedPreferences(owner)
                    .getString(PreferenceKeys.Miscellaneous.DRIVE_TEST_CMD, null);
            //long expires = PreferenceManager.getDefaultSharedPreferences(owner).getLong(PreferenceKeys.Miscellaneous.TRACKING_EXPIRES, 0);
            int elapsed = PreferenceManager.getDefaultSharedPreferences(owner)
                    .getInt(PreferenceKeys.Miscellaneous.TRACKING_ELAPSED, 0);
            //advancedIndex = PreferenceManager.getDefaultSharedPreferences(owner).getInt(PreferenceKeys.Miscellaneous.DRIVETEST_INDEX, -1);
            durMinutes = 0;

            if (cmd != null) {
                JSONObject cmdJson = new JSONObject(cmd);

                if (cmdJson.has("schedule")) {
                    JSONObject testSchedule = cmdJson.getJSONObject("schedule");
                    if (testSchedule.getInt("dur") > 0) {
                        durMinutes = testSchedule.getInt("dur");
                        if (elapsed >= durMinutes * 60)
                            return;
                        //                  if (expires > System.currentTimeMillis()) {
                        //                     int numFiveMinutePeriods = (int) (expires - System.currentTimeMillis());
                        //                     numFiveMinutePeriods = numFiveMinutePeriods / (5 * 60000) + 1;
                        //
                        //                     testSchedule.put("dur", numFiveMinutePeriods);
                        //                  }
                        //                  else
                        //                     return;
                    }
                    if (testSchedule.has("trigger")) {
                        testTrigger = testSchedule.getString("trigger");
                        //testSchedule.put("dur", 0);
                    }
                    startAdvancedTracking(cmdJson, 0, false);
                } else {
                    JSONObject testSettings = cmdJson.getJSONObject("settings");
                    if (testSettings.getInt("dur") > 0) {
                        durMinutes = testSettings.getInt("dur");
                        if (elapsed >= durMinutes * 60)
                            return;
                        //                  {
                        //                     int numFiveMinutePeriods = (int) (expires - System.currentTimeMillis());
                        //                     numFiveMinutePeriods = numFiveMinutePeriods / (5 * 60000) + 1;
                        //
                        //                     testSettings.put("dur", numFiveMinutePeriods);
                        //                  }
                        //                  else
                        //                     return;
                    }

                    startTracking(cmdJson, 0, false);
                }
                //trackingExpires = expires;
                trackingElapsed = elapsed;

                LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "resumeTracking",
                        "elapsed=" + elapsed + ",cmd=" + cmd);

            }

        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "resumeTracking",
                    "Exception reading stored tracking settings");
        }

    }

    public void startAdvancedTracking(JSONObject cmdJson, long starttime, boolean resetElapsed) {
        try {
            //JSONObject commands = cmdJson.getJSONObject("commands");
            JSONObject schedule = cmdJson.getJSONObject("schedule");

            if (schedule.has("dur"))
                durMinutes = schedule.getInt("dur");
            else
                durMinutes = 5;
            // If script is starting fresh (not from a trigger), elapsed time is reset to 0
            if (resetElapsed)
                trackingElapsed = 0;
            prevTrackingTime = System.currentTimeMillis();
            //numFiveMinutePeriods = (numFiveMinutePeriods + 4) / 5;
            if (durMinutes == 0) // continuous tracking
            {
                //trackingExpires = 0;
                // store a tracking expiry date of 10 million seconds from now
                PreferenceManager.getDefaultSharedPreferences(owner).edit()
                        .putInt(PreferenceKeys.Miscellaneous.TRACKING_ELAPSED, trackingElapsed).commit();
                PreferenceManager.getDefaultSharedPreferences(owner).edit()
                        .putLong(PreferenceKeys.Miscellaneous.ENGINEER_MODE_EXPIRES_TIME,
                                System.currentTimeMillis())
                        .commit();
            }

            if (schedule.has("trigger") && !schedule.getString("trigger").equals("")) {
                //            testTriggerOpt = schedule.getString("opt");
                //            if (testTriggerOpt.equals("once") || testTriggerOpt.equals("always"))
                //               testTrigger = "travel";
                //            else
                //               testTrigger = "";
                testTrigger = schedule.getString("trigger");
                // Initally, when not yet travelling, just wait for travel
                if (!owner.getTravelDetector().isTravelling() || !owner.getTravelDetector().isConfirmed())
                    return;
            } else
                testTrigger = "";

            if (schedule.has("commands")) {
                // The active test commands will be scheduled in a special
                scheduledCommands = schedule.getJSONArray("commands");
                advancedIndex = 0;
                //bTracking = true;

                // Run the normal Signal tracking as usual
                startCoverageTracking();
                long startDelay = 1000;
                if (starttime > System.currentTimeMillis())
                    startDelay = starttime - System.currentTimeMillis();

                handler.postDelayed(testRunnable = new Runnable() {
                    public void run() {
                        runAdvancedTrackingTests();
                    }
                }, startDelay);
            }
        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "startTracking", "exception", e);
        }
    }

    public void startCoverageTracking() {
        bTracking = true;
        this.owner.keepAwake(true, true);
        AlarmManager alarmMgr = (AlarmManager) owner.getSystemService(Service.ALARM_SERVICE);
        Intent intent = new Intent(IntentHandler.ACTION_TRACKING_5MINUTE);
        PendingIntent alarm = PendingIntent.getBroadcast(owner, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        alarmMgr.cancel(alarm);
        //trackingExpires = System.currentTimeMillis() + (numFiveMinutePeriods) * 5L * 60L * 1000L;

        //PreferenceManager.getDefaultSharedPreferences(owner).edit().putLong(PreferenceKeys.Miscellaneous.TRACKING_EXPIRES, trackingExpires).commit();
        long expiresTime = System.currentTimeMillis() + (durMinutes * 60 - trackingElapsed) * 1000;
        PreferenceManager.getDefaultSharedPreferences(owner).edit()
                .putLong(PreferenceKeys.Miscellaneous.ENGINEER_MODE_EXPIRES_TIME, expiresTime).commit();

        long delay = 0;
        if (durMinutes == 0) // continuous tracking
        {
            //trackingExpires = 0;
            // store a tracking expiry date of 10 million seconds from now
            //PreferenceManager.getDefaultSharedPreferences(owner).edit().putLong(PreferenceKeys.Miscellaneous.TRACKING_EXPIRES, System.currentTimeMillis()+10000000000l).commit();
            PreferenceManager.getDefaultSharedPreferences(owner).edit()
                    .putLong(PreferenceKeys.Miscellaneous.ENGINEER_MODE_EXPIRES_TIME, System.currentTimeMillis())
                    .commit();
        }
        LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "startTracking",
                "durationMinutes=" + durMinutes + ",covInterval=" + coverageInterval + ",SpeedInterval="
                        + speedtestInterval + ",videoInterval=" + videoInterval);

        delay = 5L * 60L * 1000L;
        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000, delay, alarm);
    }

    public void startTracking(JSONObject cmdJson, long starttime, boolean resetElapsed) {
        try {
            //         if (true)
            //         {
            //            //String json = "{\"commands\":{\"schedule\":{\"dur\":1,\"commands\":[{\"mmctype\":\"speed\",\"loop\":2,\"settings\":{}}]}},\"userid\":99323899,\"carrierid\":1381,\"deviceid\":\"0de9614b-558b-4d82-b62f-c78c75882e85\"}";
            String json = "{\"schedule\":{\"dur\":6,\"commands\":[{\"mmctype\":\"speed\",\"loop\":2,\"settings\":{}},{\"mmctype\":\"predelay\",\"loop\":60,\"settings\":{}},{\"mmctype\":\"ue\",\"loop\":1,\"settings\":{}},{\"mmctype\":\"audio\",\"loop\":2,\"settings\":{}},{\"mmctype\":\"postdelay\",\"loop\":60,\"settings\":{}}]},\"userid\":78,\"carrierid\":1,\"deviceid\":\"5f0cc3b0-8b1e-4493-bd3d-3dd234d66e03\"}";
            //            cmdJson = new JSONObject(json);
            //            startAdvancedTracking (cmdJson);
            //            return;
            //         }
            JSONObject testSettings = cmdJson.getJSONObject("settings");
            if (resetElapsed)
                trackingElapsed = 0;
            prevTrackingTime = System.currentTimeMillis();

            if (testSettings.has("dur"))
                durMinutes = testSettings.getInt("dur");
            else
                durMinutes = 15;
            if (testSettings.has("cov"))
                this.coverageInterval = testSettings.getInt("cov");
            if (testSettings.has("spd"))
                this.speedtestInterval = testSettings.getInt("spd");
            if (testSettings.has("vid"))
                this.videoInterval = testSettings.getInt("vid");
            if (testSettings.has("ct"))
                this.connectInterval = testSettings.getInt("ct");
            if (testSettings.has("sms"))
                this.smsInterval = testSettings.getInt("sms");
            if (testSettings.has("web"))
                this.webInterval = testSettings.getInt("web");
            if (testSettings.has("youtube"))
                this.youtubeInterval = testSettings.getInt("youtube");
            if (testSettings.has("vq"))
                this.vqInterval = testSettings.getInt("vq");
            if (testSettings.has("aud"))
                this.audioInterval = testSettings.getInt("aud");

            startCoverageTracking();
            long startDelay = 1000;
            if (starttime > System.currentTimeMillis())
                startDelay = starttime - System.currentTimeMillis();

            handler.postDelayed(testRunnable = new Runnable() {
                public void run() {
                    runTrackingTests();
                }
            }, startDelay);
        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.ERROR, TAG, "startTracking", "exception", e);
        }
    }

    public boolean isTracking() {
        //if (timer != null && (trackingExpires > System.currentTimeMillis() || trackingExpires == 0))
        if (bTracking == true) // && (trackingExpires+0*280000 > System.currentTimeMillis() || trackingExpires == 0))
            return true;
        else {
            bTracking = false;
            return false;
        }
    }

    public String getDriveTestTrigger() {
        return testTrigger;
    }

    public void setDriveTestTrigger(String trig) {
        testTrigger = trig;
    }

    // A Drive test script may wait and be triggered by travel detection, or other means
    public void triggerDriveTest(String reason, boolean start) {
        String cmd = PreferenceManager.getDefaultSharedPreferences(owner)
                .getString(PreferenceKeys.Miscellaneous.DRIVE_TEST_CMD, null);
        if (cmd == null)
            return;
        try {
            JSONObject cmdsJson = new JSONObject(cmd);
            JSONObject testSchedule = cmdsJson.getJSONObject("schedule");

            if (start) {
                // If drive test is to be triggered only once, disable it after starting
                //            if (testTriggerOpt != null && testTriggerOpt.equals("once")) {
                //               testTriggerOpt = "disabled";
                //               testSchedule.put ("opt", "disabled");
                //            }
                startAdvancedTracking(cmdsJson, 0, false);
            } else {
                //            if (testTriggerOpt != null && testTriggerOpt.equals("disabled")) {
                //               testTrigger = "";
                //            }
                owner.getEventManager().stopTracking();
            }
        } catch (JSONException e) {
        }
    }

    public int getTestScriptIndex() {
        return advancedIndex;
    }

    public boolean isAdvancedTrackingWaiting() {
        //if (timer != null && (trackingExpires > System.currentTimeMillis() || trackingExpires == 0))
        if (bTracking == true) // && (trackingExpires+0*280000 > System.currentTimeMillis() || trackingExpires == 0))
        {
            if (advancedIndex >= 0 && advancedWaiting)
                return true;
        } else {
            bTracking = false;
            return false;
        }
        return false;
    }

    /**
     * Cancels all scheduled tracking events.
     * Does not stop a currently running tracking event.
     */
    public void cancelScheduledEvents() {
        //if(timer != null) {
        //   timer.cancel();
        //   timer = null;
        //}
        try {
            LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "cancelScheduledEvents", "");
            bTracking = false;

            if (prevTrackingTime > 0) {
                trackingElapsed += (System.currentTimeMillis() - prevTrackingTime + 500) / 1000;
                PreferenceManager.getDefaultSharedPreferences(owner).edit()
                        .putInt(PreferenceKeys.Miscellaneous.TRACKING_ELAPSED, trackingElapsed).commit();
                if (durMinutes > 0 && trackingElapsed >= (durMinutes - 1) * 60) {
                    testTrigger = "";
                }
            }
            prevTrackingTime = System.currentTimeMillis();

            if (testTrigger.equals(""))
                trackingElapsed = 1000000;
            //trackingExpires = System.currentTimeMillis() - 10000;
            PreferenceManager.getDefaultSharedPreferences(owner).edit()
                    .putInt(PreferenceKeys.Miscellaneous.TRACKING_ELAPSED, trackingElapsed).commit();
            PreferenceManager.getDefaultSharedPreferences(owner).edit()
                    .putLong(PreferenceKeys.Miscellaneous.ENGINEER_MODE_EXPIRES_TIME, 0L).commit();

            AlarmManager alarmMgr = (AlarmManager) owner.getSystemService(Service.ALARM_SERVICE);
            Intent intent = new Intent(IntentHandler.ACTION_TRACKING_5MINUTE);
            PendingIntent alarm = PendingIntent.getBroadcast(owner, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
            alarmMgr.cancel(alarm);
            handler.removeCallbacks(testRunnable);

        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "cancelScheduledEvents", "Exception", e);
        }
    }

    // every 1 minute, execute drive tests that come due
    public void runTrackingTests() {
        if (trackingElapsed < durMinutes * 60 || bTracking == false)
            return;

        try {
            if (bTracking && (durMinutes == 0 || trackingElapsed < durMinutes * 60 + 30)) {

                handler.postDelayed(testRunnable = new Runnable() {
                    public void run() {
                        runTrackingTests();
                    }
                }, 60L * 1000L);

            }
        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "startTracking", "start:Exception", e);
        }

        if (speedtestInterval > 0 && (count % speedtestInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.MAN_SPEEDTEST, 2);
        }

        if (connectInterval > 0 && (count % connectInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.LATENCY_TEST, 2);
        }
        if (smsInterval > 0 && (count % smsInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.SMS_TEST, 2);
        }
        if (webInterval > 0 && (count % webInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.WEBPAGE_TEST, 2);
        }
        if (youtubeInterval > 0 && (count % youtubeInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.YOUTUBE_TEST, 2);
        }
        if (vqInterval > 0 && (count % vqInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.EVT_VQ_CALL, 2);
            //owner.triggerWebTest(2);
            //Intent intent = new Intent(CommonIntentBundleKeysOld.ACTION_START_VOICETEST);
            //MMCLogger.logToFile(MMCLogger.Level.ERROR, TAG, "runTracking", "beginVoiceTest");
            //owner.sendBroadcast(intent);
        }
        if (videoInterval > 0 && (count % videoInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.VIDEO_TEST, 2);
            //tasks.add(new Runnable() {
            //    @Override public void run() {
            //        owner.triggerActiveTest(2, EventType.VIDEO_TEST.getIntValue()); }});
        }
        if (audioInterval > 0 && (count % audioInterval) == 0) {
            owner.getEventManager().queueActiveTest(EventType.AUDIO_TEST, 2);
            //tasks.add(new Runnable() {
            //    @Override public void run() {
            //        owner.triggerActiveTest(2, EventType.AUDIO_TEST.getIntValue()); }});
        }
        count += 1;
        LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "runTrackingTests", "count=" + count);

    }

    // Queue a series of tests with delays, then detect when they complete, and repeat them again
    public void runAdvancedTrackingTests() {
        if ((durMinutes > 0 && trackingElapsed >= durMinutes * 60) || bTracking == false)
            return;
        if (testTrigger.equals("travel") && !owner.getTravelDetector().isTravelling()) {
            owner.getEventManager().stopTracking();
            return;
        }

        count += 1;

        try {
            advancedWaiting = false;
            JSONObject command = scheduledCommands.getJSONObject(advancedIndex);
            String cmdtype = command.getString("mmctype");
            int loop = command.getInt("loop");

            LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "runAdvancedTrackingTests",
                    "cmdtype=" + cmdtype + " loop=" + loop);

            if (cmdtype.equals("speed"))
                owner.getEventManager().queueActiveTest(EventType.MAN_SPEEDTEST, 2);
            else if (cmdtype.equals("latency"))
                owner.getEventManager().queueActiveTest(EventType.LATENCY_TEST, 2);
            else if (cmdtype.equals("smstest"))
                owner.getEventManager().queueActiveTest(EventType.SMS_TEST, 2);
            else if (cmdtype.equals("web"))
                owner.getEventManager().queueActiveTest(EventType.WEBPAGE_TEST, 2);
            else if (cmdtype.equals("youtube"))
                owner.getEventManager().queueActiveTest(EventType.YOUTUBE_TEST, 2);
            else if (cmdtype.equals("vq"))
                owner.getEventManager().queueActiveTest(EventType.EVT_VQ_CALL, 2);
            else if (cmdtype.equals("video"))
                owner.getEventManager().queueActiveTest(EventType.VIDEO_TEST, 2);
            else if (cmdtype.equals("audio"))
                owner.getEventManager().queueActiveTest(EventType.AUDIO_TEST, 2);
            else if (cmdtype.equals("predelay")) // in case a pre-delay doesn't follow a test, treat as a post delay
                cmdtype = "postdelay";
            else if (cmdtype.equals("cov")) // in case a pre-delay doesn't follow a test, treat as a post delay
            {
                cmdtype = "predelay";
                loop = 300;
            } else if (!cmdtype.equals("postdelay")) // unrecognized command
            {
                cmdtype = "postdelay";
                loop = 1;
            }

            if (cmdtype.equals("postdelay")) {
                handler.postDelayed(new Runnable() {
                    public void run() {
                        runAdvancedTrackingTests();
                    }
                }, (int) (1000 * loop));
            } else {
                // check for pre-delay in next index
                int nextIndex = (advancedIndex + 1) % scheduledCommands.length();
                command = scheduledCommands.getJSONObject(nextIndex);
                cmdtype = command.getString("mmctype");
                loop = command.getInt("loop");
                if (cmdtype.equals("predelay")) {
                    advancedIndex = (advancedIndex + 1) % scheduledCommands.length();
                    handler.postDelayed(new Runnable() {
                        public void run() {
                            runAdvancedTrackingTests();
                        }
                    }, (int) (1000 * loop));
                } else if (cmdtype.equals("postdelay")) {
                    // wait for the test queue to complete
                    advancedWaiting = true;

                } else {
                    // wait for the test queue to complete
                    advancedWaiting = true;
                }
            }
            advancedIndex = (advancedIndex + 1) % scheduledCommands.length();

        } catch (Exception e) {
            LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "startTracking", "start:Exception", e);
        }
    }

    private long prevTrackingTime = 0;

    public void runTracking() {

        if (testTrigger.equals("travel") && !owner.getTravelDetector().isTravelling()) {
            owner.getEventManager().stopTracking();
            return;
        }

        LoggerUtil.logToFile(LoggerUtil.Level.DEBUG, TAG, "runTracking", "covInterval=" + coverageInterval
                + ",speedInterval=" + speedtestInterval + ",count=" + count + ",videoInterval=" + videoInterval);
        if (prevTrackingTime > 0) {
            trackingElapsed += (System.currentTimeMillis() - prevTrackingTime + 500) / 1000;
            PreferenceManager.getDefaultSharedPreferences(owner).edit()
                    .putInt(PreferenceKeys.Miscellaneous.TRACKING_ELAPSED, trackingElapsed).commit();
        }
        prevTrackingTime = System.currentTimeMillis();

        if (durMinutes > 0 && trackingElapsed >= (durMinutes) * 60) {
            cancelScheduledEvents();
        } else if (coverageInterval > 0) {
            owner.getEventManager().triggerSingletonEvent(EventType.MAN_TRACKING);
        }
    }

}