Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,16 @@ public SQLiteDatabase getWriteDB() {
return getDBHelper().getWritableDatabase();
}

@Override
public void onLowMemory() {
GTFSRealTimeTripUpdatesProvider.onLowMemory();
}

@Override
public void onTrimMemory(int level) {
GTFSRealTimeTripUpdatesProvider.onTrimMemory(level);
}

@Nullable
@Override
public Cursor queryMT(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ object GtfsRealtimeExt {
private const val MAX_LIST_ITEMS: Int = 5

@JvmStatic
fun List<GTSTranslation>.filterUseless(): List<GTSTranslation> {
return if (this.size <= 1) {
this
} else {
this.filterNot { it.text.isNullOrBlank() }
}
fun List<GTSTranslation>.filterUseless() = when {
this.size <= 1 -> this
else -> this.filterNot { it.text.isNullOrBlank() }
}

@JvmStatic
Expand Down Expand Up @@ -74,7 +71,7 @@ object GtfsRealtimeExt {
val GtfsRealtime.FeedHeader.optGtfsRealtimeVersion get() = if (hasGtfsRealtimeVersion()) gtfsRealtimeVersion else null

@JvmStatic
fun GFeedEntity.toStringExt(debug: Boolean = Constants.DEBUG) = buildString {
fun GFeedEntity.toStringExt(debug: Boolean = Constants.DEBUG): String = buildString {
append("FeedEntity:")
append(
buildList {
Expand All @@ -89,7 +86,7 @@ object GtfsRealtimeExt {
@JvmName("toStringExtFeedEntity")
@JvmStatic
@JvmOverloads
fun List<GFeedEntity>?.toStringExt(short: Boolean = false, debug: Boolean = Constants.DEBUG): String = buildString {
fun List<GFeedEntity>?.toStringExt(short: Boolean = false, debug: Boolean = Constants.DEBUG) = buildString {
append(if (short) "FEs[" else "FeedEntity[").append(this@toStringExt?.size ?: 0).append("]")
if (debug) {
this@toStringExt?.take(MAX_LIST_ITEMS)?.forEachIndexed { idx, feedEntity ->
Expand All @@ -108,11 +105,11 @@ object GtfsRealtimeExt {
this.filter { it.hasTripUpdate() }.map { it.tripUpdate to it.id }.distinctBy { it.first }

@JvmStatic
fun List<GTripUpdate>.sortTripUpdates(nowMs: Long = TimeUtils.currentTimeMillis()): List<GTripUpdate> =
fun List<GTripUpdate>.sortTripUpdates(): List<GTripUpdate> =
this.sortedBy { it.timestamp }

@JvmStatic
fun List<Pair<GTripUpdate, String>>.sortTripUpdatesPair(nowMs: Long = TimeUtils.currentTimeMillis()): List<Pair<GTripUpdate, String>> =
fun List<Pair<GTripUpdate, String>>.sortTripUpdatesPair(): List<Pair<GTripUpdate, String>> =
this.sortedBy { (it, _) -> it.timestamp }

@JvmStatic
Expand All @@ -124,11 +121,11 @@ object GtfsRealtimeExt {
this.filter { it.hasVehicle() }.map { it.vehicle to it.id }.distinctBy { it.first }

@JvmStatic
fun List<GVehiclePosition>.sortVehicles(nowMs: Long = TimeUtils.currentTimeMillis()): List<GVehiclePosition> =
fun List<GVehiclePosition>.sortVehicles(): List<GVehiclePosition> =
this.sortedBy { it.timestamp }

@JvmStatic
fun List<Pair<GVehiclePosition, String>>.sortVehiclesPair(nowMs: Long = TimeUtils.currentTimeMillis()): List<Pair<GVehiclePosition, String>> =
fun List<Pair<GVehiclePosition, String>>.sortVehiclesPair(): List<Pair<GVehiclePosition, String>> =
this.sortedBy { (vehiclePosition, _) -> vehiclePosition.timestamp }

@JvmStatic
Expand Down Expand Up @@ -311,7 +308,7 @@ object GtfsRealtimeExt {

@JvmStatic
@JvmOverloads
fun GVehiclePosition.toStringExt(debug: Boolean = Constants.DEBUG) = buildString {
fun GVehiclePosition.toStringExt(debug: Boolean = Constants.DEBUG): String = buildString {
append("VehiclePosition:")
append(
buildList {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.mtransit.android.commons.provider.status

import android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
import android.content.Context
import android.util.Log
import org.mtransit.android.commons.Constants
Expand Down Expand Up @@ -38,6 +39,7 @@ import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
import com.google.transit.realtime.GtfsRealtime.FeedMessage as GFeedMessage
import com.google.transit.realtime.GtfsRealtime.TripUpdate as GTripUpdate

object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {

Expand Down Expand Up @@ -98,8 +100,8 @@ object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {
tripIds: List<String>
): POIStatus? {
val context = context ?: return null
if (!File(context.cacheDir, GTFS_RT_TRIP_UPDATE_PB_FILE_NAME).exists()) return null
if (GtfsRealTimeStorage.getTripUpdateLastUpdateMs(context, 0L) <= 0L) return null // never loaded
gTripUpdates ?: return null
synchronized(tripUpdateLock.getOrPut(filter.routeDirectionStop.routeDirectionUUID) { Any() }) {
return getCachedStatusS(filter.targetUUID, tripIds) // try another time
?: makeCachedStatusFromAgencyData(filter, tripIds)
Expand All @@ -113,10 +115,9 @@ object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {
tripIds: List<String>
): POIStatus? {
val context = context ?: return null
val gtfsRealTimeTripUpdateFile = File(context.cacheDir, GTFS_RT_TRIP_UPDATE_PB_FILE_NAME)
if (!gtfsRealTimeTripUpdateFile.exists()) return null
val readFromSourceMs = GtfsRealTimeStorage.getTripUpdateLastUpdateMs(context, 0L)
if (readFromSourceMs <= 0L) return null // never loaded
.takeIf { it > 0L } ?: return null // never loaded
val gTripUpdates = gTripUpdates ?: return null
val sourceLabel = SourceUtils.getSourceLabel( // always use source from official API
GTFSRealTimeProvider.getAgencyTripUpdatesUrlString(context, "T")
)
Expand All @@ -125,8 +126,6 @@ object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {
val targetAuthority = rds.authority
val routeId = rds.route.id
val directionId = rds.direction.id
val gFeedMessage = GFeedMessage.parseFrom(gtfsRealTimeTripUpdateFile.inputStream())
val gTripUpdates = gFeedMessage.entityList.toTripUpdates()
val rdTripUpdates = gTripUpdates
.mapNotNull { gTripUpdate ->
gTripUpdate.optTrip?.let { it to gTripUpdate }
Expand Down Expand Up @@ -230,12 +229,11 @@ object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {
if (lastUpdateInMs + minUpdateMs > TimeUtils.currentTimeMillis()) {
return
}
updateAgencyDataIfRequiredSync(lastUpdateInMs, inFocus)
updateAgencyDataIfRequiredSync(context, lastUpdateInMs, inFocus)
}

@Synchronized
private fun GTFSRealTimeProvider.updateAgencyDataIfRequiredSync(lastUpdateInMs: Long, inFocus: Boolean) {
val context = requireContextCompat()
private fun GTFSRealTimeProvider.updateAgencyDataIfRequiredSync(context: Context, lastUpdateInMs: Long, inFocus: Boolean) {
if (GtfsRealTimeStorage.getTripUpdateLastUpdateMs(context, 0L) > lastUpdateInMs) {
return // too late, another thread already updated
}
Expand Down Expand Up @@ -267,6 +265,51 @@ object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {

private const val GTFS_RT_TRIP_UPDATE_PB_FILE_NAME = "gtfs_rt_trip_update.pb"

@JvmStatic
fun onLowMemory() {
_gTripUpdates = null
}

@JvmStatic
fun onTrimMemory(level: Int) {
if (level >= TRIM_MEMORY_BACKGROUND) {
_gTripUpdates = null
}
}

@Volatile
private var _gTripUpdates: List<GTripUpdate>? = null

private var GTFSRealTimeProvider.gTripUpdates: List<GTripUpdate>?
get() {
if (_gTripUpdates == null) {
synchronized(this@GTFSRealTimeTripUpdatesProvider) {
if (_gTripUpdates != null) return@synchronized
_gTripUpdates = context?.let { context ->
File(context.cacheDir, GTFS_RT_TRIP_UPDATE_PB_FILE_NAME)
.takeIf { file -> file.exists() }
?.inputStream()
?.use { inputStream ->
try {
GFeedMessage.parseFrom(inputStream)
.entityList
.toTripUpdates()
} catch (e: IOException) {
MTLog.w(this@GTFSRealTimeTripUpdatesProvider, e, "gTripUpdates.get() > error while reading GTFS RT Trip Updates data!")
null
}
}
}
}
}
return _gTripUpdates
}
set(value) {
synchronized(this@GTFSRealTimeTripUpdatesProvider) {
_gTripUpdates = value
}
}

private const val PRINT_ALL_LOADED_TRIP_UPDATES = false
// private const val PRINT_ALL_LOADED_TRIP_UPDATES = true // DEBUG

Expand All @@ -286,12 +329,11 @@ object GTFSRealTimeTripUpdatesProvider : MTLog.Loggable {
try {
val responseBodyByes = response.body.bytes()
File(context.cacheDir, GTFS_RT_TRIP_UPDATE_PB_FILE_NAME).writeBytes(responseBodyByes)
gTripUpdates = GFeedMessage.parseFrom(responseBodyByes).entityList.toTripUpdates() // will be used soon
@Suppress("SimplifyBooleanWithConstants", "KotlinConstantConditions")
if (Constants.DEBUG && PRINT_ALL_LOADED_TRIP_UPDATES) {
val gFeedMessage = GFeedMessage.parseFrom(responseBodyByes)
val gTripUpdates = gFeedMessage.entityList.toTripUpdates()
MTLog.d(this@GTFSRealTimeTripUpdatesProvider, "loadAgencyDataFromWWW() > GTFS trip updates[${gTripUpdates.size}]: ")
gTripUpdates.sortTripUpdates(TimeUtils.currentTimeMillis()).forEach { gTripUpdate ->
MTLog.d(this@GTFSRealTimeTripUpdatesProvider, "loadAgencyDataFromWWW() > GTFS trip updates[${gTripUpdates?.size}]: ")
gTripUpdates?.sortTripUpdates()?.forEach { gTripUpdate ->
MTLog.d(this@GTFSRealTimeTripUpdatesProvider, "loadAgencyDataFromWWW() > - GTFS ${gTripUpdate.toStringExt()}")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ object GTFSRealTimeVehiclePositionsProvider {
if (Constants.DEBUG) {
MTLog.d(this@GTFSRealTimeVehiclePositionsProvider, "loadAgencyDataFromWWW() > GTFS vehicles[${gVehiclePositions.size}]: ")
}
for (gVehiclePosition in gVehiclePositions.sortVehicles(newLastUpdateInMs)) {
for (gVehiclePosition in gVehiclePositions.sortVehicles()) {
if (Constants.DEBUG) {
MTLog.d(this@GTFSRealTimeVehiclePositionsProvider, "loadAgencyDataFromWWW() > - GTFS ${gVehiclePosition.toStringExt()}.")
}
Expand Down