/**
   * Creates the {@link ContentValues} for a {@link Location}.
   *
   * @param location the location
   * @param trackId the track id
   */
  private ContentValues createContentValues(Location location, long trackId) {
    ContentValues values = new ContentValues();
    values.put(TrackPointsColumns.TRACKID, trackId);
    values.put(TrackPointsColumns.LONGITUDE, (int) (location.getLongitude() * 1E6));
    values.put(TrackPointsColumns.LATITUDE, (int) (location.getLatitude() * 1E6));

    // Hack for Samsung phones that don't properly populate the time field
    long time = location.getTime();
    if (time == 0) {
      time = System.currentTimeMillis();
    }
    values.put(TrackPointsColumns.TIME, time);
    if (location.hasAltitude()) {
      values.put(TrackPointsColumns.ALTITUDE, location.getAltitude());
    }
    if (location.hasAccuracy()) {
      values.put(TrackPointsColumns.ACCURACY, location.getAccuracy());
    }
    if (location.hasSpeed()) {
      values.put(TrackPointsColumns.SPEED, location.getSpeed());
    }
    if (location.hasBearing()) {
      values.put(TrackPointsColumns.BEARING, location.getBearing());
    }

    if (location instanceof MyTracksLocation) {
      MyTracksLocation myTracksLocation = (MyTracksLocation) location;
      if (myTracksLocation.getSensorDataSet() != null) {
        values.put(TrackPointsColumns.SENSOR, myTracksLocation.getSensorDataSet().toByteArray());
      }
    }
    return values;
  }
  /**
   * Fills a track point from a cursor.
   *
   * @param cursor the cursor pointing to a location.
   * @param indexes the cached track points indexes
   * @param location the track point
   */
  private void fillTrackPoint(Cursor cursor, CachedTrackPointsIndexes indexes, Location location) {
    location.reset();

    if (!cursor.isNull(indexes.longitudeIndex)) {
      location.setLongitude(((double) cursor.getInt(indexes.longitudeIndex)) / 1E6);
    }
    if (!cursor.isNull(indexes.latitudeIndex)) {
      location.setLatitude(((double) cursor.getInt(indexes.latitudeIndex)) / 1E6);
    }
    if (!cursor.isNull(indexes.timeIndex)) {
      location.setTime(cursor.getLong(indexes.timeIndex));
    }
    if (!cursor.isNull(indexes.altitudeIndex)) {
      location.setAltitude(cursor.getFloat(indexes.altitudeIndex));
    }
    if (!cursor.isNull(indexes.accuracyIndex)) {
      location.setAccuracy(cursor.getFloat(indexes.accuracyIndex));
    }
    if (!cursor.isNull(indexes.speedIndex)) {
      location.setSpeed(cursor.getFloat(indexes.speedIndex));
    }
    if (!cursor.isNull(indexes.bearingIndex)) {
      location.setBearing(cursor.getFloat(indexes.bearingIndex));
    }
    if (location instanceof MyTracksLocation && !cursor.isNull(indexes.sensorIndex)) {
      MyTracksLocation myTracksLocation = (MyTracksLocation) location;
      try {
        myTracksLocation.setSensorDataSet(
            SensorDataSet.parseFrom(cursor.getBlob(indexes.sensorIndex)));
      } catch (InvalidProtocolBufferException e) {
        Log.w(TAG, "Failed to parse sensor data.", e);
      }
    }
  }