/**
  * The call() method that broadcast intents before the measurement starts and after the
  * measurement finishes.
  */
 @Override
 public MeasurementResult[] call() throws MeasurementError {
   MeasurementResult[] results = null;
   PhoneUtils phoneUtils = PhoneUtils.getPhoneUtils();
   try {
     phoneUtils.acquireWakeLock();
     broadcastMeasurementStart();
     contextCollector.setInterval(realTask.getDescription().contextIntervalSec);
     contextCollector.startCollector();
     results = realTask.call();
     ArrayList<HashMap<String, String>> contextResults = contextCollector.stopCollector();
     for (MeasurementResult r : results) {
       r.addContextResults(contextResults);
       r.getDeviceProperty().dnResolvability = contextCollector.dnsConnectivity;
       r.getDeviceProperty().ipConnectivity = contextCollector.ipConnectivity;
     }
   } catch (MeasurementError e) {
     Logger.e("User measurement " + realTask.getDescriptor() + " has failed");
     Logger.e(e.getMessage());
     results = MeasurementResult.getFailureResult(realTask, e);
   } catch (Exception e) {
     Logger.e("User measurement " + realTask.getDescriptor() + " has failed");
     Logger.e("Unexpected Exception: " + e.getMessage());
     results = MeasurementResult.getFailureResult(realTask, e);
   } finally {
     broadcastMeasurementEnd(results);
     MeasurementTask currentTask = scheduler.getCurrentTask();
     if (currentTask != null && currentTask.equals(realTask)) {
       scheduler.setCurrentTask(null);
     }
     phoneUtils.releaseWakeLock();
   }
   return results;
 }
 private MeasurementResult getFailureResult(MeasurementTask task, Throwable error) {
   MeasurementResult result =
       new MeasurementResult(
           phoneUtils.getDeviceInfo().deviceId,
           phoneUtils.getDeviceProperty(),
           task.getType(),
           System.currentTimeMillis() * 1000,
           false,
           task.measurementDesc);
   result.addResult("error", error.toString() + "\n" + getStackTrace(error));
   return result;
 }
    private void broadcastMeasurementEnd(MeasurementResult result) {
      Intent intent = new Intent();
      intent.setAction(UpdateIntent.MEASUREMENT_PROGRESS_UPDATE_ACTION);
      intent.putExtra(UpdateIntent.TASK_PRIORITY_PAYLOAD, MeasurementTask.USER_PRIORITY);
      // A progress value greater than max progress to indicate the termination of a measurement
      intent.putExtra(UpdateIntent.PROGRESS_PAYLOAD, Config.MEASUREMENT_END_PROGRESS);

      if (result != null) {
        intent.putExtra(UpdateIntent.STRING_PAYLOAD, result.toString());
      } else {
        String errorString = "Measurement " + realTask.getDescriptor() + " has failed";
        errorString += "\nTimestamp: " + Calendar.getInstance().getTime();
        intent.putExtra(UpdateIntent.ERROR_STRING_PAYLOAD, errorString);
      }
      MeasurementScheduler.this.sendBroadcast(intent);
      // Update the status bar once the user measurement finishes
      updateStatus();
    }