@Override
  public int onStartCommand(Intent intent, int flags, int startId) {

    startAsForeground();
    networkErrorCount = 0;
    retry = true;

    currentDate = new Date();
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss");
    internalCounter = 0;

    if (!isThreadRunning) // thread is not running so start the thread
    {

      counter = 0;
      Log.d(Settings.TAG, "Stats extraction process started.");

      try {
        handler.postDelayed(
            runnable =
                new Runnable() {

                  @Override
                  public void run() {
                    List<Stats> diff = null;
                    try {
                      if (isForeground) {

                        if (android.os.Build.VERSION.SDK_INT
                            <= 19) // below lollipop we need to remove the notification by stop
                                   // foreground and restart the notification
                        {
                          stopForeground(true);
                          updateNotification();
                        } else {
                          stopForeground(false);
                        }
                        isForeground = false;
                      }
                    } catch (Exception ex) {
                      Log.d(Settings.TAG, "Error occurred while stop foreground");
                    }

                    if (compare(currentDate, new Date())
                        != 0) { // this code generates the hash code every midnight.s
                      currentDate = new Date();
                      Log.d(Settings.TAG, "Generating hash code..Date changed");
                      HashGen hashGen = new HashGen();
                      hashGen.getAllAppInfo(context); // creates hashcode file for every app
                    }

                    // scheduler for uploading hashcode
                    File file = new File(Settings.getHashFilePath());

                    boolean isExist = file.exists();
                    // boolean isWifiAvailable = NET.isWifiAvailable(context);

                    // if hash file exist upload it to server..
                    if (isExist
                        && HashFileUploader.isUploading == false
                        && Settings.IS_WIFI_AVAILABLE
                        && HashGen.isGenerating
                            == false) { // if there is hash file available and wifi is on upload the
                                        // file and delete it.
                      HashFileUploader hfUploader = new HashFileUploader(context);
                      hfUploader
                          .execute(); // this method uploads the hash file to server and delete the
                                      // file from device.
                    }

                    isExist = file.exists(); // make sure file does not exist.

                    Log.d("bu-stats", "Upload Size:" + Settings.UploadSize);
                    Log.d("bu-stats", "isUploading:" + FileUploader.isUploading);
                    Log.d("bu-stats", "IS_WIFI_AVAILABLE:" + Settings.IS_WIFI_AVAILABLE);
                    Log.d("bu-stats", "isExist:" + isExist);
                    Log.d("bu-stats", "IsGenerating Hash Code: " + HashGen.isGenerating);

                    // if hash file is uploaded and does not exist and wifi is available and hash
                    // generation process is not working and uploading of stats file is not working
                    // and current file size has surpass the threshold then upload it.
                    if (StatsFileManager.getFileSize(context) >= Settings.UploadSize
                        && FileUploader.isUploading == false
                        && Settings.IS_WIFI_AVAILABLE
                        && isExist == false
                        && HashGen.isGenerating
                            == false) // if hash file exist, info is not uploaded yet. So wait for
                                      // this file to upload before uploading stats.
                    {
                      Log.d("bu-stats", "Uploading File.");
                      FileUploader fileUploader = new FileUploader(context);
                      fileUploader.execute();
                    }

                    // Log.d("test-test", "FileUploader.IsUploading = " + FileUploader.isUploading);
                    if (!FileUploader
                        .isUploading) // if file is not uploading. (file is not in use) then
                                      // calculate the stats and store it in database.
                    {
                      String data = "";
                      // List<Stats> stepDownStats = null;
                      if (internalCounter == 0) // get the stats for the first time.
                      {
                        oldStats = Stats.getStats(context);
                      } else if (internalCounter > Settings.NetInterval) {
                        newStats = Stats.getStats(context);
                        if (newStats == null || oldStats == null) {
                          // can't read network proc file.
                          Log.e(Settings.TAG, "Unable to read network file. Stopping process");
                        }
                        diff = Stats.NETDifference(oldStats, newStats);

                        /*                                Log.d(Settings.TAG,"New Data..--------------------");
                        for(Stats st: newStats)
                        {
                            Log.d(Settings.TAG, st.getStringData());
                        }*/

                        oldStats = newStats;
                        try {
                          startAsForeground();
                        } catch (Exception ex) {
                          Log.d(Settings.TAG, "Error occurred while starting foreground");
                        }

                        boolean error = false;

                        String networkType = getNetworkType();
                        for (Stats stats : diff) {
                          if (stats.NetStats.error) {
                            error = true;
                          }

                          data = data + stats.getStringData() + "|" + networkType + "\n";
                        }
                        //    Log.d(Settings.TAG,"data without
                        // difference...++++++++++++++++++++++++++++++++++++++++++++++");
                        //  Log.d(Settings.TAG,data);
                        if (error) {
                          networkErrorCount++;
                          // retry for network file...but skip this malformed data...

                          if (networkErrorCount >= 3) {
                            retry = false;
                            forceStop = true;
                            ShowMessage.message("Malformed data. Need to restart phone.", context);
                            Log.d(Settings.TAG, "Malformed network file");
                            Notify.showNotification(
                                context,
                                "Malformed data in system file. Please restart the device to clean the file.");
                            isThreadRunning = false;
                            sendMessage();
                            stop_request = true;
                            onDestroy();
                            return;
                          } else retry = true;
                        } else {
                          networkErrorCount = 0;
                        }

                        internalCounter = 1;
                        // stepDownStats = newStats;
                        Log.d(
                            Settings.TAG,
                            "data with network...++++++++++++++++++++++++++++++++++++++");
                        Log.d(Settings.TAG, data);
                        if (retry) new StatsFileManager(context).SaveStats(data);

                      } else {
                        List<Stats> statsWithoutNet = Stats.getStatsWithoutNetowrk(context);

                        String networkType = getNetworkType();
                        for (Stats stats : statsWithoutNet)
                          data = data + stats.getStringData() + "|" + networkType + "\n";
                        // stepDownStats = statsWithoutNet;
                        // Log.d(Settings.TAG,"Data without
                        // netowrk-------------------------------------------");
                        // Log.d(Settings.TAG, data);
                        new StatsFileManager(context).SaveStats(data);
                      }
                      // Log.d("stats-result", "Internal counter: " + internalCounter);
                      internalCounter++;
                      /*


                                                 //Step-down for changing interval begins here;.,..


                                                  boolean isActive= StepDownExtraction.isDeviceActive(context);
                                                  boolean checkNetworkStepdown=false;
                                                  if(!isActive && stepDownStats!=null)
                                                  {
                                                      StepDownExtraction tempStepDown =new StepDownExtraction(stepDownStats);
                                                      if(tempStepDown.cpuTotal >0)
                                                      {
                                                          Settings.interval=Settings.minInterval;
                                                          StepDownExtraction.count=0;
                                                          Log.d(Settings.TAG,"CPU: "+ tempStepDown.cpuTotal);
                                                      }
                                                      else
                                                      {
                                                          StepDownExtraction.count++;
                                                          checkNetworkStepdown=true;
                                                      }
                                                  }
                                                  Log.d(Settings.TAG,"Count: "+StepDownExtraction.count + "  \t Threshold: "+StepDownExtraction.threshold);


                                                  if (!isActive && diff != null && StepDownExtraction.count >= Settings.NetInterval)  //initialize if screen is off or not.)  //device sleeping.  Start step down approach
                                                  {
                                                      StepDownExtraction stepDownExtraction = new StepDownExtraction(diff);
                                                      int totalCpu = stepDownExtraction.cpuTotal;
                                                      int networkUsage=stepDownExtraction.totalNetwork;
                                                      Log.d(Settings.TAG,"Netowork : "+  networkUsage);
                                                      if (totalCpu <= 0 && networkUsage<=0)  //if CPU and memory is not in use then increase the interval;
                                                      {
                                                          Log.d(Settings.TAG,"Going into step down mode");

                                                          StepDownExtraction.count++;
                                                          Log.d(Settings.TAG,"Count: "+StepDownExtraction.count);
                                                          Log.d(Settings.TAG,"threshold: "+StepDownExtraction.threshold);
                                                          if (true)  //cpu was 0 for n (threshold) times. increase the delay
                                                          {
                                                              Log.d(Settings.TAG,"Went to step down");

                                                              if ((Settings.interval * 2) <= Settings.maxInterval)
                                                                  Settings.interval += Settings.interval;
                                                              else
                                                                  Settings.interval = Settings.maxInterval; //set it to max
                                                          }
                                                      }
                                                      else
                                                      {
                                                          Log.d(Settings.TAG, "both are not zero reseting counter");
                                                          Settings.interval = Settings.minInterval;
                                                          StepDownExtraction.count = 0;                             //reset the counter

                                                      }
                                                      Log.d(Settings.TAG,"Interval: "+Settings.interval);
                                                      //Log.d("step-down", "Device sleeping. Interval: " + Settings.interval + " CPU: " + totalCpu);
                                                  }
                                                  else if(isActive)       //device is awake set default interval...
                                                  {
                                                      Log.d(Settings.TAG, "awake reseting counter");
                                                      StepDownExtraction.count = 0;                             //reset the counter
                                                      Settings.interval = Settings.minInterval;//set default interval
                                                  }
                                                  //step down ends here...
                      */
                    }
                    counter++;
                    handler.postDelayed(this, Settings.getInterval() * 1000);
                  }
                },
            Settings.getInterval() * 1000);

      } catch (Exception ex) {
        Log.d(Settings.TAG, "Error occured in stats collector thread. " + ex.toString());
        Notify.showNotification(context, "Error occurred while collecting data.");
      }
    }
    isThreadRunning = !isThreadRunning;

    if (stop_request) return START_NOT_STICKY;
    else return START_STICKY;
  }