private void startSensors() {
   Logger.d(this, "startSensors");
   // Clock.
   mSessionStartTimeMillis = SystemClock.elapsedRealtime();
   Preferences.storeStartTime(this, mSessionStartTimeMillis);
   // Sensors.
   registerSensors();
   if (mListener != null) {
     mListener.onSensorStart(mSessionStartTimeMillis);
   }
 }
 private void stopSensors() {
   Logger.d(this, "stopSensors");
   // Store data.
   saveSessionData();
   // Clear state.
   Preferences.clearStoredValues(this);
   mSessionStartTimeMillis = Integer.MIN_VALUE;
   mSessionInitialSteps = Integer.MIN_VALUE;
   mSensorInfo = null;
   // Sensors.
   unregisterSensors();
   if (mListener != null) {
     mListener.onSensorStop();
   }
 }
 @Override
 public void onSensorChanged(@NonNull SensorEvent event) {
   if (mSensorInfo == null) {
     return;
   }
   switch (event.sensor.getType()) {
     case Sensor.TYPE_STEP_COUNTER:
       final long totalSteps = (long) event.values[0];
       if (mSessionInitialSteps == Integer.MIN_VALUE) {
         mSessionInitialSteps = totalSteps;
         Preferences.storeSensorInitialStepCount(this, mSessionInitialSteps);
       }
       mSensorInfo.setSteps(totalSteps - mSessionInitialSteps);
       Logger.d(this, "Step count: " + mSensorInfo.getSteps());
       break;
     case Sensor.TYPE_LINEAR_ACCELERATION:
       final float x = event.values[0];
       final float y = event.values[1];
       final float z = event.values[2];
       //noinspection SuspiciousNameCombination
       final double totalAcc = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
       float filteredAcc = filterAcceleration((float) totalAcc);
       SensorInfo.ActivityType activityType = SensorInfo.ActivityType.STILL;
       if (filteredAcc < WALKING_THRESHOLD) {
         Logger.d(this, "Still: " + filteredAcc);
         activityType = SensorInfo.ActivityType.STILL;
       } else if (filteredAcc > WALKING_THRESHOLD && filteredAcc < RUNNING_THRESHOLD) {
         Logger.d(this, "Walking: " + filteredAcc);
         activityType = SensorInfo.ActivityType.WALKING;
       } else if (filteredAcc > RUNNING_THRESHOLD) {
         Logger.d(this, "Running: " + filteredAcc);
         activityType = SensorInfo.ActivityType.RUNNING;
       }
       if (!activityType.equals(mSensorInfo.getActivityType())) {
         mSensorInfo.setActivityType(activityType);
       }
       break;
     default:
   }
   if (mListener != null) {
     mListener.onSensorUpdate(mSensorInfo);
   }
 }
 private void registerSensors() {
   final SensorManager sensorManager = getSensorManager();
   if (sensorManager != null) {
     mSensorInfo = new SensorInfo();
     final Sensor stepSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
     if (stepSensor != null) {
       mSessionInitialSteps = Preferences.retrieveSensorInitialStepCount(this);
       sensorManager.registerListener(this, stepSensor, SensorManager.SENSOR_DELAY_NORMAL);
     }
     final Sensor linearAccelerationSensor =
         sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
     if (linearAccelerationSensor != null) {
       // Init filters.
       mKalmanFilters[0] = new ScalarKalmanFilter();
       mKalmanFilters[1] = new ScalarKalmanFilter();
       mKalmanFilters[2] = new ScalarKalmanFilter();
       sensorManager.registerListener(
           this, linearAccelerationSensor, SensorManager.SENSOR_DELAY_NORMAL);
     }
   }
 }
 @Override
 public void onDestroy() {
   Logger.d(this, "onDestroy");
   Preferences.clearStoredValues(this);
 }
 private void restoreServiceState() {
   mSessionStartTimeMillis = Preferences.retrieveStoredStartTime(this);
   mSessionInitialSteps = Preferences.retrieveSensorInitialStepCount(this);
 }