private void doStartHAR() {
    // On har-start, load indices
    staticIPS.tryLoad(new File(getFilesDir(), PPSOptions.HELSINKIIPPS_INDEX_FILE));

    isHAR = true;
    connectorThread.addConsumer(waitingPipeline);
    connectorThread.addConsumer(ppsPipeline);
    connectorThread.addConsumer(harPipeline);
  }
  private void doStopHAR() {
    connectorThread.removeConsumer(harPipeline);
    connectorThread.removeConsumer(ppsPipeline);
    connectorThread.removeConsumer(waitingPipeline);

    isHAR = false;

    // On har-stop, save indices
    staticIPS.trySave(new File(getFilesDir(), PPSOptions.HELSINKIIPPS_INDEX_FILE));
  }
  private void doEnableRecording() {
    connectorThread.addConsumer(persistor);
    isRecording = true;

    final Tag tagStartRecording =
        new Tag(
            System.currentTimeMillis(), GlobalContext.getUserId(), IntentAPI.VALUE_START_RECORDING);

    persistor.push(tagStartRecording);

    // API EXTENSIONS are triggered on together with recording
    if (API_EXTENSIONS) {
      publisher.push(tagStartRecording);
      connectorThread.addConsumer(publisher);
      connectorThread.addConsumer(gpsCache);
    }
  }
  private void doDisableRecording() {
    connectorThread.removeConsumer(persistor);
    isRecording = false;

    final Tag stopRecordingTag =
        new Tag(
            System.currentTimeMillis(), GlobalContext.getUserId(), IntentAPI.VALUE_STOP_RECORDING);

    persistor.push(stopRecordingTag);

    // API EXTENSIONS are triggered on together with recording
    if (API_EXTENSIONS) {
      // Add "STOP RECORDING TAG" to publisher
      publisher.push(stopRecordingTag);
      connectorThread.removeConsumer(publisher);
      connectorThread.removeConsumer(gpsCache);
    }
  }
 private void doStartStreaming() {
   isStreaming = true;
   connectorThread.addConsumer(streamer);
 }
 private void doStopStreaming() {
   isStreaming = false;
   connectorThread.removeConsumer(streamer);
 }
  /* ANDROID LIFECYCLE */
  @Override
  public void onCreate() {
    super.onCreate();
    LogPrincipal.configure();
    log.info("Creating ServiceSensorControl");

    // INITIALIZATIONS
    // Warning: getFilesDir is only available after onCreate was called.
    File sensorFile = new File(GlobalContext.getFileRoot(), SENSOR_FILENAME);
    File stageFile = new File(GlobalContext.getFileRoot(), STAGE_FILENAME);

    // Init index
    staticIPS =
        new StaticIPS(
            PPSOptions.INDEX_HORIZONTAL_RESOLUTION,
            PPSOptions.INDEX_VERTICAL_RESOLUTION,
            PPSOptions.INDEX_BY_CENTROID,
            PPSOptions.INDEX_STORE_DEGREE,
            new Callable<InputStream>() {
              @Override
              public InputStream call() throws IOException {
                return getAssets().open(PPSOptions.HELSINKIIPPS_ASSET);
              }
            },
            false,
            PPSOptions.HELSINKI_ID_FIELD,
            PPSOptions.HELSINKI_LAT_FIELD,
            PPSOptions.HELSINKI_LON_FIELD,
            PPSOptions.PROXIMITY);

    // Init sensor consumers
    final ZMQStreamer zmqStreamer = new ZMQStreamer();
    streamer = zmqStreamer.itemNode;

    harPipeline = new HARAdapter();
    ppsPipeline = new PPSAdapter("platform", staticIPS);
    waitingPipeline = new WaitingAdapter("platform", WaitingOptions.WAITING_TRESHOLD);
    gpsCache = new GpsCache();
    publisher = new PublicationPipeline(); // for external communication

    // Serialization used for persisting items
    Function<Item, String> persistorSerialization =
        JSON_PERSISTOR ? Persistor.JSON_SERIALIZATION : Persistor.REGULAR_SERIALIZATION;

    // Persistor taking and storing the items
    persistor =
        ZIPPED_PERSISTOR
            ? new ZipFilePersistor(sensorFile, persistorSerialization)
            : new FilePersistor(sensorFile, persistorSerialization);

    // INIT THREADS
    connectorThread = new ConnectorThread(sensorQueue);
    transferManager =
        INTENT_TRANSFER
            ? new IntentTransfer(persistor, GlobalContext.getFileRoot())
            : new TransferThreadPost(persistor, stageFile);
    monitorThread = new MonitorThread();

    // Restore user id from shared preferences
    restoreUserId();

    // Setup sensor thread
    SensorThread.setup(sensorQueue);

    final int recordingNotificationId = 1;

    // Start Recording once the first consumers connects to connector thread.
    // This should be done once the SensorThread is already running.
    connectorThread.nonEmpty.register(
        new Callback<Consumer<? super Item>>() {
          @Override
          public void call(Consumer<? super Item> consumer) {
            log.debug("Start recording sensors, configuration " + SensorCollectionOptions.con());

            // Notification
            NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            Notification notification =
                new NotificationCompat.Builder(ServiceSensorControl.this)
                    .setContentTitle("Sensor miner")
                    .setContentText("Recording sensor data")
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setLights(0xff0000ff, 900, 900)
                    .setOngoing(true)
                    .setProgress(0, 0, true)
                    .build();

            notificationManager.notify(recordingNotificationId, notification);

            SensorThread.startAllRecording();
          }
        });
    connectorThread.empty.register(
        new Callback<Consumer<? super Item>>() {
          @Override
          public void call(Consumer<? super Item> consumer) {
            log.debug("Stop recording sensors");

            NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel(recordingNotificationId);

            SensorThread.stopAllRecording();
          }
        });

    // Setup monitoring thread
    monitorThread.registerMonitorable(connectorThread, "SampleCount");
    monitorThread.registerMonitorable(persistor, "Persitor");
    monitorThread.registerMonitorable(transferManager, "Transfer");
    monitorThread.registerMonitorable(sensorQueue, "Queue");

    // Start threads
    connectorThread.start();
    monitorThread.start();
    SensorThread.start();
  }